/TCP_monitor.py

https://github.com/Dawnnnnnn/bilibili-live-tools · Python · 160 lines · 139 code · 16 blank · 5 comment · 30 complexity · acc567f2abf1b593d1814df95229ba85 MD5 · raw file

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2019/12/30 13:24
  4. # @Author : Dawnnnnnn
  5. # @Contact: 1050596704@qq.com
  6. import asyncio
  7. import json
  8. import traceback
  9. from struct import Struct
  10. from printer import Printer
  11. from rafflehandler import Rafflehandler
  12. class TCP_monitor():
  13. header_struct = Struct('>I')
  14. def __init__(self):
  15. self._reader = None
  16. self._writer = None
  17. self.connected = False
  18. def _encapsulate(self, str_body):
  19. body = str_body.encode('utf-8')
  20. len_body = len(body)
  21. len_header = 4
  22. header = self.header_struct.pack(len_body + len_header)
  23. return header + body
  24. def close_connection(self):
  25. self._writer.close()
  26. self.connected = False
  27. async def connectServer(self, host, port, key):
  28. while True:
  29. try:
  30. reader, writer = await asyncio.open_connection(host, port)
  31. self._reader = reader
  32. self._writer = writer
  33. Printer().printer(f'监控服务器连接成功', "Info", "green")
  34. await self.send_bytes(self.Auth_Key(key))
  35. self.connected = True
  36. except Exception:
  37. Printer().printer(f'连接无法建立,请检查本地网络状况,2s后重连', "Error", "red")
  38. self.connected = False
  39. await asyncio.sleep(2)
  40. continue
  41. await self.ReceiveMessageLoop()
  42. Printer().printer(f'与服务器连接断开,2s后尝试重连', "Error", "red")
  43. self.connected = False
  44. await asyncio.sleep(2)
  45. async def HeartbeatLoop(self):
  46. while True:
  47. try:
  48. while not self.connected:
  49. await asyncio.sleep(0.5)
  50. while self.connected:
  51. await self.send_bytes(self.Heartbeat())
  52. await asyncio.sleep(25)
  53. except:
  54. traceback.print_exc()
  55. def Auth_Key(self, key):
  56. dict_enter = {
  57. "cmd": "Auth",
  58. "data": {"key": key},
  59. "code": 0
  60. }
  61. str_enter = json.dumps(dict_enter)
  62. bytes_enter = self._encapsulate(str_body=str_enter)
  63. return bytes_enter
  64. def Heartbeat(self):
  65. dict_enter = {
  66. "cmd": "HeartBeat",
  67. "data": {},
  68. "code": 0
  69. }
  70. str_enter = json.dumps(dict_enter)
  71. bytes_enter = self._encapsulate(str_body=str_enter)
  72. return bytes_enter
  73. async def send_bytes(self, bytes_data) -> bool:
  74. try:
  75. self._writer.write(bytes_data)
  76. await self._writer.drain()
  77. except asyncio.CancelledError:
  78. return False
  79. except Exception:
  80. return False
  81. return True
  82. async def ReadSocketData(self):
  83. try:
  84. header = await asyncio.wait_for(self._reader.read(4), timeout=35.0)
  85. except Exception:
  86. Printer().printer("与服务器连接断开", "Error", "red")
  87. self.connected = False
  88. return False
  89. if len(header) == 0:
  90. return False
  91. try:
  92. len_body, = self.header_struct.unpack_from(header)
  93. except:
  94. Printer().printer(f"unpack_from出现错误,header:{header} len(header):{len(header)}", "Error", "red")
  95. self.connected = False
  96. return False
  97. if not len_body:
  98. return False
  99. try:
  100. body = await self._reader.read(len_body - 4)
  101. Printer().printer(f"接收到服务器的header数据{header} body数据{body}", "DEBUG", "yellow")
  102. except Exception:
  103. Printer().printer("与服务器连接断开", "Error", "red")
  104. self.connected = False
  105. return False
  106. if body is None:
  107. return False
  108. try:
  109. body = body.decode('utf-8')
  110. body = body.replace("True", "true").replace("False", "false").replace("None", "null")
  111. except:
  112. Printer().printer(f"body.decode出现错误,body:{body}", "Error", "red")
  113. self.connected = False
  114. return False
  115. try:
  116. json_data = json.loads(body)
  117. await self.parseDanMu(json_data)
  118. except Exception:
  119. Printer().printer(f"json.loads出现错误,body:{body}", "Error", "red")
  120. self.connected = False
  121. return False
  122. return True
  123. async def ReceiveMessageLoop(self):
  124. while self.connected:
  125. tmp = await self.ReadSocketData()
  126. if not tmp:
  127. break
  128. async def parseDanMu(self, dic):
  129. cmd = dic.get('cmd')
  130. if cmd is None:
  131. Printer().printer(dic, "Error", "red")
  132. return
  133. if cmd == 'HeartBeat':
  134. pass
  135. elif cmd == 'Storm':
  136. pass
  137. elif cmd == 'Guard':
  138. pass
  139. elif cmd == 'PKLottery':
  140. pass
  141. elif cmd == 'Raffle':
  142. Rafflehandler().append2list_TV(dic["data"]["RoomId"])
  143. else:
  144. Printer().printer(dic, "Info", "green")