5 Commits

12 changed files with 226 additions and 102 deletions

10
Chat.py
View File

@ -1,19 +1,27 @@
from User import User from User import User
from Lottery import Lottery
class Chat: class Chat:
content: str ="" content: str =""
user: User=None user: User=None
filterString:list = ["",]
isFiltered = False
def __init__(self, json=None): def __init__(self, json=None, lottery:Lottery = None):
if json: if json:
self.parse(json) self.parse(json)
if lottery:
self.filterString.append(lottery.content)
def parse(self, json): def parse(self, json):
self.user = User(json) self.user = User(json)
if "extra" in json: if "extra" in json:
if "content" in json["extra"]: if "content" in json["extra"]:
self.content = json["extra"]['content'] self.content = json["extra"]['content']
if self.content in self.filterString:
self.isFiltered = True
def __str__(self): def __str__(self):
return "{} : {}".format(self.user,self.content) return "{} : {}".format(self.user,self.content)

0
Digg.py Normal file
View File

14
Gift.py
View File

@ -16,7 +16,11 @@ class Gift:
def parse(self, json): def parse(self, json):
self.user = User(json) self.user = User(json)
if "extra" in json: if "common" in json and json["common"] is not None:
if Gift.roomID != int(json["common"]["room_id"]):
Gift.roomID = int(json["common"]["room_id"])
self.update()
if "extra" in json and json["extra"] is not None:
if "present_info" in json["extra"] and json["extra"]['present_info'] is not None: if "present_info" in json["extra"] and json["extra"]['present_info'] is not None:
self.ID = int(json["extra"]['present_info']['id']) self.ID = int(json["extra"]['present_info']['id'])
self.count = json["extra"]['present_info']['repeat_count'] self.count = json["extra"]['present_info']['repeat_count']
@ -25,11 +29,11 @@ class Gift:
self.count = json["extra"]['present_end_info']['count'] self.count = json["extra"]['present_end_info']['count']
if self.ID in self.giftList: if self.ID in self.giftList:
self.amount = self.giftList[self.ID]["Price"] * self.count self.amount = self.giftList[self.ID]["Price"] * self.count
else:
self.update()
@staticmethod def update(self):
def update(roomID): p = requests.get("https://i.snssdk.com/videolive/gift/get_gift_list?room_id={roomID}".format(roomID = self.roomID))
Gift.roomID = roomID
p = requests.get("https://i.snssdk.com/videolive/gift/get_gift_list?room_id={roomID}".format(roomID= roomID))
d = p.json() d = p.json()
if "gift_info" not in d: if "gift_info" not in d:
print("错误:礼物更新失败") print("错误:礼物更新失败")

58
Lottery.py Normal file
View File

@ -0,0 +1,58 @@
import requests
from LuckyUser import LuckyUser
class Lottery:
ID: int = 0
isActive = False
content = ""
isFinished = False
luckyUsers = []
joinedUserCount = 0
prizeName = ""
def __init__(self, json=None):
if json:
self.parse(json)
def parse(self, json):
if "lottery_info" not in json or json["lottery_info"] is not None:
self.isActive = int(json["lottery_info"]["status"]) > 0
self.ID = json["lottery_info"]["lottery_id"]
for i in json["lottery_info"]['conditions']:
if i['type'] != 3:
continue
self.content = i["content"]
self.joinedUserCount = int(json["lottery_info"]["candidate_num"])
self.prizeName = json["lottery_info"]["prize_info"]["name"]
def checkFinished(self):
p = requests.get("https://i.snssdk.com/videolive/lottery/check_user_right?lottery_id={}"
"&version_code=730&device_platform=android".format(
self.ID
))
d = p.json()
if d["base_resp"]["status_code"] != 0:
self.isActive = False
self.isFinished = False
return
self.isActive = int(d["lottery_info"]["status"]) == 1
self.isFinished = int(d["lottery_info"]["status"]) == 2
self.joinedUserCount = int(d["lottery_info"]["candidate_num"])
if self.isFinished:
for i in d["lottery_info"]["lucky_users"]:
self.luckyUsers.append(LuckyUser(i))
def __str__(self):
if self.isFinished:
ret = "恭喜以下中奖用户:\n"
for i in self.luckyUsers:
ret += "> {} {}\n".format(i,self.prizeName)
ret += "> 参与人数:{}".format(self.joinedUserCount)
return ret
elif self.isActive:
return "正在抽奖中。。。\n" \
"> 参与人数:{}".format(self.joinedUserCount)
else:
return "抽奖已失效"

19
LuckyUser.py Normal file
View File

