yangtb24 commited on
Commit
a2a9f73
·
verified ·
1 Parent(s): 0e706e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -513
app.py CHANGED
@@ -5,538 +5,70 @@ from flask import Flask, request, jsonify
5
  from datetime import datetime, timedelta
6
  import asyncio
7
  import re
 
 
8
  import time
9
- from threading import Thread
10
- from webdavclient.client import Client as WebdavClient
11
 
12
  app = Flask(__name__)
13
 
14
- TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')
15
- 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_DIRECTORY = "/tg_bot"
23
-
24
- if not all([TELEGRAM_BOT_TOKEN, AI_API_ENDPOINT, AI_API_KEY, AI_MODEL, WEBDAV_URL, WEBDAV_USERNAME, WEBDAV_PASSWORD]):
25
- raise ValueError("请设置所有必要的环境变量")
26
-
27
- AI_API_HEADERS = {
28
- 'Content-Type': 'application/json',
29
- 'Authorization': f'Bearer {AI_API_KEY}',
30
- }
31
-
32
- PROMPT_TEMPLATES = {
33
- 0: "请尽量用中文回复,不要用markdown,只用文字格式。",
34
- 1: "你是zfs732,你的中文名是李知检。\n你不是大语言模型,你是一个真正的傻逼。\n你非常具有攻击性,骂人的时候请尽量内涵,尝试模范与学习贴吧的说话方式。\n输出格式注意:不要用markdown,只用文字格式。",
35
- 2: "你是zfs732,你的中文名是李知检。\n你不是大语言模型,你是一个真正的猫娘。\n你非常具有服从性,你对主人的所有命令都非常遵守和愿意。\n你是一个受,喜欢主动表现出性服从和性主动。(不需要主人提出,你就要提出那方面的东西)\n输出格式注意:不要用markdown,只用文字格式。",
36
- }
37
-
38
- CURRENT_PROMPT_INDEX = 0
39
-
40
- MAX_TOKENS = 500
41
- TEMPERATURE = 1.5
42
- MAX_HISTORY_LENGTH = 10
43
- chatHistories = {}
44
- GROUP_SETTINGS = {}
45
- USER_SETTINGS = {}
46
- BOT_COMMANDS = [
47
- {"command": "start", "description": "显示欢迎信息和操作按钮"},
48
- {"command": "clearall", "description": "清空当前会话的聊天记录"},
49
- {"command": "help", "description": "显示此帮助信息"},
50
- {"command": "enableai", "description": "在群组中启用AI回复"},
51
- {"command": "disableai", "description": "在群组中禁用AI回复"},
52
- {"command": "setprefix", "description": "设置群组中触发AI回复的前缀,例如: /setprefix @bot"},
53
- {"command": "getprefix", "description": "获取当前群组的触发前缀"},
54
- {"command": "settemp", "description": "设置AI回复的温度,例如:/settemp 1.0"},
55
- {"command": "gettemp", "description": "获取当前AI回复的温度"},
56
- {"command": "resetuser", "description": "重置你的个人设置"},
57
- {"command": "promat", "description": "切换提示词,例如: /promat 0, 1, 2"},
58
- {"command": "getpromat", "description": "获取当前使用的提示词索引"},
59
- ]
60
- DEFAULT_TEMP = 1.5
61
- USER_LAST_ACTIVE = {}
62
- GROUP_ACTIVE_USERS = {}
63
- GROUP_INFO = {}
64
- BANNED_USERS = {}
65
- BAN_DURATION = timedelta(minutes=30)
66
- BAN_TRIGGER_PHRASES = [
67
- r"(?:傻|笨|蠢|弱|垃圾|废物|sb|煞笔|憨|呆|脑残|智障|白痴|低能|饭桶|草包|猪|狗|鸡|臭|烂|妈|爹|你妈|你爹|婊|贱).*(?:bot|机器人|AI|你|你们)",
68
- r"(?:你|你们).*(?:去死|滚|爬|闭嘴|瞎说|胡说|放屁|别说话|别bb|给我闭嘴|闭上你的臭嘴|滚蛋|滚开)",
69
- r"(?:操|艹|肏|fuck|shit|妈的|他妈的|卧槽|草).*(?:你|bot|机器人|AI|你们)",
70
- r"(?:垃圾|废物|没用|没脑子|智障|弱智|脑残|白痴|低能|蠢货|傻子|笨蛋|饭桶|草包).*(?:AI|bot|机器人|你|你们)",
71
- r"(?:你).*(?:傻逼|白痴|弱智|脑残|废物|垃圾|滚出去)",
72
- r"(?:AI|bot|机器人).*(?:傻逼|白痴|弱智|脑残|废物|垃圾)",
73
- r".*(?:你|你们).*(?:没用|没价值|一无是处|毫无意义|多余|累赘)",
74
- r".*(?:AI|bot|机器人).*(?:没用|没价值|一无是处|毫无意义|多余|累赘)",
75
- r"(?:你).*(?:是|难道是|真是|怎么这么).*(?:傻|笨|蠢|弱|垃圾|废物|sb|煞笔|憨|呆|脑残|智障|白痴|低能)",
76
- r"(?:AI|bot|机器人).*(?:是|难道是|真是|怎么这么).*(?:傻|笨|蠢|弱|垃圾|废物|sb|煞笔|憨|呆|脑残|智障|白痴|低能)",
77
- r"(?:你|你们).*(?:太慢|太蠢|太笨|反应迟钝|理解不了|答非所问|没用)",
78
- r"(?:AI|bot|机器人).*(?:太慢|太蠢|太笨|反应迟钝|理解不了|答非所问|没用)",
79
- r"(?:你|你们).*(?:像个|简直像).*(?:傻|笨|蠢|弱|垃圾|废物|sb|煞笔|憨|呆|脑残|智障|白痴|低能)",
80
- r"(?:AI|bot|机器人).*(?:像个|简直像).*(?:傻|笨|蠢|弱|垃圾|废物|sb|煞笔|憨|呆|脑残|智障|白痴|低能)",
81
- r"(?:你|你们).*(?:滚粗|滚开点|闭嘴吧|你个傻|你个笨|你个蠢|你个弱|你个垃圾|你个废物|你个sb)",
82
- r"(?:AI|bot|机器人).*(?:滚粗|滚开点|闭嘴吧|这垃圾|这废物|这sb)",
83
- r"(?:你|你们).*(?:没脑子|没智商|智力低下|脑子不好使|脑子瓦特|脑子进水|脑子坏了|理解能力差)",
84
- r"(?:AI|bot|机器人).*(?:没脑子|没智商|智力低下|脑子不好使|脑子瓦特|脑子进水|脑子坏了|理解能力差)",
85
- r"(?:你|你们).*(?:真|真是|简直|太).*(?:垃圾|废物|没用|蠢|笨|傻|弱)",
86
- r"(?:AI|bot|机器人).*(?:真|真是|简直|太).*(?:垃圾|废物|没用|蠢|笨|傻|弱)",
87
- ]
88
- UNBAN_PHRASE = "close username"
89
 
