main.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. from flask import Flask, request
  2. import pandas as pd
  3. from openai import OpenAI
  4. import requests
  5. import time
  6. import re
  7. from wakeonlan import send_magic_packet
  8. from ai_pic import story_start, story_start_p2p, story_start_p2p_sese
  9. from msg_send_save import send_private_message_word,save_group_message,send_group_message_pic,send_group_message_word,send_group_poke,del_group_message
  10. from chat_model import AI_chat,AI_get_picprompt,AI_lora_getpic_prompt,AI_sendphoto_ornot
  11. from special_date import get_week,get_v50,get_holidays
  12. from config import config_get
  13. import random
  14. import os
  15. app = Flask(__name__)
  16. # 读取王石列表,存为stones数据df文件
  17. stones = pd.read_csv('other/stone.csv')
  18. if 'Unnamed: 0' in stones.columns:
  19. stones = stones.drop('Unnamed: 0', axis=1)
  20. for i in range(len(stones)):
  21. final_stat = "\n"
  22. abilities = stones.loc[i, 'stats'].split("&")
  23. for j in range(len(abilities)):
  24. ability = abilities[j].split("#")
  25. if ability[2] != "Nan":
  26. final_stat += ability[2]+":"
  27. if ability[0].endswith("%"):
  28. final_stat += ability[0].split("%")[0] + ability[1] +"% "
  29. else:
  30. final_stat += ability[0] + ability[1] + " "
  31. stones.loc[i,"stat"] = final_stat
  32. # QQ机器人基础板块,包括人格,绘图风格和名称自我意识
  33. my_name = config_get("my_name")
  34. prompt_max = config_get("prompt_max")
  35. prompt_less = config_get("prompt_less")
  36. # 一个比较没用的变量,用来限制绘画cd的,现在默认是0就是无cd
  37. last_request_time = 0
  38. # 最近一次的心跳上报时间,用来记录服务状态
  39. last_heartbeat_time = time.time()
  40. def on_my_message(group_id, user_id, user_name, raw_message, message):
  41. """
  42. 每次触发猫猫关键词,收到@使用这个方法来进行回应
  43. """
  44. global last_request_time
  45. # 先对解码后消息进行判断,如果第一个解码消息为@,则触发命令模式,遍历完成若没有命令触发则再触发人格对话
  46. if message[0]['type'] == "at" and message[1]['type'] == "text":
  47. command = message[1]['data']['text'].strip(" ")
  48. if str(command).startswith("/"):
  49. on_command(group_id, user_id, command)
  50. elif command=="v你50":
  51. print(send_group_message_pic(group_id, user_id, 'v50.png'))
  52. else:
  53. AI_ans = AI_chat(group_id, user_name+":"+raw_message, prompt_less)
  54. send_group_message_word(group_id, AI_ans)
  55. save_group_message(group_id, my_name, AI_ans)
  56. # 根据条件触发AI绘画
  57. if AI_sendphoto_ornot("猫猫:"+AI_ans) == "是":
  58. current_time = time.time()
  59. # 判断距离上次请求图片的时间间隔是否小于60秒(1分钟)
  60. if current_time-last_request_time >= 0:
  61. last_request_time = current_time
  62. send_group_message_pic(group_id, user_id, story_start(AI_get_picprompt(group_id)))
  63. else:
  64. AI_ans = AI_chat(group_id, user_name + ":" + raw_message, prompt_less)
  65. send_group_message_word(group_id, AI_ans)
  66. save_group_message(group_id, my_name, AI_ans)
  67. # 根据条件触发AI绘画
  68. if AI_sendphoto_ornot(AI_ans) == "是":
  69. current_time = time.time()
  70. # 判断距离上次请求图片的时间间隔是否小于60秒(1分钟)
  71. if current_time - last_request_time >= 0:
  72. last_request_time = current_time
  73. send_group_message_pic(group_id, user_id, story_start(AI_get_picprompt(group_id)))
  74. def on_command(group_id, user_id,command):
  75. """
  76. 每当接到命令符号时,开启这个功能进行回应
  77. """
  78. global last_request_time
  79. if command == "/菜单":
  80. home = """欢迎使用命令功能:
  81. /菜单:显示功能介绍
  82. /王石:查询王石效果
  83. /猫猫画画:调用自定义AI绘画功能
  84. /整点瑟瑟:不用我多说了吧
  85. 所有命令均需要@猫猫触发"""
  86. send_group_message_word(group_id, home)
  87. save_group_message(group_id, my_name, home)
  88. elif str(command).startswith("/王石"):
  89. stone_stat = ch_stone(command)
  90. send_group_message_word(group_id, stone_stat)
  91. save_group_message(group_id, my_name, stone_stat)
  92. elif str(command).startswith("/猫猫画画"):
  93. pic_word = str(command)[len("/猫猫画画"):]
  94. current_time = time.time()
  95. # 判断距离上次请求图片的时间间隔是否小于60秒(1分钟)
  96. if current_time - last_request_time >= 0:
  97. send_group_message_word(group_id, "图片正在生成中...")
  98. last_request_time = current_time
  99. send_group_message_pic(group_id, user_id, story_start(AI_lora_getpic_prompt(pic_word)))
  100. elif str(command).startswith("/整点瑟瑟"):
  101. pic_word = str(command)[len("/猫猫瑟瑟"):]
  102. current_time = time.time()
  103. # 判断距离上次请求图片的时间间隔是否小于60秒(1分钟)
  104. if group_id == 637612718:
  105. send_group_message_word(group_id, "本群该功能已被禁用!")
  106. else:
  107. if current_time - last_request_time >= 0:
  108. send_group_message_word(group_id, "图片正在生成中...")
  109. last_request_time = current_time
  110. message_id = send_group_message_pic(group_id, user_id, story_start("nsfw,"+AI_lora_getpic_prompt(pic_word)))['data']['message_id']
  111. time.sleep(8)
  112. del_group_message(message_id)
  113. else:
  114. error = "抱歉没有找到你所输入的命令!如有关于命令的问题请@猫猫输入/菜单进行查询\n示例:\n@猫猫 /菜单"
  115. send_group_message_word(group_id, error)
  116. save_group_message(group_id, my_name, error)
  117. def ch_stone(name):
  118. """
  119. 根据关键词搜索王石,返回具体介绍
  120. """
  121. word = name.lstrip("/王石")
  122. for i in range(len(stones)):
  123. if stones.loc[i, 'name'] == word:
  124. stone_up_on = stones.loc[i, 'up_on']
  125. if stone_up_on == "Nan":
  126. stone_up_on = ""
  127. else:
  128. stone_up_on = "\n可强化:" + stone_up_on
  129. return stones.loc[i, 'type'] +" " + stones.loc[i, 'name'] + stone_up_on + stones.loc[i, 'stat']
  130. return "这里似乎没有你想找的东西喵~\n如果要查找王石,请使用/王石查询正确的王石名称,示例:\n@猫猫 /王石科隆老大\n如果不清楚王石全名,可以在[掌上波多姆]中进行模糊搜索喵"
  131. def change2setu(raw_message,group_id,user_id):
  132. """
  133. 进入变瑟图命令
  134. """
  135. message = str(raw_message)
  136. # 提取 QQ 号
  137. pattern = r'\[CQ:at,qq=(\d+),name=[^]]+\]'
  138. match = re.search(pattern, message)
  139. if match:
  140. qq = match.group(1)
  141. try:
  142. img_url = f'https://q1.qlogo.cn/g?b=qq&nk={qq}&s=640'
  143. # 创建 user 文件夹
  144. on_file_path = os.path.join('user', qq)
  145. if not os.path.exists(on_file_path):
  146. os.makedirs(on_file_path)
  147. # 下载图片
  148. img_response = requests.get(img_url)
  149. img_response.raise_for_status()
  150. file_path = os.path.join('user', qq, f'{qq}.jpg')
  151. with open(file_path, 'wb') as file:
  152. file.write(img_response.content)
  153. print(f'图片已保存到 {file_path}')
  154. send_group_message_word(group_id, "开始变身!")
  155. message_id = send_group_message_pic(group_id, user_id, story_start_p2p_sese(qq))
  156. print(message_id)
  157. time.sleep(8)
  158. del_group_message(message_id['data']['message_id'])
  159. except Exception as e:
  160. print(f'发生未知错误: {e}')
  161. send_group_message_word(group_id, "变身失败!")
  162. else:
  163. print('未找到 QQ 号')
  164. def change2girl(raw_message,group_id,user_id):
  165. """
  166. 进入变美少女命令
  167. """
  168. message = str(raw_message)
  169. # 提取 QQ 号
  170. pattern = r'\[CQ:at,qq=(\d+),name=[^]]+\]'
  171. match = re.search(pattern, message)
  172. if match:
  173. qq = match.group(1)
  174. try:
  175. img_url = f'https://q1.qlogo.cn/g?b=qq&nk={qq}&s=640'
  176. # 创建 user 文件夹
  177. on_file_path = os.path.join('user', qq)
  178. if not os.path.exists(on_file_path):
  179. os.makedirs(on_file_path)
  180. # 下载图片
  181. img_response = requests.get(img_url)
  182. img_response.raise_for_status()
  183. file_path = os.path.join('user', qq, f'{qq}.jpg')
  184. with open(file_path, 'wb') as file:
  185. file.write(img_response.content)
  186. print(f'图片已保存到 {file_path}')
  187. send_group_message_word(group_id, "开始变身!")
  188. send_group_message_pic(group_id, user_id, story_start_p2p(qq))
  189. except Exception as e:
  190. print(f'发生未知错误: {e}')
  191. send_group_message_word(group_id, "变身失败!")
  192. else:
  193. print('未找到 QQ 号')
  194. @app.route('/stat', methods=['GET'])
  195. def stat_get():
  196. return {"heartbeat": last_heartbeat_time}
  197. @app.route('/cat', methods=['POST'])
  198. def chat():
  199. global last_heartbeat_time
  200. data = request.json
  201. data_type = data['post_type']
  202. # 管理员模式,目前只有开启主机功能
  203. if 'message_type' in data:
  204. if data['message_type'] == 'private':
  205. # 进入管理员模式
  206. if data['raw_message'] == "原神启动" and data['user_id'] == 3494084267:
  207. send_magic_packet("22-43-4D-05-34-B2")
  208. send_private_message_word(data['user_id'], "主机3B0IJ2U已启动!")
  209. print(data)
  210. # 进入群聊模式
  211. if data_type == "message" and data['message_type'] == "group":
  212. group_id = data['group_id']
  213. user_id = data['user_id']
  214. message = data['message']
  215. raw_message = data['raw_message']
  216. time_now = data['time']
  217. user_name = data['sender']['nickname']
  218. # 首先判断消息类型,如果为图片类型则存入url,否则存入csv文件中
  219. if message[0].get('type')=='image':
  220. image_data = message[0].get('data', {})
  221. url = image_data.get('url')
  222. save_group_message(group_id, user_name, f"图片内容:{url}")
  223. else:
  224. save_group_message(group_id, user_name, raw_message)
  225. # 然后根据命令优先级进入AI对话模式,在这里写入AI模块
  226. if str(raw_message).startswith("变美少女[CQ:at"):
  227. change2girl(raw_message, group_id, user_id)
  228. elif str(raw_message).startswith("变瑟图[CQ:at"):
  229. if group_id == 637612718:
  230. send_group_message_word(group_id,"本群该功能已被禁用!")
  231. else:
  232. change2setu(raw_message, group_id, user_id)
  233. elif my_name in raw_message:
  234. on_my_message(group_id, user_id, user_name, raw_message, message)
  235. print(
  236. f"收到message!群号:{group_id},发送人:{user_id},时间{time_now}\n"
  237. f"消息内容:{message}\n原始消息内容:{raw_message}")
  238. else:
  239. print(f"群聊{group_id}已记录新消息!")
  240. # 进入提示消息模式
  241. elif data_type == "notice":
  242. notice_type = data['notice_type']
  243. group_id = data['group_id']
  244. if notice_type == "group_increase":
  245. user_id = data['user_id']
  246. print(f"群成员增加!群号:{group_id},加入者:{user_id}")
  247. requests.post('http://127.0.0.1:3000/send_group_msg', json={
  248. 'group_id': group_id,
  249. 'message': [{
  250. "type": "at",
  251. "data": {
  252. "qq": f"{user_id}"
  253. }
  254. }, {
  255. 'type': 'text',
  256. 'data': {
  257. 'text': "欢迎新成员加入群聊喵~"
  258. }
  259. }]
  260. })
  261. elif notice_type == "notify" and data['target_id'] == data['self_id']:
  262. user_id = data['user_id']
  263. print(f"我被{user_id}戳了一下!")
  264. send_group_poke(group_id,user_id)
  265. if get_week()=="星期四":
  266. # 触发疯狂星期四文案
  267. # 生成一个0到99之间的随机整数,控制特殊文案概率为40%
  268. rand_num = random.randint(0, 99)
  269. print(rand_num)
  270. send_group_message_word(group_id,get_v50()) if rand_num < 30 else send_group_message_word(group_id,"₍^ >ヮ<^₎")
  271. else:
  272. send_group_message_word(group_id,"₍^ >ヮ<^₎")
  273. elif data_type == "meta_event":
  274. if data["meta_event_type"] == "heartbeat":
  275. last_heartbeat_time = data['time']
  276. return ""
  277. if __name__ == '__main__':
  278. app.run(host='0.0.0.0', port=3100)