Compare commits

..

4 Commits

3 changed files with 83 additions and 18 deletions

View File

@ -79,6 +79,21 @@
- `早安` - `早安`
- `晚安` - `晚安`
</details>
<details>
<summary>点歌功能</summary>
- 使用[hifi公共音源库](https://github.com/sachinsenal0x64/hifi)提供服务,
- 由于音源位于海外,大陆连接下载音乐时可能遇到缓慢问题,考虑优化网络环境
- 由于海外音源,搜歌时考虑使用繁体中文,英文等进行搜索以处理搜索不到的情况
- 默认下载flac/CD无损级音乐,可在配置文件调整为mp3音质或直接通过语音发送
- ~~可以听周杰伦~~
- `#点歌晴天`
- `#听1`
- `#听夜曲`
> 直接#听+歌曲名可能播放错误的歌曲
</details> </details>
<details> <details>
<summary>晶灵智能✨</summary> <summary>晶灵智能✨</summary>
@ -142,7 +157,8 @@
"welcome": true, "welcome": true,
"faceReply": true, "faceReply": true,
"ai": true, "ai": true,
"blackWords": true "blackWords": true,
"music": true
} }
``` ```
</details> </details>
@ -215,6 +231,23 @@
} }
``` ```
</details> </details>
<details>
<summary>music.json</summary>
```
{
"?url": "api地址,不建议修改",
"url": "https://api.401658.xyz",
"?username&&password": "请勿修改",
"username": "crystelf",
"password": "1145141919810",
"?quality": "1为96kbpsAAC,2为320kbpsAAC,3为最高16-bit/44.1kHzflac",
"quality": "3"
}
```
</details>
<details> <details>
<summary>ai.json</summary> <summary>ai.json</summary>
@ -238,6 +271,10 @@
"maxSessions": 10, "maxSessions": 10,
"?chatHistory": "聊天上下文最大长度", "?chatHistory": "聊天上下文最大长度",
"chatHistory": 10, "chatHistory": 10,
"?maxMessageLength": "最大消息长度,如果消息长度大于这个值,超出的部分将会被截断",
"maxMessageLength": 100,
"?getChatHistoryLength": "获取到的聊天上下文长度,ai可以看到多少条群聊的聊天记录",
"getChatHistoryLength":20,
"?blockGroup": "禁用的群聊(黑名单)", "?blockGroup": "禁用的群聊(黑名单)",
"blockGroup": [], "blockGroup": [],
"?whiteGroup": "白名单群聊,存在该部分时,黑名单将被禁用", "?whiteGroup": "白名单群聊,存在该部分时,黑名单将被禁用",

View File