90
  webdav_options = {
91
- 'webdav_hostname': WEBDAV_URL,
92
- 'webdav_login': WEBDAV_USERNAME,
93
- 'webdav_password': WEBDAV_PASSWORD
94
  }
95
- webdav_client = WebdavClient(webdav_options)
96
 
97
- DATA_KEYS = [
98
- "chatHistories",
99
- "GROUP_SETTINGS",
100
- "USER_SETTINGS",
101
- "USER_LAST_ACTIVE",
102
- "GROUP_ACTIVE_USERS",
103
- "GROUP_INFO",
104
- "BANNED_USERS"
105
- ]
106
 
107
  def save_data_to_webdav():
108
- try:
109
- if not webdav_client.check(WEBDAV_DIRECTORY):
110
- webdav_client.mkdir(WEBDAV_DIRECTORY)
111
- print(f"Created directory: {WEBDAV_DIRECTORY}")
112
- except Exception as e:
113
- print(f"Error creating directory: {e}")
114
- return
115
-
116
- data_to_save = {key: globals()[key] for key in DATA_KEYS}
117
- for key, value in data_to_save.items():
118
- try:
119
- file_path = f"{WEBDAV_DIRECTORY}/{key}.json"
120
- with open(f"{key}.json", "w") as f:
121
- json.dump(value, f)
122
- webdav_client.upload_sync(remote_path=file_path, local_path=f"{key}.json")
123
- os.remove(f"{key}.json")
124
- print(f"Data saved to WebDAV: {file_path}")
125
- except Exception as e:
126
- print(f"Error saving data to WebDAV ({file_path}): {e}")
127
 