@ -0,0 +1,19 @@
from User import User
class LuckyUser:
user = None
count = 0
def __init__(self, json=None):
if json:
self.parse(json)
def parse(self, json):
self.user = User()
self.user.ID = json['user_id']
self.user.name = json['user_name']
self.count = int(json["grant_count"])
def __str__(self):
return "用户 {} 获得了 {}".format(self.user,self.count)

View File

@ -28,7 +28,8 @@ class MemberMsg:
elif self.type == 1: elif self.type == 1:
return "{} 进入了房间".format(self.user) return "{} 进入了房间".format(self.user)
else: else:
print(self.type) if self.content == "":
return "未知消息{} 关于用户 {}".format(self.type, self.user)
return self.content.format(self.user) return self.content.format(self.user)
def __unicode__(self): def __unicode__(self):

View File

@ -4,10 +4,11 @@
界面版:[q792602257/XiguaDanmakuHelperGUI](https://github.com/q792602257/XiguaDanmakuHelperGUI "C# ver") 界面版:[q792602257/XiguaDanmakuHelperGUI](https://github.com/q792602257/XiguaDanmakuHelperGUI "C# ver")
### 计划更新: ### 计划更新:
+ Digg消息点亮了喜欢实例化
+ √ ~~使用android app协议~~ + √ ~~使用android app协议~~
已使用 已使用
除从用户ID获取roomID及判断是否在播其他均改为Android Api 除从用户ID获取roomID外其他均改为Android Api
+ √ ~~闲的无聊的时候看一看有没有好用的GUI轮子可以用用~~ + √ ~~闲的无聊的时候看一看有没有好用的GUI轮子可以用用~~

12
User.py
View File

@ -23,10 +23,14 @@ class User:
self.type = json["extra"]["user_room_auth_status"]["user_type"] self.type = json["extra"]["user_room_auth_status"]["user_type"]
self.block = json["extra"]["user_room_auth_status"]["is_block"] self.block = json["extra"]["user_room_auth_status"]["is_block"]
self.mute = json["extra"]["user_room_auth_status"]["is_silence"] self.mute = json["extra"]["user_room_auth_status"]["is_silence"]
elif "data" in json: elif "room" in json and json["room"] is not None:
if "anchorInfo" in json["data"]: if "user_info" in json["room"] and json["room"]["user_info"] is not None:
self.ID = json["data"]['anchorInfo']['id'] self.ID = json["room"]['user_info']['user_id']
self.name = json["data"]['anchorInfo']['name'] self.name = json["room"]['user_info']['name']
elif "anchor" in json and json["anchor"] is not None:
if "user_info" in json["anchor"] and json["anchor"]['user_info'] is not None:
self.ID = json["anchor"]['user_info']['user_id']
self.name = json["anchor"]['user_info']['name']
if self.type is None: if self.type is None:
self.type = 0 self.type = 0
if isinstance(self.level, str): if isinstance(self.level, str):

View File

@ -3,9 +3,9 @@ import sys
import time import time
from Gift import Gift from Gift import Gift
from Lottery import Lottery
from MemberMsg import MemberMsg from MemberMsg import MemberMsg
from User import User from User import User
from Chat import Chat from Chat import Chat
from api import XiGuaLiveApi as Api from api import XiGuaLiveApi as Api
import msvcrt import msvcrt
@ -31,7 +31,9 @@ def readInput(caption, default, timeout: int = 5):
msvcrt.putch(b"\b") msvcrt.putch(b"\b")
if len(input) == 0: if len(input) == 0:
start_time = time.time() start_time = time.time()
elif 32 <= ord(chr) <= 126: # space_char elif 32 > ord(chr) or 255 > ord(chr) > 126: # space_char
continue
else:
input += chr.decode("utf8") input += chr.decode("utf8")
if len(input) == 0 and (time.time() - start_time) > timeout: if len(input) == 0 and (time.time() - start_time) > timeout:
break break
@ -119,7 +121,7 @@ class WinMain(Api):
def onJoin(self, user: User): def onJoin(self, user: User):
set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK) set_cmd_text_color(BACKGROUND_WHITE | FOREGROUND_BLACK)
print("感谢", user, "加入了粉丝团") print("欢迎", user, "加入了粉丝团")
resetColor() resetColor()
def onSubscribe(self, user: User): def onSubscribe(self, user: User):
@ -136,8 +138,15 @@ class WinMain(Api):
def onChat(self, chat: Chat): def onChat(self, chat: Chat):
if SHOW_ALL: if SHOW_ALL:
resetColor()
if not chat.isFiltered:
print(chat) print(chat)
def onLottery(self, i:Lottery):
set_cmd_text_color(FOREGROUND_WHITE | BACKGROUND_DARKGRAY)
print(i)
resetColor()
def onPresent(self, gift: Gift): def onPresent(self, gift: Gift):
if SHOW_ALL: if SHOW_ALL:
set_cmd_text_color(FOREGROUND_DARKGRAY) set_cmd_text_color(FOREGROUND_DARKGRAY)
@ -164,24 +173,14 @@ def warning(*args):
if __name__ == "__main__": if __name__ == "__main__":
room = 97621754276 # 永恒 name = "永恒de草薙"
# room = 75366565294
# room = 83940182312 #Dae
resetColor() resetColor()
print("西瓜直播弹幕助手 by JerryYan") print("西瓜直播弹幕助手 by JerryYan")
if len(sys.argv) > 1: if len(sys.argv) > 1:
if sys.argv[-1] == "a": name = sys.argv[1]
SHOW_ALL = True
try:
room = int(sys.argv[1])
except:
pass
else: else:
try: name = readInput("请输入主播用户名(请用拼音字母),默认为", name, 3)
room = int(readInput("请输入用户ID号默认为永恒的ID号", room, 3)) api = WinMain(name)
except ValueError:
pass
api = WinMain(room)
print("进入", api.roomLiver, "的直播间") print("进入", api.roomLiver, "的直播间")
if not api.isValidRoom: if not api.isValidRoom:
input("房间不存在") input("房间不存在")
@ -190,11 +189,11 @@ if __name__ == "__main__":
print("=" * 30) print("=" * 30)
while True: while True:
if api.isLive: if api.isLive:
try:
os.system("title {}".format(api.getTitle())) os.system("title {}".format(api.getTitle()))
try:
api.getDanmaku() api.getDanmaku()
except Exception as e: except Exception as e:
warning(e) print(e.__str__())
time.sleep(1) time.sleep(1)
else: else:
set_cmd_text_color(FOREGROUND_RED) set_cmd_text_color(FOREGROUND_RED)

