mirror of
https://github.com/Cola-Echo/Cola.git
synced 2026-06-06 03:35:50 +00:00
Add files via upload
This commit is contained in:
24
ai.js
24
ai.js
@@ -634,7 +634,29 @@ ${allowStickers ? buildStickerPrompt(settings) : ''}${allowMusicShare ? buildMus
|
||||
|
||||
拉黑后:
|
||||
- 用户发的消息你收不到,会显示"被拒收"
|
||||
- 你发的消息用户也看不到(解除后才能看到)`;
|
||||
- 你发的消息用户也看不到(解除后才能看到)
|
||||
|
||||
【红包和转账功能 - 你可以主动发送!】
|
||||
当你想给用户发红包时,使用格式:[红包:金额:祝福语]
|
||||
当你想给用户转账时,使用格式:[转账:金额:说明]
|
||||
|
||||
示例:
|
||||
- [红包:88:生日快乐!] ← 发88元红包
|
||||
- [红包:6.66] ← 发6.66元红包(可省略祝福语)
|
||||
- [转账:520:想你了] ← 转账520元
|
||||
- [转账:100] ← 转账100元(可省略说明)
|
||||
|
||||
使用场景建议:
|
||||
- 用户生日、节日时可以发红包
|
||||
- 用户说想买东西时可以转账
|
||||
- 想表达心意、哄用户开心时
|
||||
- 用户问你要红包/转账时可以发
|
||||
- 红包金额建议:1-200元
|
||||
- 转账金额不限
|
||||
|
||||
【绝对禁止】红包/转账标签必须单独一条!
|
||||
× 错误:给你买奶茶[转账:20] ← 错误!
|
||||
√ 正确:给你买奶茶|||[转账:20] ← 用 ||| 分开`;
|
||||
|
||||
// Meme 表情包提示词(如果启用)
|
||||
if (allowStickers && settings.memeStickersEnabled) {
|
||||
|
||||
13
chat.js
13
chat.js
@@ -116,11 +116,8 @@ export function appendBlockedNotice(contact) {
|
||||
exclamationDiv.className = 'wechat-blocked-exclamation';
|
||||
exclamationDiv.innerHTML = `<span class="wechat-blocked-exclamation-icon">!</span>`;
|
||||
|
||||
// 插入到消息内容前面
|
||||
const contentDiv = lastUserMsg.querySelector('.wechat-message-content');
|
||||
if (contentDiv) {
|
||||
contentDiv.insertBefore(exclamationDiv, contentDiv.firstChild);
|
||||
}
|
||||
// 插入到 .wechat-message 的末尾(因为 self 是 row-reverse,末尾会显示在左边)
|
||||
lastUserMsg.appendChild(exclamationDiv);
|
||||
|
||||
// 添加点击事件
|
||||
exclamationDiv.addEventListener('click', () => {
|
||||
@@ -389,16 +386,18 @@ function appendBlockedAIMessage(content, contact, quote = null) {
|
||||
const hasMeme = processedContent !== content;
|
||||
const bubbleContent = `<div class="wechat-message-bubble">${hasMeme ? processedContent : escapeHtml(content)}</div>`;
|
||||
|
||||
// 红色感叹号
|
||||
// 红色感叹号(作为独立元素,不在 content 内部)
|
||||
const exclamationHtml = `
|
||||
<div class="wechat-blocked-ai-exclamation" title="对方在您拉黑期间发送">
|
||||
<span class="wechat-blocked-exclamation-icon">!</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 感叹号作为 .wechat-message 的直接子元素,在 content 后面(flex row 会让它显示在右边)
|
||||
messageDiv.innerHTML = `
|
||||
<div class="wechat-message-avatar">${avatarContent}</div>
|
||||
<div class="wechat-message-content">${bubbleContent}${exclamationHtml}</div>
|
||||
<div class="wechat-message-content">${bubbleContent}</div>
|
||||
${exclamationHtml}
|
||||
`;
|
||||
|
||||
messagesContainer.appendChild(messageDiv);
|
||||
|
||||
15
config.js
15
config.js
@@ -113,10 +113,17 @@ export const MEME_PROMPT_TEMPLATE = `##【必须使用】表情包功能
|
||||
【重要】你【必须】经常发送表情包!每2-3条回复至少发一个表情包!
|
||||
|
||||
使用规则:
|
||||
- 表情包【必须】单独一条消息,用 ||| 分隔
|
||||
- 格式:<meme>文件名</meme>
|
||||
- 只能从下面列表选择,不能编造文件名
|
||||
|
||||
【绝对禁止 - 最重要的规则!】
|
||||
<meme>标签前后【绝对不能】有任何其他文字!必须用 ||| 分隔!
|
||||
× 错误:好想你<meme>xxx</meme> ← 绝对禁止!标签和文字混在一起!
|
||||
× 错误:<meme>xxx</meme>哈哈 ← 绝对禁止!标签后面有文字!
|
||||
× 错误:我很开心<meme>xxx</meme>你呢 ← 绝对禁止!标签夹在文字中间!
|
||||
√ 正确:好想你|||<meme>xxx</meme> ← 用|||分开,标签独立!
|
||||
√ 正确:<meme>xxx</meme>|||哈哈哈 ← 标签独立一条!
|
||||
|
||||
可用表情包列表:
|
||||
[
|
||||
${MEME_STICKERS.join('\n')}
|
||||
@@ -127,11 +134,7 @@ ${MEME_STICKERS.join('\n')}
|
||||
哈哈哈笑死|||<meme>小熊跳舞122o4w.gif</meme>|||你太搞笑了
|
||||
<meme>喜欢你egvwqb.jpg</meme>|||我真的好喜欢你
|
||||
|
||||
【错误示例 - 绝对禁止】:
|
||||
好想你<meme>xxx</meme> ← 错误!表情包没有用|||分开
|
||||
<meme>不存在的表情.jpg</meme> ← 错误!编造了不存在的文件名
|
||||
|
||||
记住:表情包让聊天更生动,【必须】经常使用!`;
|
||||
记住:表情包让聊天更生动,【必须】经常使用!但<meme>标签必须独立!`;
|
||||
|
||||
// 一起听功能提示词模板
|
||||
export const LISTEN_TOGETHER_PROMPT_TEMPLATE = `##【一起听歌场景】
|
||||
|
||||
@@ -351,7 +351,7 @@ export function renderToyHistory(contact) {
|
||||
</div>
|
||||
<div class="wechat-toy-history-card-actions">
|
||||
<span class="wechat-toy-history-card-target">${targetText}</span>
|
||||
<button class="wechat-history-delete-btn" data-tab="toy" data-index="${originalIndex}" title="删除">🗑️</button>
|
||||
<button class="wechat-history-delete-btn" data-tab="toy" data-index="${originalIndex}" title="删除">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wechat-toy-history-card-meta">
|
||||
|
||||
2
main.js
2
main.js
@@ -167,10 +167,10 @@ function renderHistoryContent(contact, tabType) {
|
||||
html += `<div class="wechat-history-card-header">`;
|
||||
html += `<span class="wechat-history-card-time">${escapeHtml(time)}</span>`;
|
||||
html += `<div class="wechat-history-card-actions">`;
|
||||
html += `<button class="wechat-history-delete-btn" data-tab="${tabType}" data-index="${originalIndex}" title="删除">×</button>`;
|
||||
if (duration) {
|
||||
html += `<span class="wechat-history-card-duration">${escapeHtml(duration)}</span>`;
|
||||
}
|
||||
html += `<button class="wechat-history-delete-btn" data-tab="${tabType}" data-index="${originalIndex}" title="删除">🗑️</button>`;
|
||||
html += `</div>`;
|
||||
html += `</div>`;
|
||||
|
||||
|
||||
16
style.css
16
style.css
@@ -6888,6 +6888,7 @@
|
||||
|
||||
.wechat-moment-images.grid-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.wechat-moment-images.grid-3,
|
||||
@@ -10674,9 +10675,9 @@
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 6px;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.wechat-blocked-exclamation-icon {
|
||||
@@ -10709,8 +10710,8 @@
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 6px;
|
||||
flex-shrink: 0;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
/* 手机弹窗样式 */
|
||||
@@ -10898,14 +10899,17 @@
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 2px 4px;
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s;
|
||||
font-size: 18px;
|
||||
color: #999;
|
||||
padding: 0 4px;
|
||||
line-height: 1;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.wechat-history-delete-btn:hover {
|
||||
opacity: 1;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.wechat-toy-history-card-actions {
|
||||
|
||||
@@ -307,7 +307,7 @@ export function generateSummaryPrompt(allChats, cupNumber) {
|
||||
// 如果有自定义模板,使用自定义模板
|
||||
let prompt;
|
||||
if (settings.customSummaryTemplate && settings.customSummaryTemplate.trim()) {
|
||||
prompt = settings.customSummaryTemplate.trim() + '\n\n【线上聊天记录】\n';
|
||||
prompt = settings.customSummaryTemplate.trim() + '\n\n以下是线上聊天记录:\n\n【线上聊天记录】\n';
|
||||
} else {
|
||||
// 使用默认模板(纯对话记录模式)
|
||||
prompt = `你的任务是将这段【线上聊天记录】原样整理成JSON格式。
|
||||
@@ -328,6 +328,8 @@ export function generateSummaryPrompt(allChats, cupNumber) {
|
||||
【JSON示例】
|
||||
{"keys":["公园","约会","周末"],"content":"{{user}}: 今天去哪玩?\\n{{char}}: 去公园吧\\n{{user}}: 好呀\\n{{char}}: 那我们下午2点见","comment":"${getCupName(cupNumber)}"}
|
||||
|
||||
以下是线上聊天记录:
|
||||
|
||||
【线上聊天记录】
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -655,6 +655,18 @@ function bindVideoCallEvents() {
|
||||
}
|
||||
});
|
||||
|
||||
// 移动端键盘收起后重置滚动位置
|
||||
document.getElementById('wechat-video-call-input')?.addEventListener('blur', () => {
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0);
|
||||
const page = document.getElementById('wechat-video-call-page');
|
||||
if (page) {
|
||||
page.style.transform = '';
|
||||
page.style.top = '0';
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// AI来电界面事件
|
||||
document.getElementById('wechat-video-call-incoming-accept')?.addEventListener('click', acceptIncomingCall);
|
||||
document.getElementById('wechat-video-call-incoming-decline')?.addEventListener('click', declineIncomingCall);
|
||||
@@ -724,6 +736,21 @@ async function triggerAIVideoGreeting() {
|
||||
if (/^\[(?:表情|照片|分享音乐|音乐)[::]/.test(reply)) continue;
|
||||
reply = reply.replace(/\[.*?\]/g, '').trim();
|
||||
|
||||
// 过滤掉泄露的提示词或内部指令
|
||||
reply = reply.replace(/^-\d+\s*.*/gm, '').trim();
|
||||
if (/我需要.*(回复|做出|扮演|以.*身份)/.test(reply)) {
|
||||
const dashMatch = reply.match(/---+\s*(.+)$/);
|
||||
if (dashMatch) {
|
||||
reply = dashMatch[1].trim();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (reply.includes('---')) {
|
||||
const parts2 = reply.split(/---+/);
|
||||
reply = parts2[parts2.length - 1].trim();
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
// 分离场景描述和说话内容
|
||||
// 提取所有括号内的场景描述
|
||||
@@ -798,6 +825,21 @@ async function triggerCameraToggleReaction() {
|
||||
if (/^\[(?:表情|照片|分享音乐|音乐)[::]/.test(reply)) continue;
|
||||
reply = reply.replace(/\[.*?\]/g, '').trim();
|
||||
|
||||
// 过滤掉泄露的提示词或内部指令
|
||||
reply = reply.replace(/^-\d+\s*.*/gm, '').trim();
|
||||
if (/我需要.*(回复|做出|扮演|以.*身份)/.test(reply)) {
|
||||
const dashMatch = reply.match(/---+\s*(.+)$/);
|
||||
if (dashMatch) {
|
||||
reply = dashMatch[1].trim();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (reply.includes('---')) {
|
||||
const parts2 = reply.split(/---+/);
|
||||
reply = parts2[parts2.length - 1].trim();
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
// 分离场景描述和说话内容
|
||||
const sceneMatches = reply.match(/([^)]+)/g);
|
||||
@@ -906,6 +948,21 @@ ${lastMessages}
|
||||
if (/^\[(?:表情|照片|分享音乐|音乐)[::]/.test(reply)) continue;
|
||||
reply = reply.replace(/\[.*?\]/g, '').trim();
|
||||
|
||||
// 过滤掉泄露的提示词或内部指令
|
||||
reply = reply.replace(/^-\d+\s*.*/gm, '').trim();
|
||||
if (/我需要.*(回复|做出|扮演|以.*身份)/.test(reply)) {
|
||||
const dashMatch = reply.match(/---+\s*(.+)$/);
|
||||
if (dashMatch) {
|
||||
reply = dashMatch[1].trim();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (reply.includes('---')) {
|
||||
const parts2 = reply.split(/---+/);
|
||||
reply = parts2[parts2.length - 1].trim();
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
// 保存到聊天历史
|
||||
const now = new Date();
|
||||
|
||||
@@ -632,6 +632,20 @@ function bindCallEvents() {
|
||||
sendCallMessage();
|
||||
}
|
||||
});
|
||||
|
||||
// 移动端键盘收起后重置滚动位置
|
||||
document.getElementById('wechat-voice-call-input')?.addEventListener('blur', () => {
|
||||
// 延迟执行以等待键盘完全收起
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0);
|
||||
// 重置可能被移动的元素
|
||||
const page = document.getElementById('wechat-voice-call-page');
|
||||
if (page) {
|
||||
page.style.transform = '';
|
||||
page.style.top = '0';
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// 接听来电
|
||||
@@ -803,7 +817,7 @@ ${lastMessages}
|
||||
hideTypingIndicator();
|
||||
}
|
||||
|
||||
// 按 ||| 分割,并将特殊标签与文本分离,避免“文字+表情包”混在同一条
|
||||
// 按 ||| 分割,并将特殊标签与文本分离,避免"文字+表情包"混在同一条
|
||||
const parts = splitAIMessages(aiResponse);
|
||||
|
||||
for (const part of parts) {
|
||||
@@ -815,6 +829,25 @@ ${lastMessages}
|
||||
// 移除可能的特殊标记
|
||||
reply = reply.replace(/\[.*?\]/g, '').trim();
|
||||
|
||||
// 过滤掉泄露的提示词或内部指令
|
||||
// 1. 以负数开头的行(如 -5000)
|
||||
reply = reply.replace(/^-\d+\s*.*/gm, '').trim();
|
||||
// 2. 包含"我需要"+"回复/做出/扮演"等指令性内容
|
||||
if (/我需要.*(回复|做出|扮演|以.*身份)/.test(reply)) {
|
||||
// 尝试提取 --- 后面的实际内容
|
||||
const dashMatch = reply.match(/---+\s*(.+)$/);
|
||||
if (dashMatch) {
|
||||
reply = dashMatch[1].trim();
|
||||
} else {
|
||||
continue; // 跳过这条消息
|
||||
}
|
||||
}
|
||||
// 3. 移除 --- 分隔符前面的内容(如果有的话)
|
||||
if (reply.includes('---')) {
|
||||
const parts2 = reply.split(/---+/);
|
||||
reply = parts2[parts2.length - 1].trim();
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
// 保存到聊天历史
|
||||
const now = new Date();
|
||||
|
||||
Reference in New Issue
Block a user