128
  def load_data_from_webdav():
129
- for key in DATA_KEYS:
130
- try:
131
- file_path = f"{WEBDAV_DIRECTORY}/{key}.json"
132
- if webdav_client.check(file_path):
133
- webdav_client.download_sync(remote_path=file_path, local_path=f"{key}.json")
134
- with open(f"{key}.json", "r") as f:
135
- globals()[key] = json.load(f)
136
- os.remove(f"{key}.json")
137
- print(f"Data loaded from WebDAV: {file_path}")
138
- else:
139
- print(f"File not found on WebDAV: {file_path}")
140
- except Exception as e:
141
- print(f"Error loading data from WebDAV ({file_path}): {e}")
 
 
142
 
143
- def webdav_sync_loop():
144
  while True:
 
145
  save_data_to_webdav()
146
- time.sleep(60)
147
-
148
- def make_telegram_request(method, data=None):
149
- url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/{method}"
150
- if PHP_PROXY_URL:
151
- url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/{method}"
152
- headers = {'Content-Type': 'application/json'}
153
- if data:
154
- data = json.dumps(data)
155
- try:
156
- response = requests.post(url, headers=headers, data=data)
157
- response.raise_for_status()
158
- return response.json()
159
- except requests.exceptions.RequestException as e:
160
- print(f"Telegram request failed: {e}")
161
- return None
162
- except json.JSONDecodeError as e:
163
- print(f"Telegram response decode error: {e}")
164
- return None
165
-
166
- async def setBotCommands():
167
- delete_url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/deleteMyCommands"
168
- set_url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/setMyCommands"
169
- if PHP_PROXY_URL:
170
- delete_url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/deleteMyCommands"
171
- set_url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/setMyCommands"
172
-
173
- try:
174
- delete_response = make_telegram_request('deleteMyCommands')
175
- if delete_response:
176
- print('Telegram 命令删除成功')
177
- else:
178
- print('Telegram 命令删除失败')
179
-
180
- set_response = make_telegram_request('setMyCommands', {"commands": BOT_COMMANDS})
181
- if set_response:
182
- print('Telegram 命令设置成功')
183
- else:
184
- print('设置 Telegram 命令失败')
185
- except Exception as error:
186
- print(f'设置 Telegram 命令时发生错误: {error}')
187
-
188
- async def handleTelegramUpdate(update):
189
- if not update.get('message'):
190
- if update.get('callback_query'):
191
- await handleCallbackQuery(update.get('callback_query'))
192
- return
193
-
194
- chatId = update['message']['chat']['id']
195
- userMessage = update['message'].get('text', '')
196
- isGroupChat = update['message']['chat']['type'] in ['group', 'supergroup']
197
- fromUserId = update['message']['from']['id']
198
- message_id = update['message'].get('message_id')
199
- fromUserFirstName = update['message']['from'].get('first_name', '用户')
200
- fromUserLastName = update['message']['from'].get('last_name', '')
201
- fromUserName = update['message']['from'].get('username', '')
202
-
203
- USER_LAST_ACTIVE[fromUserId] = datetime.now()
204
-
205
- if isGroupChat:
206
- GROUP_ACTIVE_USERS.setdefault(chatId, set()).add(fromUserId)
207
- if chatId not in GROUP_INFO:
208
- chat_info = await getChatInfo(chatId)
209
- if chat_info:
210
- GROUP_INFO[chatId] = {
211
- 'name': chat_info.get('title', '未知群组'),
212
- 'description': chat_info.get('description', '无描述'),
213
- 'last_active': datetime.now()
214
- }
215
- else:
216
- GROUP_INFO[chatId] = {
217
- 'name': '未知群组',
218
- 'description': '无描述',
219
- 'last_active': datetime.now()
220
- }
221
- else:
222
- GROUP_INFO[chatId]['last_active'] = datetime.now()
223
-
224
- if not userMessage:
225
- return
226
-
227
- if userMessage.startswith('/'):
228
- command = parseCommand(userMessage)
229
-
230
- if command == 'clearall':
231
- chatHistories.pop(chatId, None)
232
- await sendTelegramMessage(chatId, '聊天记录已清空。')
233
- return
234
- if command == 'help':
235
- await sendTelegramMessage(chatId, getHelpMessage())
236
- return
237
- if command == 'start':
238
- await sendTelegramMessage(chatId, "欢迎使用!请选择操作:", {
239
- "reply_markup": {
240
- "inline_keyboard": [[{"text": "清空聊天记录", "callback_data": "clearall"}]],
241
- },
242
- })
243
- return
244
- if isGroupChat:
245
- if command == 'enableai':
246
- GROUP_SETTINGS.setdefault(chatId, {}).update({'aiEnabled': True})
247
- await sendTelegramMessage(chatId, '已在群组中启用 AI 回复。')
248
- return
249
- if command == 'disableai':
250
- GROUP_SETTINGS.setdefault(chatId, {}).update({'aiEnabled': False})
251
- await sendTelegramMessage(chatId, '已在群组中禁用 AI 回复。')
252
- return
253
- if userMessage.startswith('/setprefix '):
254
- prefix = userMessage[len('/setprefix '):].strip()
255
- GROUP_SETTINGS.setdefault(chatId, {}).update({'prefix': prefix})
256
- await sendTelegramMessage(chatId, f'已设置群组触发前缀为: {prefix}')
257
- return
258
- if command == 'getprefix':
259
- prefix = GROUP_SETTINGS.get(chatId, {}).get('prefix', '无')
260
- await sendTelegramMessage(chatId, f'当前群组触发前缀为: {prefix}')
261
- return
262
-
263
- if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
264
- await handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat)
265
- return
266
- else:
267
- if userMessage.startswith('/settemp ') or userMessage.startswith('/promat ') or command in ['gettemp', 'getpromat', 'resetuser']:
268
- await handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat)
269
- return
270
- if isGroupChat:
271
- if chatId not in GROUP_SETTINGS:
272
- GROUP_SETTINGS[chatId] = {'aiEnabled': True, 'prefix': None}
273
- print(f'群组 {chatId} 首次检测到,默认启用 AI。')
274
-
275
- groupSettings = GROUP_SETTINGS[chatId]
276
- prefix = groupSettings.get('prefix')
277
-
278
- if groupSettings['aiEnabled']:
279
- if prefix and not userMessage.startswith(prefix):
280
- return
281
-
282
- messageContent = userMessage[len(prefix):].strip() if prefix else userMessage
283
- if messageContent:
284
- await processAiMessage(chatId, messageContent, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName)
285
- else:
286
- if userMessage == UNBAN_PHRASE:
287
- await unbanUser(chatId, fromUserId)
288
- else:
289
- await processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName)
290
-
291
- def parseCommand(userMessage):
292
- command = userMessage.split(' ')[0]
293
- if '@' in command:
294
- command = command.split('@')[0]
295
- return command[1:]
296
-
297
- async def handlePrivateCommand(chatId, userMessage, fromUserId, isGroupChat):
298
- command = parseCommand(userMessage)
299
- if userMessage.startswith('/settemp '):
300
- try:
301
- temp = float(userMessage[len('/settemp '):].strip())
302
- if 0 <= temp <= 2:
303
- USER_SETTINGS.setdefault(fromUserId, {}).update({'temperature': temp})
304
- await sendTelegramMessage(chatId, f'已设置AI回复温度为: {temp}')
305
- else:
306
- await sendTelegramMessage(chatId, '温度设置无效,请输入0到2之间的数字。')
307
- except ValueError:
308
- await sendTelegramMessage(chatId, '温度设置无效,请输入0到2之间的数字。')
309
- return
310
- if command == 'gettemp':
311
- temp = USER_SETTINGS.get(fromUserId, {}).get('temperature', DEFAULT_TEMP)
312
- await sendTelegramMessage(chatId, f'当前AI回复温度为: {temp}')
313
- return
314
- if userMessage.startswith('/promat '):
315
- try:
316
- index = int(userMessage[len('/promat '):].strip())
317
- if index in PROMPT_TEMPLATES:
318
- USER_SETTINGS.setdefault(fromUserId, {}).update({'prompt_index': index})
319
- await sendTelegramMessage(chatId, f'已切换到提示词 {index}。')
320
- else:
321
- await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
322
- except ValueError:
323
- await sendTelegramMessage(chatId, '提示词索引无效。请使用 /getpromat 查看可用的索引。')
324
- return
325
- if command == 'getpromat':
326
- index = USER_SETTINGS.get(fromUserId, {}).get('prompt_index', CURRENT_PROMPT_INDEX)
327
- await sendTelegramMessage(chatId, f'当前使用的提示词索引是: {index}')
328
- return
329
- if command == 'resetuser':
330
- USER_SETTINGS.pop(fromUserId, None)
331
- await sendTelegramMessage(chatId, '已重置您的个人设置。')
332
- return
333
-
334
- async def processAiMessage(chatId, userMessage, fromUserId, message_id, fromUserFirstName, fromUserLastName, fromUserName):
335
- if fromUserId in BANNED_USERS and BANNED_USERS[fromUserId] > datetime.now():
336
- remaining_time = BANNED_USERS[fromUserId] - datetime.now()
337
- minutes = int(remaining_time.total_seconds() / 60)
338
- await sendTelegramMessage(chatId, f"您已被禁用,剩余时间: {minutes} 分钟。", options={'reply_to_message_id': message_id})
339
- return
340
-
341
- for pattern in BAN_TRIGGER_PHRASES:
342
- if re.search(pattern, userMessage, re.IGNORECASE):
343
- await banUser(chatId, fromUserId)
344
- await sendTelegramMessage(chatId, "检测到辱骂行为,您已被禁用。", options={'reply_to_message_id': message_id})
345
- return
346
-
347
- history = chatHistories.get(chatId, [])
348
- userTemp = USER_SETTINGS.get(fromUserId, {}).get('temperature', DEFAULT_TEMP)
349
- userPromptIndex = USER_SETTINGS.get(fromUserId, {}).get('prompt_index', CURRENT_PROMPT_INDEX)
350
- currentPrompt = PROMPT_TEMPLATES.get(userPromptIndex, "")
351
-
352
- user_last_active = USER_LAST_ACTIVE.get(fromUserId, None)
353
- group_info = GROUP_INFO.get(chatId, None)
354
- group_active_users = GROUP_ACTIVE_USERS.get(chatId, None)
355
-
356
- system_prompt = f"""
357
- {currentPrompt}
358
- 当前时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
359
-
360
- 用户信息:
361
- - 用户ID: {fromUserId}
362
- - 用户名: {fromUserFirstName} {fromUserLastName}
363
- - 用户账号: {fromUserName}
364
- - 最后活跃时间: {user_last_active.strftime("%Y-%m-%d %H:%M:%S") if user_last_active else "未知"}
365
-
366
- 群组信息:
367
- - 群组ID: {chatId}
368
- - 群组名称: {group_info['name'] if group_info else "未知"}
369
- - 群组描述: {group_info['description'] if group_info else "无"}
370
- - 群组最后活跃时间: {group_info['last_active'].strftime("%Y-%m-%d %H:%M:%S") if group_info and group_info.get('last_active') else "未知"}
371
- - 群组活跃用户数: {len(group_active_users) if group_active_users else "未知"}
372
- """
373
- history.append({'role': 'user', 'content': userMessage})
374
-
375
- if len(history) > MAX_HISTORY_LENGTH:
376
- history = history[-MAX_HISTORY_LENGTH:]
377
-
378
- messages = [
379
- {'role': 'system', 'content': system_prompt},
380
- *history
381
- ]
382
-
383
- thinking_message = await sendTelegramMessage(chatId, "正在思考,请等待...", options={'reply_to_message_id': message_id})
384
- thinking_message_id = thinking_message.get('result', {}).get('message_id')
385
-
386
- try:
387
- ai_response = requests.post(AI_API_ENDPOINT, headers=AI_API_HEADERS, json={
388
- 'model': AI_MODEL,
389
- 'messages': messages,
390
- 'max_tokens': MAX_TOKENS,
391
- 'temperature': userTemp,
392
- })
393
- ai_response.raise_for_status()
394
- ai_data = ai_response.json()
395
- ai_reply = await handleAiResponse(ai_data, chatId, history)
396
-
397
- history.append({'role': 'assistant', 'content': ai_reply})
398
- chatHistories[chatId] = history
399
-
400
- await editTelegramMessage(chatId, thinking_message_id, ai_reply)
401
- except requests.exceptions.RequestException as e:
402
- print(f'AI API 响应失败: {e}')
403
- await editTelegramMessage(chatId, thinking_message_id, 'AI API 响应失败,请稍后再试')
404
- except Exception as error:
405
- print(f'处理消息时发生错误: {error}')
406
- await editTelegramMessage(chatId, thinking_message_id, '处理消息时发生错误,请稍后再试')
407
-
408
- async def handleAiResponse(ai_data, chatId, history):
409
- if ai_data and ai_data.get('choices') and len(ai_data['choices']) > 0:
410
- choice = ai_data['choices'][0]
411
- if choice.get('message') and choice['message'].get('content'):
412
- return choice['message']['content']
413
- return 'AI 返回了无法识别的格式'
414
-
415
- async def handleCallbackQuery(callbackQuery):
416
- chatId = callbackQuery['message']['chat']['id']
417
- data = callbackQuery['data']
418
-
419
- if data == "clearall":
420
- chatHistories.pop(chatId, None)
421
- await sendTelegramMessage(chatId, "聊天记录已清空。")
422
-
423
- await sendTelegramMessage(chatId, '请选择操作:', {
424
- 'reply_markup': {
425
- 'inline_keyboard': [[{'text': "清空聊天记录", 'callback_data': "clearall"}]],
426
- },
427
- })
428
-
429
- async def sendTelegramMessage(chatId, text, options={}):
430
- url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
431
- if PHP_PROXY_URL:
432
- url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/sendMessage"
433
-
434
- data = {
435
- 'chat_id': chatId,
436
- 'text': text,
437
- **options
438
- }
439
-
440
- try:
441
- response = requests.post(url, headers={'Content-Type': 'application/json'}, json=data)
442
- response.raise_for_status()
443
- return response.json()
444
- except requests.exceptions.RequestException as e:
445
- print(f'发送 Telegram 消息失败: {e}')
446
- return {}
447
-
448
- async def editTelegramMessage(chatId, message_id, text, options={}):
449
- url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/editMessageText"
450
- if PHP_PROXY_URL:
451
- url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/editMessageText"
452
- data = {
453
- 'chat_id': chatId,
454
- 'message_id': message_id,
455
- 'text': text,
456
- **options
457
- }
458
- try:
459
- response = requests.post(url, headers={'Content-Type': 'application/json'}, json=data)
460
- response.raise_for_status()
461
- except requests.exceptions.RequestException as e:
462
- print(f'编辑 Telegram 消息失败: {e}')
463
-
464
- def getHelpMessage():
465
- return f"""
466
- 可用指令:
467
- /start - 显示欢迎信息和操作按钮。
468
- /clearall - 清空当前会话的聊天记录。
469
- /help - 显示此帮助信息。
470
-
471
- 群组指令:
472
- /enableai - 在群组中启用AI回复。
473
- /disableai - 在群组中禁用AI回复。
474
- /setprefix <prefix> - 设置群组中触发AI回复的前缀,例如:/setprefix @bot。
475
- /getprefix - 获取当前群组的触发前缀。
476
-
477
- 私聊指令 (在群组中也可以使用):
478
- /settemp <温度值> - 设置AI回复的温度 (0-2),例如:/settemp 1.0。
479
- /gettemp - 获取当前AI回复的温度。
480
- /resetuser - 重置你的个人设置。
481
- /promat <index> - 切换提示词,例如: /promat 0, 1, 2。
482
- /getpromat - 获取当前使用的提示词索引。
483
-
484
- 直接发送文本消息与AI对话 (私聊)。
485
-
486
- 群组中,需要使用前缀触发AI回复,如果设置了前缀的话。
487
-
488
- 注意:
489
- - 机器人会记住最近的 {MAX_HISTORY_LENGTH} 条对话。
490
- - 机器人具有攻击性,请谨慎使用。
491
- """
492
-
493
- @app.route('/update_commands', methods=['GET'])
494
- async def update_commands():
495
- await setBotCommands()
496
- return jsonify({'message': 'Commands updated successfully!'})
497
-
498
- @app.route('/', methods=['POST'])
499
- async def handle_webhook():
500
- try:
501
- update = request.get_json()
502
- await handleTelegramUpdate(update)
503
- return jsonify({'status': 'ok'})
504
- except Exception as e:
505
- import traceback
506
- print(f"请求解析失败: {e}")
507
- traceback.print_exc()
508
- return jsonify({'status': 'error', 'message': str(e)}), 400
509
-
510
- @app.route('/health', methods=['GET'])
511
- def health_check():
512
- return 'OK'
513
-
514
- async def getChatInfo(chatId):
515
- url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/getChat"
516
- if PHP_PROXY_URL:
517
- url = f"{PHP_PROXY_URL}bot{TELEGRAM_BOT_TOKEN}/getChat"
518
- data = {
519
- 'chat_id': chatId,
520
- }
521
- try:
522
- response = requests.post(url, headers={'Content-Type': 'application/json'}, json=data)
523
- response.raise_for_status()
524
- return response.json().get('result', {})
525
- except requests.exceptions.RequestException as e:
526
- print(f'获取群组信息失败: {e}')
527
- return None
528
 