133
api.py
View File

@ -4,6 +4,7 @@ from MemberMsg import MemberMsg
from User import User from User import User
from Gift import Gift from Gift import Gift
from Chat import Chat from Chat import Chat
from Lottery import Lottery
import requests import requests
import time import time
@ -16,18 +17,18 @@ class XiGuaLiveApi:
isLive: bool = False isLive: bool = False
isValidRoom: bool = False isValidRoom: bool = False
_rawRoomInfo = {} _rawRoomInfo = {}
name: str = ""
roomID: int = 0 roomID: int = 0
roomTitle: str = "" roomTitle: str = ""
roomLiver: User = None roomLiver: User = None
roomPopularity: int = 0 roomPopularity: int = 0
roomMember: int = 0
_cursor:str = "0" _cursor:str = "0"
_updRoomCount:int = 0
lottery:Lottery = None
def __init__(self, room: int): def __init__(self, name: str = "永恒de草薙"):
self.room = room self.name = name
self.updRoomInfo() self.updRoomInfo()
Gift.update(self.roomID)
self._enterRoom()
def _updateRoomInfo(self, json): def _updateRoomInfo(self, json):
if "extra" in json: if "extra" in json:
@ -52,6 +53,7 @@ class XiGuaLiveApi:
pass pass
def onChat(self, chat: Chat): def onChat(self, chat: Chat):
if not chat.isFiltered:
print(chat) print(chat)
def onEnter(self, msg: MemberMsg): def onEnter(self, msg: MemberMsg):
@ -61,7 +63,7 @@ class XiGuaLiveApi:
print("消息 :", user, "关注了主播") print("消息 :", user, "关注了主播")
def onJoin(self, user: User): def onJoin(self, user: User):
print("感谢", user, "加入了粉丝团") print("欢迎", user, "加入了粉丝团")
def onMessage(self, msg: str): def onMessage(self, msg: str):
print("消息 :", msg) print("消息 :", msg)
@ -70,50 +72,76 @@ class XiGuaLiveApi:
print("用户", user, "点了喜欢") print("用户", user, "点了喜欢")
def onLeave(self, json: any): def onLeave(self, json: any):
print("消息 :", "主播离开一小会") print("消息 :", "主播离开")
def _enterRoom(self): def onLottery(self, i:Lottery):
if not self.isValidRoom: print("中奖消息 :", i)
return
p = s.post("https://i.snssdk.com/videolive/room/enter&version_code=730" def updRoomInfo(self):
if self.isLive:
p = s.post("https://i.snssdk.com/videolive/room/enter?version_code=730"
"&device_platform=android", "&device_platform=android",
data="room_id={roomID}&version_code=730" data="room_id={roomID}&version_code=730"
"&device_platform=android".format(roomID=self.roomID), "&device_platform=android".format(roomID=self.roomID),
headers={"Content-Type":"application/x-www-form-urlencoded"}) headers={"Content-Type":"application/x-www-form-urlencoded"})
if DEBUG:
print(p.text)
def searchLive(self, keyword):
ret = []
p = s.get("https://security.snssdk.com/video/app/search/live/?version_code=730&device_platform=android"
"&format=json&keyword={}".format(keyword))
d = p.json() d = p.json()
if "data" not in d: self.isValidRoom = d["base_resp"]["status_code"] == 0
if d["base_resp"]["status_code"] != 0:
return False
if "room" not in d and d["room"] is None:
self.apiChangedError("Api发生改变请及时联系我")
return False
self._rawRoomInfo = d["room"]
self.isLive = d["room"]["status"] == 2
self.roomLiver = User(d)
self.roomTitle = d["room"]["title"]
self.roomPopularity = d["room"]["user_count"]
l = Lottery(d)
if l.isActive:
self.lottery = l
return True
else:
p = s.get("https://security.snssdk.com/video/app/search/live/?version_code=730&device_platform=android"
"&format=json&keyword={}".format(self.name))
d = p.json()
if "data" in d:
for i in d["data"]: for i in d["data"]:
if i["block_type"] != 2: if i["block_type"] != 0:
continue continue
for _i in i["cells"]: if len(i["cells"]) == 0:
ret.append(_i["room"]) return
return ret self.isLive = i["cells"][0]["anchor"]["user_info"]["is_living"]
self.roomID = int(i["cells"][0]["anchor"]["room_id"])
self.roomLiver = User(i["cells"][0])
if self.isLive:
return self.updRoomInfo()
else:
return False
def updRoomInfo(self): @staticmethod
p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=self.room)) def findRoomByUserId(userId:int):
p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=userId))
if DEBUG: if DEBUG:
print(p.text) print(p.text)
d = p.json() d = p.json()
if "data" not in d or "title" not in d["data"] or "id" not in d["data"]: if "data" not in d or "title" not in d["data"] or "id" not in d["data"]:
self.apiChangedError("无法获取RoomID请与我联系") XiGuaLiveApi.apiChangedError("无法获取RoomID请与我联系")
return return XiGuaLiveApi()
self.isValidRoom = True return XiGuaLiveApi(d["data"]["id"])
self._rawRoomInfo = d["data"]
self.roomLiver = User(d) @staticmethod
self.roomTitle = d["data"]["title"] def searchLive(keyword):
self.roomID = d["data"]["id"] ret = []
self._updateRoomInfo(d) p = s.get("https://security.snssdk.com/video/app/search/live/?version_code=730&device_platform=android"
if "status" in d["data"] and d["data"]["status"] == 2: "&format=json&keyword={}".format(keyword))
self.isLive = True d = p.json()
else: if "data" in d:
self.isLive = False for i in d["data"]:
if i["block_type"] != 0:
continue
for _i in i["cells"]:
ret.append(_i["room"])
return ret
def getDanmaku(self): def getDanmaku(self):
if not self.isValidRoom: if not self.isValidRoom:
@ -133,9 +161,6 @@ class XiGuaLiveApi:
self._cursor = d["extra"]["cursor"] self._cursor = d["extra"]["cursor"]
if DEBUG: if DEBUG:
print("Cursor", self._cursor) print("Cursor", self._cursor)
if len(d['data']) == 0:
self.updRoomInfo()
return
for i in d['data']: for i in d['data']:
if DEBUG: if DEBUG:
print(i) print(i)
@ -148,7 +173,7 @@ class XiGuaLiveApi:
elif i["common"]['method'] == "VideoLiveRoomAdMessage": elif i["common"]['method'] == "VideoLiveRoomAdMessage":
self.onAd(i) self.onAd(i)
elif i["common"]['method'] == "VideoLiveChatMessage": elif i["common"]['method'] == "VideoLiveChatMessage":
self.onChat(Chat(i)) self.onChat(Chat(i, self.lottery))
elif i["common"]['method'] == "VideoLiveMemberMessage": elif i["common"]['method'] == "VideoLiveMemberMessage":
self._updateRoomInfo(i) self._updateRoomInfo(i)
self.onEnter(MemberMsg(i)) self.onEnter(MemberMsg(i))
@ -162,25 +187,31 @@ class XiGuaLiveApi:
self.onLike(User(i)) self.onLike(User(i))
else: else:
pass pass
self._updRoomCount += 1
if self._updRoomCount > 120 or len(d['data']) == 0:
if self.lottery is not None:
self.lottery.checkFinished()
if self.lottery.isFinished:
self.onLottery(self.lottery)
self.lottery = None
self.updRoomInfo()
self._updRoomCount = 0
return
if __name__ == "__main__": if __name__ == "__main__":
room = 97621754276 # 永恒 name = "永恒de草薙"
# room = 75366565294 if len(sys.argv) > 2:
# room = 83940182312 #Dae
if len(sys.argv) > 1:
if sys.argv[-1] == "d": if sys.argv[-1] == "d":
DEBUG = True DEBUG = True
try: name = sys.argv[1]
room = int(sys.argv[1])
except ValueError:
pass
print("西瓜直播弹幕助手 by JerryYan") print("西瓜直播弹幕助手 by JerryYan")
api = XiGuaLiveApi(room) api = XiGuaLiveApi(name)
print("进入", api.roomLiver, "的直播间")
if not api.isValidRoom: if not api.isValidRoom:
print(api.roomID)
input("房间不存在") input("房间不存在")
sys.exit() sys.exit()
print("进入", api.roomLiver, "的直播间")
print("=" * 30) print("=" * 30)
while True: while True:
if api.isLive: if api.isLive:

