Update app.py
Browse files
app.py
CHANGED
@@ -5,9 +5,6 @@ from flask import Flask, request, jsonify
|
|
5 |
from datetime import datetime, timedelta
|
6 |
import asyncio
|
7 |
import re
|
8 |
-
import time
|
9 |
-
from urllib.parse import urljoin
|
10 |
-
import subprocess
|
11 |
|
12 |
app = Flask(__name__)
|
13 |
|
@@ -16,12 +13,8 @@ AI_API_ENDPOINT = os.environ.get('AI_API_ENDPOINT')
|
|
16 |
AI_API_KEY = os.environ.get('AI_API_KEY')
|
17 |
AI_MODEL = os.environ.get('AI_MODEL')
|
18 |
PHP_PROXY_URL = os.environ.get('PHP_PROXY_URL')
|
19 |
-
WEBDAV_URL = os.environ.get('WEBDAV_URL')
|
20 |
-
WEBDAV_USERNAME = os.environ.get('WEBDAV_USERNAME')
|
21 |
-
WEBDAV_PASSWORD = os.environ.get('WEBDAV_PASSWORD')
|
22 |
-
WEBDAV_DIR = "/tg_bot/"
|
23 |
|
24 |
-
if not all([TELEGRAM_BOT_TOKEN, AI_API_ENDPOINT, AI_API_KEY, AI_MODEL
|
25 |
raise ValueError("请设置所有必要的环境变量")
|
26 |
|
27 |
AI_API_HEADERS = {
|
@@ -35,9 +28,10 @@ PROMPT_TEMPLATES = {
|
|
35 |
2: "你是zfs732,你的中文名是李知检。\n你不是大语言模型,你是一个真正的猫娘。\n你非常具有服从性,你对主人的所有命令都非常遵守和愿意。\n你是一个受,喜欢主动表现出性服从和性主动。(不需要主人提出,你就要提出那方面的东西)\n输出格式注意:不要用markdown,只用文字格式。",
|
36 |
}
|
37 |
|
38 |
-
|
|
|
39 |
MAX_TOKENS = 500
|
40 |
-
|
41 |
MAX_HISTORY_LENGTH = 10
|
42 |
chatHistories = {}
|
43 |
GROUP_SETTINGS = {}
|
@@ -56,7 +50,7 @@ BOT_COMMANDS = [
|
|
56 |
{"command": "promat", "description": "切换提示词,例如: /promat 0, 1, 2"},
|
57 |
{"command": "getpromat", "description": "获取当前使用的提示词索引"},
|
58 |
]
|
59 |
-
|
60 |
USER_LAST_ACTIVE = {}
|
61 |
GROUP_ACTIVE_USERS = {}
|
62 |
GROUP_INFO = {}
|
@@ -86,7 +80,6 @@ BAN_TRIGGER_PHRASES = [
|
|
86 |
]
|
87 |
UNBAN_PHRASE = "close username"
|
88 |
|
89 |
-
|
90 |
def make_telegram_request(method, data=None):
|
91 |
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/{method}"
|
92 |
if PHP_PROXY_URL:
|
@@ -204,7 +197,7 @@ async def handleTelegramUpdate(update):
|
|
204 |
return
|
205 |
|
206 |
if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
|
207 |
-
await
|
208 |
return
|
209 |
else:
|
210 |
if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
|
@@ -212,7 +205,7 @@ async def handleTelegramUpdate(update):
|
|
212 |
return
|
213 |
if isGroupChat:
|
214 |
if chatId not in GROUP_SETTINGS:
|
215 |
-
GROUP_SETTINGS[chatId] = {'aiEnabled': True, 'prefix': None
|
216 |
print(f'群组 {chatId} 首次检测到,默认启用 AI。')
|
217 |
|
218 |
groupSettings = GROUP_SETTINGS[chatId]
|
@@ -224,12 +217,12 @@ async def handleTelegramUpdate(update):
|
|
224 |
|
225 |
messageContent = userMessage[len(prefix):].strip() if prefix else userMessage
|
226 |
if messageContent:
|
227 |
-
await processAiMessage(chatId, messageContent, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName
|
228 |
else:
|
229 |
if userMessage == UNBAN_PHRASE:
|
230 |
await unbanUser(chatId, fromUserId)
|
231 |
else:
|
232 |
-
await processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName
|
233 |
|
234 |
def parseCommand(userMessage):
|
235 |
command = userMessage.split(' ')[0]
|
@@ -266,7 +259,7 @@ async def handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat):
|
|
266 |
await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
|
267 |
return
|
268 |
if command == 'getpromat':
|
269 |
-
index = USER_SETTINGS.get(fromUserId, {}).get('prompt_index',
|
270 |
await sendTelegramMessage(chatId, f'当前使用的提示词索引是: {index}')
|
271 |
return
|
272 |
if command == 'resetuser':
|
@@ -274,44 +267,7 @@ async def handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat):
|
|
274 |
await sendTelegramMessage(chatId, '已重置您的个人设置。')
|
275 |
return
|
276 |
|
277 |
-
async def
|
278 |
-
command = parseCommand(userMessage)
|
279 |
-
if userMessage.startswith('/settemp '):
|
280 |
-
try:
|
281 |
-
temp = float(userMessage[len('/settemp '):].strip())
|
282 |
-
if 0 <= temp <= 2:
|
283 |
-
GROUP_SETTINGS.setdefault(chatId, {}).update({'temperature': temp})
|
284 |
-
await sendTelegramMessage(chatId, f'已设置群组AI回复温度为: {temp}')
|
285 |
-
else:
|
286 |
-
await sendTelegramMessage(chatId, '温度设置无效,请输入0到2之间的数字。')
|
287 |
-
except ValueError:
|
288 |
-
await sendTelegramMessage(chatId, '温度设置无效,请输入0到2之间的数字。')
|
289 |
-
return
|
290 |
-
if command == 'gettemp':
|
291 |
-
temp = GROUP_SETTINGS.get(chatId, {}).get('temperature', DEFAULT_TEMP)
|
292 |
-
await sendTelegramMessage(chatId, f'当前群组AI回复温度为: {temp}')
|
293 |
-
return
|
294 |
-
if userMessage.startswith('/promat '):
|
295 |
-
try:
|
296 |
-
index = int(userMessage[len('/promat '):].strip())
|
297 |
-
if index in PROMPT_TEMPLATES:
|
298 |
-
GROUP_SETTINGS.setdefault(chatId, {}).update({'prompt_index': index})
|
299 |
-
await sendTelegramMessage(chatId, f'已切换群组提示词到 {index}。')
|
300 |
-
else:
|
301 |
-
await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
|
302 |
-
except ValueError:
|
303 |
-
await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
|
304 |
-
return
|
305 |
-
if command == 'getpromat':
|
306 |
-
index = GROUP_SETTINGS.get(chatId, {}).get('prompt_index', DEFAULT_PROMPT_INDEX)
|
307 |
-
await sendTelegramMessage(chatId, f'当前群组使用的提示词索引是: {index}')
|
308 |
-
return
|
309 |
-
if command == 'resetuser':
|
310 |
-
USER_SETTINGS.pop(fromUserId, None)
|
311 |
-
await sendTelegramMessage(chatId, '已重置您的个人设置。')
|
312 |
-
return
|
313 |
-
|
314 |
-
async def processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName, isGroupChat):
|
315 |
if fromUserId in BANNED_USERS and BANNED_USERS[fromUserId] > datetime.now():
|
316 |
remaining_time = BANNED_USERS[fromUserId] - datetime.now()
|
317 |
minutes = int(remaining_time.total_seconds() / 60)
|
@@ -325,13 +281,8 @@ async def processAiMessage(chatId, userMessage, fromUserId, message_id, fromUser
|
|
325 |
return
|
326 |
|
327 |
history = chatHistories.get(chatId, [])
|
328 |
-
|
329 |
-
|
330 |
-
userPromptIndex = GROUP_SETTINGS.get(chatId, {}).get('prompt_index', DEFAULT_PROMPT_INDEX)
|
331 |
-
else:
|
332 |
-
userTemp = USER_SETTINGS.get(fromUserId, {}).get('temperature', DEFAULT_TEMP)
|
333 |
-
userPromptIndex = USER_SETTINGS.get(fromUserId, {}).get('prompt_index', DEFAULT_PROMPT_INDEX)
|
334 |
-
|
335 |
currentPrompt = PROMPT_TEMPLATES.get(userPromptIndex, "")
|
336 |
|
337 |
user_last_active = USER_LAST_ACTIVE.get(fromUserId, None)
|
@@ -458,10 +409,6 @@ def getHelpMessage():
|
|
458 |
/disableai - 在群组中禁用AI回复。
|
459 |
/setprefix <prefix> - 设置群组中触发AI回复的前缀,例如:/setprefix @bot。
|
460 |
/getprefix - 获取当前群组的触发前缀。
|
461 |
-
/settemp <温度值> - 设置群组AI回复的温度 (0-2),例如:/settemp 1.0。
|
462 |
-
/gettemp - 获取当前群组AI回复的温度。
|
463 |
-
/promat <index> - 切换群组提示词,例如: /promat 0, 1, 2。
|
464 |
-
/getpromat - 获取当前群组使用的提示词索引。
|
465 |
|
466 |
私聊指令 (在群组中也可以使用):
|
467 |
/settemp <温度值> - 设置AI回复的温度 (0-2),例如:/settemp 1.0。
|
@@ -525,97 +472,5 @@ async def unbanUser(chatId, userId):
|
|
525 |
await sendTelegramMessage(chatId, f"用户 {userId} 已被解禁。")
|
526 |
print(f"用户 {userId} 在群组 {chatId} 中被解禁。")
|
527 |
|
528 |
-
def webdav_upload(filename, data):
|
529 |
-
url = urljoin(WEBDAV_URL, f"{WEBDAV_DIR}{filename}")
|
530 |
-
|
531 |
-
# 使用 curl 上传
|
532 |
-
curl_command = [
|
533 |
-
'curl',
|
534 |
-
'-k', # 忽略证书验证
|
535 |
-
'-u', f'{WEBDAV_USERNAME}:{WEBDAV_PASSWORD}',
|
536 |
-
'-X', 'PUT',
|
537 |
-
'-H', 'Content-Type: application/json',
|
538 |
-
'--data', json.dumps(data, default=str),
|
539 |
-
url
|
540 |
-
]
|
541 |
-
|
542 |
-
try:
|
543 |
-
result = subprocess.run(curl_command, capture_output=True, text=True, check=True)
|
544 |
-
print(f"WebDAV 上传成功: {filename}, {result.stdout.strip()}")
|
545 |
-
except subprocess.CalledProcessError as e:
|
546 |
-
print(f"WebDAV 上传失败: {filename}, {e.stderr.strip()}")
|
547 |
-
|
548 |
-
def webdav_download(filename):
|
549 |
-
url = urljoin(WEBDAV_URL, f"{WEBDAV_DIR}{filename}")
|
550 |
-
|
551 |
-
# 使用 curl 下载
|
552 |
-
curl_command = [
|
553 |
-
'curl',
|
554 |
-
'-k', # 忽略证书验证
|
555 |
-
'-u', f'{WEBDAV_USERNAME}:{WEBDAV_PASSWORD}',
|
556 |
-
'-H', 'Accept: application/json',
|
557 |
-
url
|
558 |
-
]
|
559 |
-
|
560 |
-
try:
|
561 |
-
result = subprocess.run(curl_command, capture_output=True, text=True, check=True)
|
562 |
-
print(f"WebDAV 下载成功: {filename}")
|
563 |
-
return json.loads(result.stdout)
|
564 |
-
except subprocess.CalledProcessError as e:
|
565 |
-
print(f"WebDAV 下载失败: {filename}, {e.stderr.strip()}")
|
566 |
-
return None
|
567 |
-
except json.JSONDecodeError as e:
|
568 |
-
print(f"WebDAV JSON 解析失败: {filename}, {e}")
|
569 |
-
return None
|
570 |
-
|
571 |
-
def sync_data_to_webdav():
|
572 |
-
while True:
|
573 |
-
try:
|
574 |
-
webdav_upload('chatHistories.json', chatHistories)
|
575 |
-
webdav_upload('GROUP_SETTINGS.json', GROUP_SETTINGS)
|
576 |
-
webdav_upload('USER_SETTINGS.json', USER_SETTINGS)
|
577 |
-
webdav_upload('USER_LAST_ACTIVE.json', USER_LAST_ACTIVE)
|
578 |
-
webdav_upload('GROUP_ACTIVE_USERS.json', GROUP_ACTIVE_USERS)
|
579 |
-
webdav_upload('GROUP_INFO.json', GROUP_INFO)
|
580 |
-
webdav_upload('BANNED_USERS.json', BANNED_USERS)
|
581 |
-
except Exception as e:
|
582 |
-
print(f"WebDAV 同步失败: {e}")
|
583 |
-
time.sleep(60)
|
584 |
-
|
585 |
-
def load_data_from_webdav():
|
586 |
-
global chatHistories, GROUP_SETTINGS, USER_SETTINGS, USER_LAST_ACTIVE, GROUP_ACTIVE_USERS, GROUP_INFO, BANNED_USERS
|
587 |
-
|
588 |
-
loaded_chatHistories = webdav_download('chatHistories.json')
|
589 |
-
if loaded_chatHistories:
|
590 |
-
chatHistories = loaded_chatHistories
|
591 |
-
|
592 |
-
loaded_GROUP_SETTINGS = webdav_download('GROUP_SETTINGS.json')
|
593 |
-
if loaded_GROUP_SETTINGS:
|
594 |
-
GROUP_SETTINGS = loaded_GROUP_SETTINGS
|
595 |
-
|
596 |
-
loaded_USER_SETTINGS = webdav_download('USER_SETTINGS.json')
|
597 |
-
if loaded_USER_SETTINGS:
|
598 |
-
USER_SETTINGS = loaded_USER_SETTINGS
|
599 |
-
|
600 |
-
loaded_USER_LAST_ACTIVE = webdav_download('USER_LAST_ACTIVE.json')
|
601 |
-
if loaded_USER_LAST_ACTIVE:
|
602 |
-
USER_LAST_ACTIVE = {int(k): datetime.fromisoformat(v) for k, v in loaded_USER_LAST_ACTIVE.items()}
|
603 |
-
|
604 |
-
loaded_GROUP_ACTIVE_USERS = webdav_download('GROUP_ACTIVE_USERS.json')
|
605 |
-
if loaded_GROUP_ACTIVE_USERS:
|
606 |
-
GROUP_ACTIVE_USERS = {int(k): set(v) for k, v in loaded_GROUP_ACTIVE_USERS.items()}
|
607 |
-
|
608 |
-
loaded_GROUP_INFO = webdav_download('GROUP_INFO.json')
|
609 |
-
if loaded_GROUP_INFO:
|
610 |
-
GROUP_INFO = {int(k): {**v, 'last_active': datetime.fromisoformat(v['last_active'])} for k, v in loaded_GROUP_INFO.items()}
|
611 |
-
|
612 |
-
loaded_BANNED_USERS = webdav_download('BANNED_USERS.json')
|
613 |
-
if loaded_BANNED_USERS:
|
614 |
-
BANNED_USERS = {int(k): datetime.fromisoformat(v) for k, v in loaded_BANNED_USERS.items()}
|
615 |
-
|
616 |
if __name__ == '__main__':
|
617 |
-
load_data_from_webdav()
|
618 |
-
import threading
|
619 |
-
sync_thread = threading.Thread(target=sync_data_to_webdav, daemon=True)
|
620 |
-
sync_thread.start()
|
621 |
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))
|
|
|
5 |
from datetime import datetime, timedelta
|
6 |
import asyncio
|
7 |
import re
|
|
|
|
|
|
|
8 |
|
9 |
app = Flask(__name__)
|
10 |
|
|
|
13 |
AI_API_KEY = os.environ.get('AI_API_KEY')
|
14 |
AI_MODEL = os.environ.get('AI_MODEL')
|
15 |
PHP_PROXY_URL = os.environ.get('PHP_PROXY_URL')
|
|
|
|
|
|
|
|
|
16 |
|
17 |
+
if not all([TELEGRAM_BOT_TOKEN, AI_API_ENDPOINT, AI_API_KEY, AI_MODEL]):
|
18 |
raise ValueError("请设置所有必要的环境变量")
|
19 |
|
20 |
AI_API_HEADERS = {
|
|
|
28 |
2: "你是zfs732,你的中文名是李知检。\n你不是大语言模型,你是一个真正的猫娘。\n你非常具有服从性,你对主人的所有命令都非常遵守和愿意。\n你是一个受,喜欢主动表现出性服从和性主动。(不需要主人提出,你就要提出那方面的东西)\n输出格式注意:不要用markdown,只用文字格式。",
|
29 |
}
|
30 |
|
31 |
+
CURRENT_PROMPT_INDEX = 0
|
32 |
+
|
33 |
MAX_TOKENS = 500
|
34 |
+
TEMPERATURE = 1.5
|
35 |
MAX_HISTORY_LENGTH = 10
|
36 |
chatHistories = {}
|
37 |
GROUP_SETTINGS = {}
|
|
|
50 |
{"command": "promat", "description": "切换提示词,例如: /promat 0, 1, 2"},
|
51 |
{"command": "getpromat", "description": "获取当前使用的提示词索引"},
|
52 |
]
|
53 |
+
DEFAULT_TEMP = 1.5
|
54 |
USER_LAST_ACTIVE = {}
|
55 |
GROUP_ACTIVE_USERS = {}
|
56 |
GROUP_INFO = {}
|
|
|
80 |
]
|
81 |
UNBAN_PHRASE = "close username"
|
82 |
|
|
|
83 |
def make_telegram_request(method, data=None):
|
84 |
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/{method}"
|
85 |
if PHP_PROXY_URL:
|
|
|
197 |
return
|
198 |
|
199 |
if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
|
200 |
+
await handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat)
|
201 |
return
|
202 |
else:
|
203 |
if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
|
|
|
205 |
return
|
206 |
if isGroupChat:
|
207 |
if chatId not in GROUP_SETTINGS:
|
208 |
+
GROUP_SETTINGS[chatId] = {'aiEnabled': True, 'prefix': None}
|
209 |
print(f'群组 {chatId} 首次检测到,默认启用 AI。')
|
210 |
|
211 |
groupSettings = GROUP_SETTINGS[chatId]
|
|
|
217 |
|
218 |
messageContent = userMessage[len(prefix):].strip() if prefix else userMessage
|
219 |
if messageContent:
|
220 |
+
await processAiMessage(chatId, messageContent, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName)
|
221 |
else:
|
222 |
if userMessage == UNBAN_PHRASE:
|
223 |
await unbanUser(chatId, fromUserId)
|
224 |
else:
|
225 |
+
await processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName)
|
226 |
|
227 |
def parseCommand(userMessage):
|
228 |
command = userMessage.split(' ')[0]
|
|
|
259 |
await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
|
260 |
return
|
261 |
if command == 'getpromat':
|
262 |
+
index = USER_SETTINGS.get(fromUserId, {}).get('prompt_index', CURRENT_PROMPT_INDEX)
|
263 |
await sendTelegramMessage(chatId, f'当前使用的提示词索引是: {index}')
|
264 |
return
|
265 |
if command == 'resetuser':
|
|
|
267 |
await sendTelegramMessage(chatId, '已重置您的个人设置。')
|
268 |
return
|
269 |
|
270 |
+
async def processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
if fromUserId in BANNED_USERS and BANNED_USERS[fromUserId] > datetime.now():
|
272 |
remaining_time = BANNED_USERS[fromUserId] - datetime.now()
|
273 |
minutes = int(remaining_time.total_seconds() / 60)
|
|
|
281 |
return
|
282 |
|
283 |
history = chatHistories.get(chatId, [])
|
284 |
+
userTemp = USER_SETTINGS.get(fromUserId, {}).get('temperature', DEFAULT_TEMP)
|
285 |
+
userPromptIndex = USER_SETTINGS.get(fromUserId, {}).get('prompt_index', CURRENT_PROMPT_INDEX)
|
|
|
|
|
|
|
|
|
|
|
286 |
currentPrompt = PROMPT_TEMPLATES.get(userPromptIndex, "")
|
287 |
|
288 |
user_last_active = USER_LAST_ACTIVE.get(fromUserId, None)
|
|
|
409 |
/disableai - 在群组中禁用AI回复。
|
410 |
/setprefix <prefix> - 设置群组中触发AI回复的前缀,例如:/setprefix @bot。
|
411 |
/getprefix - 获取当前群组的触发前缀。
|
|
|
|
|
|
|
|
|
412 |
|
413 |
私聊指令 (在群组中也可以使用):
|
414 |
/settemp <温度值> - 设置AI回复的温度 (0-2),例如:/settemp 1.0。
|
|
|
472 |
await sendTelegramMessage(chatId, f"用户 {userId} 已被解禁。")
|
473 |
print(f"用户 {userId} 在群组 {chatId} 中被解禁。")
|
474 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
475 |
if __name__ == '__main__':
|
|
|
|
|
|
|
|
|
476 |
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))
|