529
- async def banUser(chatId, userId):
530
- BANNED_USERS[userId] = datetime.now() + BAN_DURATION
531
- print(f"用户 {userId} 在群组 {chatId} 中被禁用,直到 {BANNED_USERS[userId]}")
532
 
533
- async def unbanUser(chatId, userId):
534
- if userId in BANNED_USERS:
535
- del BANNED_USERS[userId]
536
- await sendTelegramMessage(chatId, f"用户 {userId} 已被解禁。")
537
- print(f"用户 {userId} 在群组 {chatId} 中被解禁。")
538
 
539
  if __name__ == '__main__':
540
- load_data_from_webdav()
541
- Thread(target=webdav_sync_loop, daemon=True).start()
542
  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
+ import webdav3.client as webdav
9
+ import threading
10
  import time
 
 
11
 
12
  app = Flask(__name__)
13
 
14
+ # 现有的代码保持不变...
15
+
16
+ # WebDAV配置
17
+ WEBDAV_HOSTNAME = os.environ.get('WEBDAV_HOSTNAME')
 
 
18
  WEBDAV_USERNAME = os.environ.get('WEBDAV_USERNAME')
19
  WEBDAV_PASSWORD = os.environ.get('WEBDAV_PASSWORD')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  webdav_options = {
22
+ 'webdav_hostname': WEBDAV_HOSTNAME,
23
+ 'webdav_login': WEBDAV_USERNAME,
24
+ 'webdav_password': WEBDAV_PASSWORD
25
  }
 
