telegram 群组监控 / 群组功能
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
13 KiB

8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
  1. # code=utf-8
  2. import os, sys
  3. from telethon.tl.functions.channels import JoinChannelRequest
  4. from tg_module.initial_group import join_channel
  5. from tg_utils.tg_model import GroupFunc
  6. root_path = os.path.abspath(os.path.dirname(__file__)).split('telegram_crawler')[0] + "telegram_crawler"
  7. sys.path.append(root_path)
  8. from utils.MysqlData import MysqlPoolClient
  9. from utils.push_kafka import SKafka
  10. from telethon import TelegramClient, events
  11. import json
  12. from telethon.sessions import StringSession
  13. from telethon.tl.types import User, ChatAdminRights, Updates, Channel
  14. import time
  15. from config import logger, SESSION_STRING, API_ID, API_HASH, PROXY, TOPIC_ADDRESS, TOPIC_DIC, CRAWLER_DB_CONF, \
  16. TG_ROBOT_ACCOUNT_TABLE
  17. import telethon, asyncio
  18. from tg_utils.tg_api import *
  19. from utils.upload_files import upload_file
  20. from telethon.sync import TelegramClient as SyncTelegramClient
  21. """
  22. nohup python receive_message.py > rece.log 2>&1 &
  23. """
  24. def get_group(api_id):
  25. """
  26. TODO:sql读取
  27. :return:
  28. """
  29. group_ids = []
  30. logger.success(f"load group lengths {len(group_ids) if group_ids else 0}")
  31. logger.success(f"load group: {group_ids}")
  32. return group_ids
  33. def push_kafka(kp, data, topic):
  34. """
  35. kafka推送
  36. :param kp:
  37. :param data:
  38. :param topic:
  39. :return:
  40. """
  41. try:
  42. if isinstance(data, list):
  43. kp.sync_producer(topic, data)
  44. else:
  45. kp.sync_producer(topic, [data])
  46. except Exception as e:
  47. logger.error(f"数据推送失败:{data}")
  48. logger.error(f"kafka error: {e}")
  49. async def update_filename(message, media, file="resources"):
  50. """
  51. :param message:
  52. :param media:
  53. :param file:
  54. :return:
  55. """
  56. file_type = telethon.utils.get_extension(media)
  57. logger.info(f"捕获文件类型:{file_type}")
  58. if "." in file_type: # 修改文件名称
  59. time_stamp = str(int(time.time()))
  60. file = f"{file}/{time_stamp}_{message.id}{file_type}"
  61. filename = await download_media(message, file=file)
  62. upload_path = await upload_file(filename) # 上传文件
  63. return upload_path
  64. else:
  65. filename = await download_media(message)
  66. upload_path = await upload_file(filename) # 上传文件
  67. return upload_path
  68. async def download_resources(message, media, client, sender, file="resources"):
  69. """
  70. :param message:
  71. :param media:
  72. :param client:
  73. :param sender:
  74. :param file:
  75. :return:
  76. """
  77. new_file_name = None # 对于没有媒体类的消息 直接不下载了
  78. if media:
  79. file_type = telethon.utils.get_extension(media)
  80. # logger.info(f"捕获文件类型:{file_type}")
  81. if "." in file_type: # 能识别出来类型的 修改文件名称
  82. time_stamp = str(int(time.time()))
  83. new_file_name = f"{file}/{time_stamp}_{message.id}{file_type}"
  84. else:
  85. new_file_name = file
  86. # 下载telegram 媒体类文件
  87. media_path, photo_path = await asyncio.gather(
  88. download_media(message, file=new_file_name), # 媒体文件下载
  89. download_profile_photo(client, sender) # 下载头像
  90. )
  91. logger.info(f"下载媒体文件路径:{media_path} ; 下载头像文件路径:{photo_path} ;")
  92. # 上传go-fast
  93. upload_media_path, upload_photo_path = await asyncio.gather(
  94. upload_file(media_path),
  95. upload_file(photo_path)
  96. )
  97. logger.info(f"go-fast媒体文件路径:{upload_media_path} ; go-fast头像路径:{upload_photo_path} ;")
  98. return upload_media_path, upload_photo_path
  99. async def main(session_string, api_id, api_hash, kp=None, message_topic=""):
  100. session = StringSession(session_string)
  101. # session = session_string
  102. logger.info(f"客户端 {api_id} 启动!!!!")
  103. client = TelegramClient(session, api_id, api_hash, timeout=60, proxy=PROXY)
  104. await client.start()
  105. @client.on(events.NewMessage(chats=get_group(api_id), incoming=True))
  106. async def handler(event):
  107. """
  108. chats控制
  109. :param event:
  110. :return:
  111. """
  112. sender = await event.get_sender() # 群组接受的为user 频道则接受的为频道
  113. chat = await event.get_chat()
  114. logger.info(f"测试 sender: {sender}")
  115. logger.info(f"测试 chat: {chat}")
  116. if not sender:
  117. logger.info(f" 不存在发送者 群组异常: {chat}")
  118. logger.info(f"meesages: {event}")
  119. logger.info(f"messages: {event.message}")
  120. return
  121. if isinstance(sender, User):
  122. sender_name = str(sender.first_name) + ' ' + str(sender.last_name)
  123. else: # 如果是频道的话 发送者是以频道为对象发送
  124. sender_name = sender.title
  125. message = event.message
  126. media = event.media
  127. other_link = await get_extra_linked(message) # 获得超链接
  128. # file_list, user_photo = await download_resources(message, media, client, sender)
  129. file_list, user_photo = None, None
  130. message_text = message.message
  131. date = message.date
  132. replay = message.reply_to # MessageReplyHeader 对象
  133. data = {
  134. "group_title": chat.title,
  135. "group_id": -1000000000000 - chat.id,
  136. "username": str(chat.username),
  137. "sender_name": sender_name,
  138. "sender_id": str(sender.id),
  139. "media": file_list,
  140. "sender_photo": user_photo,
  141. "message_id": message.id,
  142. "reply_to_msg_id": replay.reply_to_msg_id if replay else None, # 这个字段是针对某一条聊天记录的回复 *****
  143. "reply_to_top_id": replay.reply_to_top_id if replay else None, # 这个字段是针对频道内的讨论组 针对的某一条聊天内容发起的讨论
  144. "message_text": message_text,
  145. "other_link": other_link, # 聊天过程中的超链接 以及对应的位置
  146. "datetime": date.strftime("%Y-%m-%d %H:%M:%S")
  147. }
  148. logger.debug(f"client: {api_id} ; data: {data}")
  149. # logger.debug(f"message: {message}")
  150. # push_kafka(kp, json.dumps(data, ensure_ascii=False), message_topic)
  151. if client:
  152. logger.info("client start")
  153. await client.run_until_disconnected()
  154. async def _join_group(session_string, api_id, api_hash):
  155. """
  156. :param session_string:
  157. :param api_id:
  158. :param api_hash:
  159. :return:
  160. """
  161. session = StringSession(session_string) # 通过session字符串来登陆 也可通过本地文件登陆(不推荐)
  162. client = TelegramClient(session, api_id, api_hash, timeout=60, proxy=PROXY)
  163. await client.start()
  164. channel = "saudovskayaaraviya_rabota" # 加群测试demo
  165. res = await client(JoinChannelRequest(channel=channel))
  166. print(res)
  167. if isinstance(res, Updates):
  168. chats = res.chats
  169. result = {"title": res.chats[0].title, "group_id": -1000000000000 - res.chats[0].id}
  170. print(chats)
  171. if isinstance(chats[0], Channel):
  172. channel_obj = chats[0]
  173. rights = channel_obj.default_banned_rights # 群组默认的权限对象
  174. result["allow_sending"] = False
  175. if rights: # 目前发现只有群组存在这个值
  176. if (not rights.send_messages) and (not rights.send_photos) and (not rights.send_plain):
  177. print("允许发送 图文信息")
  178. result["allow_sending"] = False
  179. print(f"加群返回结果:{result}")
  180. async def _replay_demo(session_string, api_id, api_hash):
  181. session = StringSession(session_string) # 通过session字符串来登陆 也可通过本地文件登陆(不推荐)
  182. client = TelegramClient(session, api_id, api_hash, timeout=60, proxy=PROXY)
  183. await client.start()
  184. # TODO: 实现判断是否能在群里发消息以及发消息
  185. channel = "teleSUR_tv" # 频道demo broadcast
  186. # channel = "xeqm3333" # 群组demo megagroup send_plain=True/send_photos=False 可以发
  187. # channel = "Pakistanichatgingroup" # 群组demo
  188. channel = "tvhd02"
  189. # channel = 'MarketingTools2024' # 群组demo 啥都不允许发
  190. # channel = 'ali_the_esq'
  191. # channel = "+86 184 4310 4914"
  192. # channel = "appics_official"
  193. # channel = "saudovskayaaraviya_rabota"
  194. channel = "MarketingTools2024"
  195. group_entity = await client.get_entity(channel) # 获取群组类型
  196. print(group_entity)
  197. res = {"allow_sending": {}}
  198. print(res)
  199. res["allow_sending"] = await GroupFunc.get_group_rights(client, group_entity)
  200. print(res)
  201. if "+" not in channel:
  202. # print(f"群组信息 {group_entity}")
  203. print(group_entity.default_banned_rights)
  204. if group_entity.broadcast:
  205. print(f" 当前群组为 频道 => {channel}")
  206. else:
  207. a = await client.get_permissions(group_entity, 'me') # 确定是不是管理员禁止发送消息
  208. print(a.is_banned)
  209. # print(group_entity.admin_rights)
  210. print(group_entity.default_banned_rights)
  211. print(f" send_plain => {group_entity.default_banned_rights.send_plain}")
  212. print(f" send_photos => {group_entity.default_banned_rights.send_photos}")
  213. # if group_entity.default_banned_rights:
  214. # # TODO: 测试发送类型 图片 send_photos/ 消息 send_plain
  215. # pass
  216. # 发送文件
  217. # file_path = "resources/b0a26d56a34a1840fe68e5314b3a70e5.jpeg"
  218. # with open(file_path, "r", encoding="utf-8") as f:
  219. # content = f.read()
  220. # content = 'http://172.18.1.180:9980/group17/default/20240507/17/07/3/image.jpg'
  221. # res = await client.send_message(group_entity, "<b> ni hao wa </b>", file=content)
  222. # res = await client.send_file(group_entity, file_path)
  223. # f.close()
  224. # res = await client.send_message(group_entity, file=file_path)
  225. # res = await client.send_message(group_entity, "hello")
  226. # print(res)
  227. await client.disconnect()
  228. async def leave_group(session_string, api_id, api_hash):
  229. session = StringSession(session_string) # 通过session字符串来登陆 也可通过本地文件登陆(不推荐)
  230. client = TelegramClient(session, api_id, api_hash, timeout=60, proxy=PROXY)
  231. await client.start()
  232. dialogs = await client.get_dialogs() # 获取所有群组的 ID 和名称
  233. print(f" 一共有 =》 {len(dialogs)}")
  234. for i in range(len(dialogs)):
  235. print(f"删除 =》 {dialogs[i]}")
  236. await client.delete_dialog(dialogs[i])
  237. time.sleep(5)
  238. await client.disconnect()
  239. async def login():
  240. # api_id = "28340634"
  241. # api_hash = "5c54ebfc2729b32bc6f49e4b34747f47"
  242. data = {'id': 2, 'phone': '18846824798', 'api_id': '22955009',
  243. 'api_hash': 'c5581d1ed5880f6e0b1734dad1d4a10d',
  244. 'session_string': '1BVtsOIEBuwG1-0k5xGzlopl4G7ghAhBPorz1HcaSkfcuDEsYKSJKQ0nCLYbMTT7yplnfJHEYXR-rGY5FoEyrAYsW86obngGwxLDpl9b9IuGhxCDlFSo_O2AIPw3Duf8tc5DewfNGqZ7U8CbpEjFcpEaRRy23Z93DVZtcYHBLp6vLh5iLndKXanW4vxArJODjVklAKwxqDD5LGixvoeP5p9W1VJAeihJxqEl0UHL12dF4T7MYcdhW-ylA4NvCtgeIaqiVwZ1VuVyiyLNYaMrpZZfdmfOGkYapp-1ubYE8XKAQ8jau3XnWCLvk50w6L9DaWp8PSdQ7RRZf5G2swSyurHCK6quAVfA=',
  245. 'plateform': 'DeskTop', 'total_group': 274}
  246. session = StringSession(data["session_string"])
  247. client = TelegramClient(session, data["api_id"], data["api_hash"], timeout=60, proxy=PROXY)
  248. print(client)
  249. await client.start()
  250. # client = SyncTelegramClient("session_name", data["api_id"], data["api_hash"], timeout=60)
  251. # await client.start()
  252. print(StringSession.save(client.session))
  253. print("连接成功")
  254. await client.disconnect()
  255. async def mul_account():
  256. tasks = []
  257. api_id = "28279639"
  258. api_hash = "dc7eb234661a51bfd723ecd201797e1a"
  259. # session_string = "demo1"
  260. session_string = "1BVtsOMUBu6HAZK23ZSobi4_zwJPrKdjckKtX3NzXA6mj26BaZTQ3fGlhKNke-A7unmk2mH4ESMi7mfQx2vvogezgj8C-W7VO2V_91vTIZv-crQ3yaQNMSwwEJaOYRmCr5SrLV1cILYP0bgP0o2Sr-KIP82Z0mDxfJycW0q65liB3W_nZMqiO2131QK8_Nq_MEYrG8uKj6rV8XQOcSTZYmu27_dHz_elbJMrJZvcFGCg3l7EtoZr7VlQDcUP_4wfoSHWGqOuipxnnmZbd97mZENrTsfPdJNdX_vI7QPRrK69p2mwmlXQ6Waj_6zKp3nHNQPSuK4Athiy6Fcle8TZ9BRQep8IryxA="
  261. tasks.append(main(session_string, api_id, api_hash))
  262. # tasks.append(login())
  263. # tasks.append(_replay_demo(session_string, api_id, api_hash))
  264. # tasks.append(_join_group(session_string, api_id, api_hash))
  265. # tasks.append(leave_group(session_string, api_id, api_hash))
  266. logger.info(f"获得任务数量 {len(tasks)}")
  267. await asyncio.gather(*tasks)
  268. if __name__ == '__main__':
  269. # main()
  270. loop = asyncio.get_event_loop()
  271. try:
  272. loop.run_until_complete(mul_account())
  273. except Exception as e:
  274. print(f"An error occurred: {e}")
  275. # mul_account()
  276. # pass