1
0
mirror of https://github.com/wbt5/real-url.git synced 2025-08-01 14:48:01 +08:00
zhibo-url/danmu/danmaku/huajiao.py
2020-07-19 23:15:51 +08:00

219 lines
7.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from . import huajiao_pb2 as pb
import struct
import hashlib
import random
import string
import json
import time
class HuaJiao:
heartbeat = b'\x00\x00\x00\x00'
ws_url = 'wss://bridge.huajiao.com'
def __init__(self, rid=None):
self.sn = ''
self.tt = str(int(time.time() * 1000))
self.roomId = rid
self.flag = 'qh'
self.protocolVersion = 1
self.clientVersion = 101
self.appId = 2080
self.sender = self.password = '999' + self.tt + self.random_(6, 'n')
self.defaultKey = '3f190210cb1cf32a2378ee57900acf78'
def init_p(self):
p = pb.Message()
p.sn = int(self.random_(10, 'n'))
p.sender = self.sender
p.sender_type = 'jid'
return p
@staticmethod
def random_(num, var):
seq = ''
if var == 's':
seq = string.ascii_letters + string.digits
if var == 'n':
seq = string.digits
result = ''.join([random.choice(seq) for i in range(num)])
return result
@staticmethod
def md5(data):
return hashlib.md5(data.encode('utf-8')).hexdigest()
@staticmethod
def rc4(data, key):
a = [i for i in range(256)]
l = i = 0
while i < 256:
l = (l + a[i] + ord(key[i % len(key)])) % 256
a[i], a[l] = a[l], a[i]
i += 1
i = l = n = 0
s = len(data)
f = []
while n < s:
i = (i + 1) % 256
l = (l + a[i]) % 256
a[i], a[l] = a[l], a[i]
f.append(data[n] ^ a[(a[i] + a[l]) % 256])
n += 1
return bytes(f)
def sendHandshakePack(self):
HandshakePack = struct.pack('!2sbbhih', self.flag.encode(), self.protocolVersion << 4, self.clientVersion,
self.appId, 0, 0)
p = self.init_p()
self.sn = p.sn
p.msgid = 100009
p.req.init_login_req.client_ram = self.random_(10, 's')
p.req.init_login_req.sig = ''
data = p.SerializeToString()
a = self.rc4(data, self.defaultKey)
HandshakePack += struct.pack('!i', len(HandshakePack + a) + 4) + a
return HandshakePack
def processHandShakePack(self, message):
o, = struct.unpack('!2s', message[:2])
if o.decode() != self.flag:
raise Exception('processHandShakePack 服务器响应标识flag有误')
s = self.rc4(message[6:], self.defaultKey)
p = self.init_p()
try:
p.ParseFromString(s)
except:
raise Exception('processHandShakePack 解析消息体异常')
if p.msgid != 200009:
raise Exception('processHandShakePack 响应msgid异常')
if p.sn != self.sn:
raise Exception('processHandShakePack sn验证失败')
return p.resp
def sendLoginPack(self, message):
e = self.processHandShakePack(message)
u = e.init_login_resp.server_ram
secret_ram = self.rc4((u + self.random_(8, 's')).encode(), self.password)
verf_code = self.md5(self.sender + '360tantan@1408$')[24:]
p = self.init_p()
self.sn = p.sn
p.msgid = 100001
p.req.login.app_id = 2080
p.req.login.mobile_type = 'ios'
p.req.login.net_type = 4
p.req.login.not_encrypt = True
p.req.login.platform = 'h5'
p.req.login.server_ram = u
p.req.login.secret_ram = secret_ram
p.req.login.verf_code = verf_code
a = p.SerializeToString()
l = self.rc4(a, self.defaultKey)
LoginPack = struct.pack('!i', 4 + len(l)) + l
return LoginPack
def processLoginPack(self, message):
p = self.init_p()
try:
p.ParseFromString(self.rc4(message[4:], self.password))
except:
try:
p.ParseFromString(self.rc4(message[4:], self.defaultKey))
except:
raise Exception('processLoginPack 解析消息体异常')
if p.msgid != 200001:
raise Exception('processLoginPack 响应msgid异常')
if p.sn != self.sn:
raise Exception('processLoginPack sn验证失败')
return p
def sendJoinChatroomPack(self, message):
p = self.processLoginPack(message)
o = self.roomId.encode()
# crm : ChatroomRequestMessage
crm = pb.ChatRoomPacket()
crm.client_sn = p.sn
crm.roomid = o
crm.appid = self.appId
crm.uuid = self.md5(self.random_(10, 's') + '0000000001' + str(int(time.time() * 1000)))
crm.to_server_data.payloadtype = 102
crm.to_server_data.applyjoinchatroomreq.roomid = o
crm.to_server_data.applyjoinchatroomreq.room.roomid = o
crm.to_server_data.applyjoinchatroomreq.userid_type = 0
p = self.init_p()
self.sn = p.sn
p.msgid = 100011
p.req.service_req.service_id = 10000006
p.req.service_req.request = crm.SerializeToString()
u = p.SerializeToString()
JoinChatroomPack = struct.pack('!i', 4 + len(u)) + u
return JoinChatroomPack
def processMessagePack(self, message):
i, = struct.unpack_from('!i', message, 0)
if len(message) == 4 and i == 0: # HeartbeatPack
return None
p = self.init_p()
p.ParseFromString(message[4:])
o = p.msgid
if o == 200011:
return self.processService_RespMessage(p)
elif o == 300000:
return self.processNewMessageNotifyMessage(p)
else:
return None
def processService_RespMessage(self, p):
if p.sn != self.sn:
raise Exception('processService_RespMessage sn验证失败')
crp = pb.ChatRoomPacket()
crp.ParseFromString(p.resp.service_resp.response)
n = crp.to_user_data
r = i = ''
if n.payloadtype == 102 or n.applyjoinchatroomresp:
if n.result == 0:
r = n.applyjoinchatroomresp.room.properties[1].value
i = n.applyjoinchatroomresp.room.partnerdata
r = r.decode('utf-8')
i = i.decode('utf-8')
return r, i
def processNewMessageNotifyMessage(self, p):
crp = pb.ChatRoomPacket()
crp.ParseFromString(p.notify.newinfo_ntf.info_content)
r = crp.to_user_data
s = i = ''
if r.result == 0:
if r.payloadtype == 1000 and r.newmsgnotify:
s = r.newmsgnotify.memcount
i = r.newmsgnotify.msgcontent
elif r.payloadtype == 1001 and r.memberjoinnotify:
s = r.memberjoinnotify.room.properties[1].value
i = r.memberjoinnotify.room.members[0].userdata
elif r.payloadtype == 1002 and r.memberquitnotify:
s = r.memberquitnotify.room.properties[0].value
i = r.memberquitnotify.room.members[0].userdata
i = i.decode('utf-8')
i = json.loads(i)
return s, i
def decode_msg(self, message):
msgs = []
memcountmsg, msgcontent = self.processMessagePack(message)
if msgcontent.get('type') == 9:
name = msgcontent['extends']['nickname']
content = msgcontent['text']
msg = {'name': name, 'content': content, 'msg_type': 'danmaku'}
msgs.append(msg)
return msgs