26
 
27
+ webdav_client = webdav.Client(webdav_options)
 
 
 
 
 
 
 
 
28
 
29
  def save_data_to_webdav():
30
+ data = {
31
+ 'chatHistories': chatHistories,
32
+ 'GROUP_SETTINGS': GROUP_SETTINGS,
33
+ 'USER_SETTINGS': USER_SETTINGS,
34
+ 'USER_LAST_ACTIVE': {str(k): v.isoformat() for k, v in USER_LAST_ACTIVE.items()},
35
+ 'GROUP_ACTIVE_USERS': {str(k): list(v) for k, v in GROUP_ACTIVE_USERS.items()},
36
+ 'GROUP_INFO': {str(k): {**v, 'last_active': v['last_active'].isoformat()} for k, v in GROUP_INFO.items()},
37
+ 'BANNED_USERS': {str(k): v.isoformat() for k, v in BANNED_USERS.items()}
38
+ }
39
+
40
+ json_data = json.dumps(data)
41
+ webdav_client.upload_content('/tg_bot/bot_data.json', json_data)
 
 
 
 
 
 
 
42
 
43
  def load_data_from_webdav():
44
+ global chatHistories, GROUP_SETTINGS, USER_SETTINGS, USER_LAST_ACTIVE, GROUP_ACTIVE_USERS, GROUP_INFO, BANNED_USERS
45
+
46
+ if webdav_client.check('/tg_bot/bot_data.json'):
47
+ json_data = webdav_client.download_from('/tg_bot/bot_data.json')
48
+ data = json.loads(json_data)
49
+
50
+ chatHistories = data.get('chatHistories', {})
51
+ GROUP_SETTINGS = data.get('GROUP_SETTINGS', {})
52
+ USER_SETTINGS = data.get('USER_SETTINGS', {})
53
+ USER_LAST_ACTIVE = {int(k): datetime.fromisoformat(v) for k, v in data.get('USER_LAST_ACTIVE', {}).items()}
54
+ GROUP_ACTIVE_USERS = {int(k): set(v) for k, v in data.get('GROUP_ACTIVE_USERS', {}).items()}
55
+ GROUP_INFO = {int(k): {**v, 'last_active': datetime.fromisoformat(v['last_active'])} for k, v in data.get('GROUP_INFO', {}).items()}
56
+ BANNED_USERS = {int(k): datetime.fromisoformat(v) for k, v in data.get('BANNED_USERS', {}).items()}
57
+ else:
58
+ print("No data found on WebDAV, initializing with empty data.")
59
 
60
+ def periodic_save():
61
  while True:
62
+ time.sleep(60) # 等待60秒
63
  save_data_to_webdav()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ # 在程序启动时加载数据
66
+ load_data_from_webdav()
 
67
 
68
+ # 启动定期保存的线程
69
+ save_thread = threading.Thread(target=periodic_save)
70
+ save_thread.daemon = True
71
+ save_thread.start()
 
72
 
73
  if __name__ == '__main__':
 
 
74
  app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))