@ -25,11 +25,11 @@ export class CrystelfMusic extends plugin {
priority: -1000, priority: -1000,
rule: [ rule: [
{ {
reg: '^#?点歌\\s+(.+)$', reg: '^#?点歌\\s*(.+)$',
fnc: 'handleSearch' fnc: 'handleSearch'
}, },
{ {
reg: '^#?听\\s+(.+)$', reg: '^#?听\\s*(.+)',
fnc: 'handleDirectPlay' fnc: 'handleDirectPlay'
}, },
{ {
@ -46,14 +46,16 @@ export class CrystelfMusic extends plugin {
*/ */
async handleSearch(e) { async handleSearch(e) {
try { try {
if (!ConfigControl.get()?.config?.music) {
return;
}
const keyword = e.msg.replace(/^#?点歌\s*/, '').trim(); const keyword = e.msg.replace(/^#?点歌\s*/, '').trim();
if (!keyword) { if (!keyword) {
return await e.reply('请输入要点的歌名,例如:#点歌 夜曲'); return await e.reply('请输入要点的歌名,例如:#点歌夜曲');
} }
const adapter = await YunzaiUtils.getAdapter(e); const adapter = await YunzaiUtils.getAdapter(e);
await Message.emojiLike(e,e.message_id,60,e.group_id,adapter); await Message.emojiLike(e, e.message_id, 60, e.group_id, adapter);
const result = await musicSearch.handleSearch(e, keyword); const result = await musicSearch.handleSearch(e, keyword);
if (result.success) { if (result.success) {
await e.reply({ await e.reply({
type: 'image', type: 'image',
@ -62,7 +64,6 @@ export class CrystelfMusic extends plugin {
} else { } else {
await e.reply(`${result.message}`, true); await e.reply(`${result.message}`, true);
} }
} catch (error) { } catch (error) {
logger.error('[crystelf-music] 处理搜索失败:', error); logger.error('[crystelf-music] 处理搜索失败:', error);
await e.reply('搜索失败,请稍后重试', true); await e.reply('搜索失败,请稍后重试', true);
@ -75,18 +76,38 @@ export class CrystelfMusic extends plugin {
*/ */
async handleDirectPlay(e) { async handleDirectPlay(e) {
try { try {
const songName = e.msg.replace(/^#?听\s*/, '').trim(); if (!ConfigControl.get()?.config?.music) {
if (!songName) { return;
return await e.reply('请输入要听的歌名,例如:#听 夜曲', true); }
const content = e.msg.replace(/^#?听\s*/, '').trim();
if (!content) {
return await e.reply('请输入要听的歌名或序号,例如:#听 夜曲 或 #听 1', true);
}
const index = parseInt(content);
if (!isNaN(index) && index >= 1 && index <= 20) {
const searchResult = musicSearch.getGroupSearchResult(e.group_id);
if (!searchResult) {
return await e.reply('没有找到当前可选择的音乐列表,请先搜索歌曲', true);
} }
const adapter = await YunzaiUtils.getAdapter(e); const adapter = await YunzaiUtils.getAdapter(e);
await Message.emojiLike(e,e.message_id,60,e.group_id,adapter); await Message.emojiLike(e, e.message_id, 60, e.group_id, adapter);
const result = await musicSearch.handleDirectPlay(e, songName); const result = await musicSearch.handleSelection(e, index);
if (result.success) { if (result.success) {
await this.sendMusicResult(e, result); await this.sendMusicResult(e, result);
} else { } else {
await e.reply(`${result.message}`, true); await e.reply(`${result.message}`, true);
} }
} else {
const adapter = await YunzaiUtils.getAdapter(e);
await Message.emojiLike(e, e.message_id, 60, e.group_id, adapter);
const result = await musicSearch.handleDirectPlay(e, content);
if (result.success) {
await this.sendMusicResult(e, result);
} else {
await e.reply(`${result.message}`, true);
}
}
} catch (error) { } catch (error) {
logger.error('[crystelf-music] 处理直接播放失败:', error); logger.error('[crystelf-music] 处理直接播放失败:', error);
await e.reply('播放失败,请稍后重试', true); await e.reply('播放失败,请稍后重试', true);
@ -99,6 +120,9 @@ export class CrystelfMusic extends plugin {
*/ */
async handleIndexSelection(e) { async handleIndexSelection(e) {
try { try {
if (!ConfigControl.get()?.config?.music) {
return;
}
const index = parseInt(e.msg); const index = parseInt(e.msg);
if (isNaN(index) || index < 1 || index > 20) { if (isNaN(index) || index < 1 || index > 20) {
return; return;
@ -112,6 +136,7 @@ export class CrystelfMusic extends plugin {
const result = await musicSearch.handleSelection(e, index); const result = await musicSearch.handleSelection(e, index);
if (result.success) { if (result.success) {
await this.sendMusicResult(e, result); await this.sendMusicResult(e, result);
await musicSearch.clearGroupSearch(e.group_id);
} else { } else {
await e.reply(`${result.message}`, true); await e.reply(`${result.message}`, true);
} }
@ -134,7 +159,9 @@ export class CrystelfMusic extends plugin {
await Group.sendGroupRecord(e, e.group_id, `file://${audioFile}`, adapter); await Group.sendGroupRecord(e, e.group_id, `file://${audioFile}`, adapter);
} else { } else {
const extension = await this.getFileExtension(); const extension = await this.getFileExtension();
const filename = `${song.displayTitle} - ${song.displayArtist}.${extension}`; const sanitizedTitle = song.displayTitle.replace(/\s+/g, '_');
const sanitizedArtist = song.displayArtist.replace(/\s+/g, '_');
const filename = `${sanitizedTitle} - ${sanitizedArtist}.${extension}`;
await Group.sendGroupFile(e, e.group_id, `file://${audioFile}`, filename, adapter); await Group.sendGroupFile(e, e.group_id, `file://${audioFile}`, filename, adapter);
} }
musicSearch.clearUserSelection(e.group_id, e.user_id); musicSearch.clearUserSelection(e.group_id, e.user_id);

View File

@ -15,5 +15,6 @@
"welcome": true, "welcome": true,
"faceReply": true, "faceReply": true,
"ai": true, "ai": true,
"blackWords": true "blackWords": true,
"music": true
} }