選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

app.py 25KB

4ヶ月前
3ヶ月前
1ヶ月前
2ヶ月前
4ヶ月前
1ヶ月前
4ヶ月前
4ヶ月前
1ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
2ヶ月前
3ヶ月前
3ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
3ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
2ヶ月前
1ヶ月前
1ヶ月前
3ヶ月前
2ヶ月前
1ヶ月前
2ヶ月前
4ヶ月前
3ヶ月前
1ヶ月前
3ヶ月前
3ヶ月前
1ヶ月前
3ヶ月前
1ヶ月前
3ヶ月前
2ヶ月前
3ヶ月前
2ヶ月前
1ヶ月前
2ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
3ヶ月前
3ヶ月前
2ヶ月前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. from flask import Flask, send_from_directory, request,jsonify
  2. from flask_restful import Api,got_request_exception
  3. from resources.messages_resource import MessagesResource
  4. from resources.contacts_resources import DeleteFriendResource,GetFriendsInfoResource
  5. from resources.config_reources import GetWxchatConfigResource ,SaveWxchatConfigResource
  6. from resources.groups_resources import GetGroupsInfoResource,GetGroupMemberList
  7. from resources.login_resources import GetLoginInfoResource,GetLoginWxQRCodeResource,LoginWxCaptchCodeResource
  8. from resources.sns_resources import SendSNSTextResource,SendSNSImageResource, SendSNSVideoResource
  9. from common.log import logger, log_exception
  10. from common.interceptors import before_request, after_request, handle_exception,check_login_status
  11. import threading
  12. from common import kafka_helper, redis_helper,utils
  13. import random
  14. from model import Models
  15. import logging
  16. from config import load_config
  17. from wechat.biz import start_kafka_consumer_thread
  18. from wechat import gewe_chat
  19. import os,time,json,time
  20. from voice.ali.ali_voice import AliVoice
  21. # 自定义错误消息
  22. errors = {
  23. 'UserAlreadyExistsError': {
  24. 'message': "A user with that username already exists.",
  25. 'status': 409,
  26. },
  27. 'ResourceDoesNotExist': {
  28. 'message': "A resource with that ID no longer exists.",
  29. 'status': 410,
  30. 'extra': "Any extra information you want.",
  31. },
  32. }
  33. def fetch_and_save_contacts():
  34. """
  35. 获取联系人列表并保存到缓存
  36. """
  37. wxchat=gewe_chat.wxchat
  38. while True:
  39. try:
  40. login_keys = list(redis_helper.redis_helper.client.scan_iter(match='__AI_OPS_WX__:LOGININFO:*'))
  41. logger.info(f"Fetching login keys: {login_keys}")
  42. # 遍历每一个获取到的登录键
  43. for k in login_keys:
  44. try:
  45. r= redis_helper.redis_helper.get_hash(k)
  46. # print(r)
  47. token_id = r.get('tokenId')
  48. app_id = r.get('appId')
  49. wxid = r.get('wxid')
  50. status=r.get('status')
  51. if status=='1':
  52. ret,msg,contacts_list = wxchat.fetch_contacts_list(token_id, app_id)
  53. if ret==200:
  54. friend_wxids = [c for c in contacts_list['friends'] if c not in ['fmessage', 'medianote','weixin','weixingongzhong']] # 可以调整截取范围
  55. print(f'{wxid}的好友数量 {len(friend_wxids)}')
  56. wxchat.save_contacts_brief_to_cache(token_id, app_id, wxid, friend_wxids)
  57. logger.info(f'微信ID {wxid} 登录APPID {app_id} 成功,联系人已定时保存')
  58. chatrooms=contacts_list['chatrooms']
  59. wxchat.save_groups_info_to_cache(token_id, app_id, wxid, chatrooms)
  60. wxchat.save_groups_members_to_cache(token_id, app_id, wxid, chatrooms)
  61. logger.info(f'微信ID {wxid} 登录APPID {app_id} 成功,群信息已定时保存')
  62. else:
  63. logger.warning(f'{msg}-微信ID {wxid} 登录APPID {app_id} 不能获取好友和群资料')
  64. else:
  65. logger.info(f'微信ID {wxid} 未登录 {app_id} ,联系人不能定时保存')
  66. time.sleep(3)
  67. except Exception as e:
  68. logger.error(f'处理好友和群资料出错 login key {k}: {str(e)}', exc_info=True)
  69. except Exception as e:
  70. logger.error(f'发送错误 {str(e)}', exc_info=True)
  71. time.sleep(3600*1)
  72. def auto_add_contacts_from_chatrooms():
  73. '''
  74. 从群中自动添加好友
  75. '''
  76. logger.info('自动从群添加好友')
  77. wxchat=gewe_chat.wxchat
  78. while True:
  79. login_keys = list(redis_helper.redis_helper.client.scan_iter(match='__AI_OPS_WX__:LOGININFO:*'))
  80. #logger.info(f"Fetching login keys: {login_keys}")
  81. # 遍历每一个获取到的登录键
  82. for k in login_keys:
  83. r= redis_helper.redis_helper.get_hash(k)
  84. # print(r)
  85. token_id = r.get('tokenId')
  86. app_id = r.get('appId')
  87. nickname=r.get('nickName')
  88. wxid = r.get('wxid')
  89. status=r.get('status')
  90. # 启动线程处理登录信息
  91. thread = threading.Thread(target=process_add_contacts_from_chatrooms, args=(wxchat,status, wxid, token_id, app_id))
  92. thread.start()
  93. time.sleep(3)
  94. #time.sleep(60*10)
  95. time.sleep(3600*24)
  96. def process_add_contacts_from_chatrooms(wxchat:gewe_chat.GeWeChatCom,status, wxid, token_id, app_id):
  97. if status == '1':
  98. c = wxchat.get_wxchat_config_from_cache(wxid)
  99. contacts = wxchat.get_contacts_brief_from_cache(wxid)
  100. contact_wxids = [c.get('userName') for c in contacts]
  101. chatrooms = c.get('addContactsFromChatroomIdWhiteList', [])
  102. for chatroom_id in chatrooms:
  103. chatroom = wxchat.get_group_info_from_cache(wxid, chatroom_id)
  104. chatroom_member=wxchat.get_group_members_from_cache(wxid, chatroom_id)
  105. chatroom_nickname = chatroom.get('nickName')
  106. chatroom_owner_wxid = chatroom_member.get('chatroomOwner', None)
  107. admin_wxid = chatroom_member.get('adminWxid', None)
  108. logger.info(f'{chatroom_nickname} 的群主是 {chatroom_owner_wxid},管理员是{admin_wxid}')
  109. contact_wxids_set = set(contact_wxids)
  110. if admin_wxid is not None:
  111. contact_wxids_set.add(admin_wxid)
  112. if chatroom_owner_wxid is not None:
  113. contact_wxids_set.add(chatroom_owner_wxid)
  114. contact_wxids_set.add(wxid)
  115. unavailable_wixds=wxchat.check_wixd_group_add_contacts_history(wxid,chatroom_id)
  116. contact_wxids_set.update(unavailable_wixds)
  117. chatroot_member_list = chatroom.get('memberList', [])
  118. remaining_chatroot_members = [x for x in chatroot_member_list if x.get('wxid') not in contact_wxids_set]
  119. nickname = next((member['nickName'] for member in chatroot_member_list if member['wxid'] == wxid), None)
  120. logger.info(f'{nickname}-{wxid} 在 {chatroom_nickname} 群里还可以邀请的好友有:{[x.get("nickName") for x in remaining_chatroot_members]}')
  121. for m in remaining_chatroot_members:
  122. ret, msg, data = wxchat.add_group_member_as_friend(token_id, app_id, chatroom_id, m.get('wxid'), f'我是群聊"{chatroom_nickname}"群的{nickname}')
  123. if ret==200:
  124. contact_wxids= m.get('wxid')
  125. history=Models.AddGroupContactsHistory.model_validate({
  126. "chatroomId":chatroom_id,
  127. "wxid":wxid,
  128. "contactWixd":contact_wxids,
  129. "addTime":int(time.time())
  130. })
  131. wxchat.save_group_add_contacts_history(wxid,chatroom_id,contact_wxids,history)
  132. else:
  133. logger.info(f'群好友邀请失败原因:{data}')
  134. logger.info(f'{nickname} 向 {chatroom_nickname}-{chatroom_id} 群的 {m.get("nickName")}-{m.get("wxid")} 发送好友邀请 {msg}')
  135. time.sleep(10)
  136. time.sleep(20)
  137. else:
  138. logger.info(f'微信ID {wxid} 未登录 {app_id} ,群成员不能定时定时')
  139. def auto_add_contacts_from_to_add_contacts_queue():
  140. '''
  141. 从待添加好友队列中自动添加好友
  142. '''
  143. logger.info('自动添加好友')
  144. wxchat=gewe_chat.wxchat
  145. while True:
  146. login_keys = list(redis_helper.redis_helper.client.scan_iter(match='__AI_OPS_WX__:LOGININFO:*'))
  147. for k in login_keys:
  148. r= redis_helper.redis_helper.get_hash(k)
  149. token_id = r.get('tokenId')
  150. app_id = r.get('appId')
  151. nickname=r.get('nickName')
  152. wxid = r.get('wxid')
  153. status=r.get('status')
  154. if status == '1':
  155. c = wxchat.get_wxchat_config_from_cache(wxid)
  156. contacts = wxchat.get_contacts_brief_from_cache(wxid)
  157. contact_wxids = [c.get('userName') for c in contacts]
  158. add_contacts_queue = c.get('addContactsQueue', [])
  159. for contact_wxid in add_contacts_queue:
  160. if contact_wxid not in contact_wxids:
  161. ret, msg, data = wxchat.add_contacts(token_id, app_id, contact_wxid)
  162. if ret==200:
  163. contact_wxids.append(contact_wxid)
  164. wxchat.save_contacts_brief_to_cache(token_id, app_id, wxid, contact_wxids)
  165. history=Models.AddContactsHistory.model_validate({
  166. "wxid":wxid,
  167. "contactWixd":contact_wxid,
  168. "addTime":int(time.time())
  169. })
  170. def background_wxchat_thread():
  171. lock_name = "background_wxchat_thread_lock"
  172. lock_identifier = str(time.time()) # 使用时间戳作为唯一标识
  173. # 尝试获取分布式锁
  174. if redis_helper.redis_helper.acquire_lock(lock_name, timeout=60):
  175. try:
  176. logger.info("分布式锁已成功获取")
  177. # 启动任务
  178. scan_wx_login_info()
  179. #threading.Thread(target=fetch_and_save_contacts).start()
  180. #threading.Thread(target=auto_add_contacts_from_chatrooms).start()
  181. threading.Thread(target=wx_thread_manager.check_and_manage_threads()).start()
  182. # 保持锁的续期
  183. while True:
  184. time.sleep(30) # 每30秒检查一次锁的状态
  185. if not redis_helper.redis_helper.renew_lock(lock_name, lock_identifier, timeout=60):
  186. break # 如果无法续期锁,退出循环
  187. finally:
  188. # 释放锁
  189. redis_helper.redis_helper.release_lock(lock_name, lock_identifier)
  190. else:
  191. # 如果获取锁失败,等待一段时间后重试
  192. time.sleep(10)
  193. background_wxchat_thread()
  194. def scan_wx_login_info():
  195. wxchat = gewe_chat.wxchat
  196. cursor = 0
  197. while True:
  198. cursor, login_keys = redis_helper.redis_helper.client.scan(cursor, match='__AI_OPS_WX__:LOGININFO:*')
  199. for k in login_keys:
  200. r = redis_helper.redis_helper.get_hash(k)
  201. app_id=r.get("appId")
  202. #tel=r.get("mobile")
  203. token_id=r.get("tokenId")
  204. wxid=r.get("wxid")
  205. is_online = wxchat.check_online(token_id, app_id)
  206. if is_online:
  207. logger.info(f'微信ID {wxid} 在APPID {app_id} 已经在线')
  208. else:
  209. # 尝试重连
  210. res = wxchat.reconnection(token_id, app_id)
  211. if res.get('ret') == 200:
  212. logger.info(f'微信ID {wxid} 在APPID {app_id} 重连成功')
  213. # 同步联系人
  214. #fetch_and_save_contacts(wxchat, token_id, app_id, k)
  215. else:
  216. print("重连失败,重新登录...")
  217. print("发送离线消息到kafka")
  218. redis_helper.redis_helper.update_hash_field(k,'status',0)
  219. time.sleep(3)
  220. # 如果游标为 0,则表示扫描完成
  221. if cursor == 0:
  222. break
  223. class WechatThreadManager:
  224. def __init__(self):
  225. # 同步好友服务线程
  226. self.sync_contacts_worker_threads = {}
  227. self.sync_contacts_task_threads = {}
  228. # 群加好友服务线程
  229. self.add_contacts_from_group_worker_threads = {}
  230. # 群加好友任务线程
  231. self.add_group_member_as_friend_task_threads = {}
  232. # 自动加好友线程
  233. self.add_contacts_worker_threads = {}
  234. self.wxchat=gewe_chat.wxchat
  235. def check_and_manage_threads(self):
  236. while True:
  237. login_keys = list(redis_helper.redis_helper.client.scan_iter(match='__AI_OPS_WX__:LOGININFO:*'))
  238. for k in login_keys:
  239. r= redis_helper.redis_helper.get_hash(k)
  240. token_id = r.get('tokenId')
  241. app_id = r.get('appId')
  242. nickname=r.get('nickName')
  243. wxid = r.get('wxid')
  244. status=r.get('status')
  245. #print(status)
  246. if status == '1':
  247. #print(wxid not in self.add_contacts_from_group_worker_threads)
  248. if wxid not in self.add_contacts_from_group_worker_threads:
  249. print(f"微信 {wxid} 在线,创建群好友添加线程...")
  250. self.add_contacts_from_group_worker_threads[wxid] = threading.Thread(
  251. target=self.auto_add_contacts_from_group_worker,
  252. kwargs={"wxid":wxid, "token_id": token_id, "app_id": app_id} # wxid 作为关键字参数
  253. )
  254. self.add_contacts_from_group_worker_threads[wxid].start()
  255. if wxid not in self.sync_contacts_worker_threads:
  256. print(f"微信 {wxid} 在线,创建同步联系人任务...")
  257. self.sync_contacts_worker_threads[wxid] = threading.Thread(
  258. target=self.sync_contacts_processer,
  259. kwargs={"wxid":wxid, "token_id": token_id, "app_id": app_id}
  260. )
  261. self.sync_contacts_worker_threads[wxid].start()
  262. else:
  263. if wxid in self.add_contacts_from_group_worker_threads:
  264. print(f"微信 {wxid} 离线,关闭群好友添加线程...")
  265. self.add_contacts_from_group_worker_threads[wxid].join()
  266. del self.add_contacts_from_group_worker_threads[wxid]
  267. if wxid in self.sync_contacts_worker_threads:
  268. print(f"微信 {wxid} 离线,关闭同步联系线程线程...")
  269. self.sync_contacts_worker_threads[wxid].join()
  270. del self.sync_contacts_worker_threads[wxid]
  271. print('关闭线程')
  272. time.sleep(0)
  273. def auto_add_contacts_worker(self,wxid):
  274. while True:
  275. try:
  276. to_add_contact= self.wxchat.dequeue_to_add_contacts(wxid)
  277. if not to_add_contact:
  278. continue
  279. except Exception as e:
  280. logger.error(f'{wxid} 自动添加好友出错')
  281. def add_friends2(self,wxid):
  282. '''
  283. 24 小时只能加 5-15 位好友,每 2 小时不要超过 8 人,每个好友添加间隔要做随机间隔
  284. '''
  285. total_friends = 0
  286. start_time = time.time()
  287. last_friend_time = start_time
  288. while time.time() - start_time < 24 * 60 * 60: # 24 小时内
  289. # 每 2 小时内不超过 8 个好友
  290. if time.time() - last_friend_time < 2 * 60 * 60:
  291. if len([t for t in [last_friend_time] if t > time.time() - 2 * 60 * 60]) >= 8:
  292. time.sleep(1)
  293. continue
  294. # 添加好友
  295. print(f"添加好友 {total_friends + 1}")
  296. total_friends += 1
  297. # 随机间隔
  298. interval = random.randint(1, 10) * 60 # 1到10分钟的随机间隔
  299. time.sleep(interval)
  300. # 更新最后添加好友的时间
  301. last_friend_time = time.time()
  302. # 如果已经添加了 15 个好友,提前退出
  303. if total_friends >= 15:
  304. break
  305. def add_friends():
  306. total_friends = 0
  307. start_time = time.time()
  308. friend_times = [] # 用于记录每次添加好友的时间
  309. while time.time() - start_time < 24 * 60 * 60: # 24 小时内
  310. # 检查最近 2 小时内是否已经添加了 8 个好友
  311. current_time = time.time()
  312. recent_friends = [t for t in friend_times if t > current_time - 2 * 60 * 60]
  313. if len(recent_friends) >= 8:
  314. # 如果已经添加了 8 个好友,等待一段时间再检查
  315. time.sleep(1)
  316. continue
  317. # 添加好友
  318. print(f"添加好友 {total_friends + 1}")
  319. total_friends += 1
  320. # 记录添加好友的时间
  321. friend_times.append(current_time)
  322. # 随机间隔
  323. interval = random.randint(1, 10) * 60 # 1到10分钟的随机间隔
  324. time.sleep(interval)
  325. # 如果已经添加了 15 个好友,提前退出
  326. if total_friends >= 15:
  327. break
  328. def auto_add_contacts_from_group_worker(self,wxid, token_id, app_id):
  329. '''
  330. 从群添加好友任务
  331. '''
  332. while True:
  333. k, login_info = utils.get_login_info_by_wxid(wxid)
  334. if login_info.get('status') == "0":
  335. return
  336. c = self.wxchat.get_wxchat_config_from_cache(wxid)
  337. contacts = self.wxchat.get_contacts_brief_from_cache(wxid)
  338. contact_wxids = [c.get('userName') for c in contacts]
  339. chatrooms = c.get('addContactsFromChatroomIdWhiteList', [])
  340. for chatroom_id in chatrooms:
  341. chatroom = self.wxchat.get_group_info_from_cache(wxid, chatroom_id)
  342. chatroom_member=self.wxchat.get_group_members_from_cache(wxid, chatroom_id)
  343. chatroom_nickname = chatroom.get('nickName')
  344. chatroom_owner_wxid = chatroom_member.get('chatroomOwner', None)
  345. admin_wxid = chatroom_member.get('adminWxid', None)
  346. #logger.info(f'{chatroom_nickname} 的群主是 {chatroom_owner_wxid},管理员是{admin_wxid}')
  347. contact_wxids_set = set(contact_wxids)
  348. if admin_wxid is not None:
  349. contact_wxids_set.add(admin_wxid)
  350. if chatroom_owner_wxid is not None:
  351. contact_wxids_set.add(chatroom_owner_wxid)
  352. contact_wxids_set.add(wxid)
  353. unavailable_wixds=self.wxchat.check_wixd_group_add_contacts_history(wxid,chatroom_id)
  354. contact_wxids_set.update(unavailable_wixds)
  355. chatroot_member_list = chatroom.get('memberList', [])
  356. remaining_chatroot_members = [x for x in chatroot_member_list if x.get('wxid') not in contact_wxids_set]
  357. nickname = next((member['nickName'] for member in chatroot_member_list if member['wxid'] == wxid), None)
  358. #logger.info(f'{nickname}-{wxid} 在 {chatroom_nickname} 群里还可以邀请的好友有:{[x.get("nickName") for x in remaining_chatroot_members]}')
  359. for m in remaining_chatroot_members:
  360. tasks_id=f'{wxid}-{chatroom_id}-{m.get("wxid")}'
  361. if tasks_id not in self.add_group_member_as_friend_task_threads:
  362. self.add_group_member_as_friend_task_threads[tasks_id] =threading.Thread(target=self.add_group_member_as_friend_thread,
  363. args=(token_id, app_id, wxid,chatroom_id,m,nickname,chatroom_nickname,)
  364. )
  365. #self.add_group_member_as_friend_task_threads[tasks_id].daemon = True # 设置为守护线程
  366. self.add_group_member_as_friend_task_threads[tasks_id].start()
  367. time.sleep(0)
  368. def sync_contacts_processer(self,wxid, token_id, app_id):
  369. while True:
  370. k, login_info = utils.get_login_info_by_wxid(wxid)
  371. if login_info.get('status') == "0":
  372. print('sync_contacts_processer exit')
  373. #self.sync_contacts_task_threads[wxid].join()
  374. del self.sync_contacts_task_threads[wxid]
  375. return
  376. if wxid not in self.sync_contacts_task_threads:
  377. self.sync_contacts_task_threads[wxid]=threading.Thread(target=self.sync_contacts_threads_processer, args=(wxid,token_id,app_id))
  378. #self.sync_contacts_task_threads[wxid].daemon = True
  379. self.sync_contacts_task_threads[wxid].start()
  380. time.sleep(0)
  381. def sync_contacts_threads_processer(self,wxid, token_id, app_id):
  382. ret,msg,contacts_list = self.wxchat.fetch_contacts_list(token_id, app_id)
  383. if ret==200:
  384. friend_wxids = [c for c in contacts_list['friends'] if c not in ['fmessage', 'medianote','weixin','weixingongzhong']] # 可以调整截取范围
  385. print(f'{wxid}的好友数量 {len(friend_wxids)}')
  386. self.wxchat.save_contacts_brief_to_cache(token_id, app_id, wxid, friend_wxids)
  387. logger.info(f'微信ID {wxid} 登录APPID {app_id} 成功,联系人已定时保存')
  388. chatrooms=contacts_list['chatrooms']
  389. self.wxchat.save_groups_info_to_cache(token_id, app_id, wxid, chatrooms)
  390. self.wxchat.save_groups_members_to_cache(token_id, app_id, wxid, chatrooms)
  391. logger.info(f'微信ID {wxid} 登录APPID {app_id} 成功,群信息已定时保存')
  392. else:
  393. logger.warning(f'{msg}-微信ID {wxid} 登录APPID {app_id} 不能获取好友和群资料')
  394. time.sleep(random.uniform(3000, 3600))
  395. def add_group_member_as_friend_thread(self,token_id, app_id, wxid,chatroom_id,chatroot_member,nickname,chatroom_nickname):
  396. '''
  397. 从群添加好友线程,
  398. '''
  399. tasks_id=f'{wxid}-{chatroom_id}-{chatroot_member.get("wxid")}'
  400. k, login_info = utils.get_login_info_by_wxid(wxid)
  401. if login_info.get('status') == "0":
  402. del self.add_group_member_as_friend_task_threads[tasks_id]
  403. return
  404. contact_history=self.wxchat.get_group_add_contacts_history(wxid,chatroom_id,chatroot_member.get('wxid'))
  405. if len(contact_history)==1:
  406. last_contact_history=contact_history[0]
  407. diff_time=int(time.time())-last_contact_history.addTime
  408. oneday_seconds=60 * 60 * 24
  409. if diff_time<oneday_seconds:
  410. logging.info(f'{nickname}-{nickname} 向 {chatroom_nickname}-{chatroom_id} 群的 {chatroot_member.get("nickName")}-{ chatroot_member.get("wxid")} 第二次邀请好友,等待{oneday_seconds-diff_time}秒再执行')
  411. time.sleep(oneday_seconds-diff_time)
  412. ret, msg, data = self.wxchat.add_group_member_as_friend(token_id, app_id, chatroom_id, chatroot_member.get('wxid'), f'我是群聊"{chatroom_nickname}"群的{nickname}')
  413. if ret!=200:
  414. logger.info(f'群好友邀请失败原因:{data}')
  415. contact_wxids= chatroot_member.get('wxid')
  416. history=Models.AddGroupContactsHistory.model_validate({
  417. "chatroomId":chatroom_id,
  418. "wxid":wxid,
  419. "contactWixd":contact_wxids,
  420. "addTime":int(time.time())
  421. })
  422. self.wxchat.save_group_add_contacts_history(wxid,chatroom_id,contact_wxids,history)
  423. logger.info(f'{nickname} 向 {chatroom_nickname}-{chatroom_id} 群的 {chatroot_member.get("nickName")}-{chatroot_member.get("wxid")} 发送好友邀请 {msg}')
  424. time.sleep(random.uniform(5, 10))
  425. del self.add_group_member_as_friend_task_threads[tasks_id]
  426. app = Flask(__name__)
  427. # api = Api(app)
  428. flask_api = Api(app,errors=errors, catch_all_404s=True)
  429. # 设置日志(logger 已在 log.py 中配置)
  430. app.logger.handlers.clear() # 清除 Flask 默认的日志处理器
  431. app.logger.addHandler(logger.handlers[1]) # 使用文件日志处理器
  432. app.logger.setLevel(logging.DEBUG) # 设置日志级别
  433. # 添加拦截器
  434. app.before_request(before_request)
  435. app.after_request(after_request)
  436. app.register_error_handler(Exception, handle_exception)
  437. # 定义路由
  438. flask_api.add_resource(MessagesResource, '/messages')
  439. flask_api.add_resource(DeleteFriendResource, '/api/contacts/deletefriend')
  440. flask_api.add_resource(GetFriendsInfoResource, '/api/contacts/getfriends')
  441. flask_api.add_resource(GetWxchatConfigResource, '/api/wxchat/getconfig')
  442. flask_api.add_resource(SaveWxchatConfigResource, '/api/wxchat/saveconfig')
  443. flask_api.add_resource(GetGroupsInfoResource, '/api/groups/getchatroominfo')
  444. flask_api.add_resource(GetGroupMemberList,'/api/groups/getmenberlist')
  445. flask_api.add_resource(GetLoginInfoResource, '/api/agent/getlogin')
  446. flask_api.add_resource(GetLoginWxQRCodeResource, '/api/agent/getwxqrcode')
  447. flask_api.add_resource(LoginWxCaptchCodeResource, '/api/agent/logincaptchcode')
  448. flask_api.add_resource(SendSNSTextResource, '/api/sns/sendtext')
  449. flask_api.add_resource(SendSNSImageResource, '/api/sns/sendimages')
  450. flask_api.add_resource(SendSNSVideoResource, '/api/sns/sendvideo')
  451. load_config()
  452. kafka_helper.start()
  453. redis_helper.start()
  454. gewe_chat.start()
  455. wx_thread_manager=WechatThreadManager()
  456. #wx_thread_manager.check_and_manage_threads()
  457. start_kafka_consumer_thread()
  458. # background_wxchat_thread()
  459. threading.Thread(target=background_wxchat_thread).start()
  460. if __name__ == '__main__':
  461. # 获取环境变量
  462. environment = os.environ.get('environment', 'default')
  463. port = 80 if environment == 'default' else 5000
  464. app.run(debug=False, host='0.0.0.0', port=port)