View File

@ -323,7 +323,7 @@ class Bilibili:
) )
print(r.text) print(r.text)
for _p in self.files: for _p in self.files:
os.remove(_p.path) shutil.move(_p.path, "/tmp/oss/")
def appendUpload(self, def appendUpload(self,
aid, aid,

View File

@ -23,12 +23,13 @@ class downloader(XiGuaLiveApi):
self.updPlayList() self.updPlayList()
def updPlayList(self): def updPlayList(self):
if "playInfo" not in self._rawRoomInfo or "Main" not in self._rawRoomInfo["playInfo"]: if "stream_url" not in self._rawRoomInfo:
if self.playlist is None: if self.playlist is None:
self.apiChangedError("无法获取直播链接") self.apiChangedError("无法获取直播链接")
self.playlist = False self.playlist = False
else: else:
self.playlist = self._rawRoomInfo["playInfo"]["Main"]["1"]["Url"]["HlsUrl"] self.playlist = self._rawRoomInfo["stream_url"]["alternate_pull_url"]
self.playlist = self.playlist.replace("_uhd","").replace("_sd","").replace("_ld","")
def onLike(self, user): def onLike(self, user):
pass pass
@ -119,7 +120,7 @@ def upload(date=datetime.strftime(datetime.now(), "%Y_%m_%d")):
if i is True: if i is True:
print("自动投稿中,请稍后") print("自动投稿中,请稍后")
b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"], b.finishUpload(config["t_t"].format(date), 17, config["tag"], config["des"],
source="https://live.ixigua.com/userlive/97621754276", no_reprint=0) source=config["src"], no_reprint=0)
break break
print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
try: try:
@ -134,18 +135,15 @@ b = Bilibili()
b.login(config["b_u"], config["b_p"]) b.login(config["b_u"], config["b_p"])
if __name__ == "__main__": if __name__ == "__main__":
room = 97621754276 # 永恒 name = "永恒de草薙"
# room = 75366565294 # room = 75366565294
# room = 83940182312 #Dae # room = 83940182312 #Dae
# room = 5947850784 #⑦ # room = 5947850784 #⑦
# room = 58649240617 #戏 # room = 58649240617 #戏
if len(sys.argv) > 1: if len(sys.argv) > 1:
try: name = sys.argv[1]
room = int(sys.argv[1])
except ValueError:
pass
print("西瓜直播录播助手 by JerryYan") print("西瓜直播录播助手 by JerryYan")
api = downloader(room) api = downloader(name)
print("进入", api.roomLiver, "的直播间") print("进入", api.roomLiver, "的直播间")
if not api.isValidRoom: if not api.isValidRoom:
input("房间不存在") input("房间不存在")
@ -181,7 +179,8 @@ if __name__ == "__main__":
uq.put(True) uq.put(True)
isUpload = False isUpload = False
else: else:
pass del config
from config import config
# print("主播未开播等待1分钟后重试") # print("主播未开播等待1分钟后重试")
time.sleep(60) time.sleep(60)
api.updRoomInfo() api.updRoomInfo()