8 Commits

Author SHA1 Message Date
14525ee76e 添加搜索功能[Beta]
Update ReadMe.md

Signed-off-by: Jerry Yan <792602257@qq.com>
2019-01-28 20:26:23 +08:00
cd4d7605f5 Fix Conflicts
# Conflicts:
#	api.py
2019-01-28 18:58:16 +08:00
5da70e81f9 Api使用Android app弹幕协议 2019-01-28 18:54:24 +08:00
f7727a3c39 Emeg: fix default room 2019-01-27 22:26:06 +08:00
e46e4ec0d7 Update README.md 2019-01-27 22:20:23 +08:00
a4f4c10efc 修正Linux版显示 2019-01-27 22:18:17 +08:00
82b076df3f 修正因未开播而导致的Queue内占满了False的BUG 2019-01-26 18:54:41 +08:00
cf8cbaae8c 修复删除已上传视频的逻辑,添加 追加上传功能 2019-01-26 16:29:04 +08:00
9 changed files with 308 additions and 167 deletions

10
Chat.py
View File

@ -2,8 +2,8 @@ from User import User
class Chat: class Chat:
content:str="" content: str =""
user:User=None user: User=None
def __init__(self, json=None): def __init__(self, json=None):
if json: if json:
@ -11,9 +11,9 @@ class Chat:
def parse(self, json): def parse(self, json):
self.user = User(json) self.user = User(json)
if "Msg" in json: if "extra" in json:
if "content" in json["Msg"]: if "content" in json["extra"]:
self.content = json["Msg"]['content'] self.content = json["extra"]['content']
def __str__(self): def __str__(self):
return "{} : {}".format(self.user,self.content) return "{} : {}".format(self.user,self.content)

23
Gift.py
View File

@ -16,26 +16,27 @@ class Gift:
def parse(self, json): def parse(self, json):
self.user = User(json) self.user = User(json)
if "Msg" in json: if "extra" in json:
if "present_end_info" in json["Msg"]: if "present_info" in json["extra"] and json["extra"]['present_info'] is not None:
self.ID = json["Msg"]['present_end_info']['id'] self.ID = int(json["extra"]['present_info']['id'])
self.count = json["Msg"]['present_end_info']['count'] self.count = json["extra"]['present_info']['repeat_count']
elif "present_info" in json["Msg"]: elif "present_end_info" in json["extra"] and json["extra"]['present_end_info'] is not None:
self.ID = json["Msg"]['present_info']['id'] self.ID = int(json["extra"]['present_end_info']['id'])
self.count = json["Msg"]['present_info']['repeat_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
@staticmethod @staticmethod
def update(roomID): def update(roomID):
Gift.roomID = roomID Gift.roomID = roomID
p = requests.get("https://live.ixigua.com/api/gifts/{roomID}".format(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 isinstance(d, int) or "data" not in d: if "gift_info" not in d:
print("错误:礼物更新失败") print("错误:礼物更新失败")
else: else:
for i in d["data"]: for i in d["gift_info"]:
Gift.giftList[i["ID"]] = {"Name": i["Name"], "Price": i["DiamondCount"]} _id = int(i["id"])
Gift.giftList[_id] = {"Name": i["name"], "Price": i["diamond_count"]}
def __str__(self): def __str__(self):
if self.ID in self.giftList: if self.ID in self.giftList:

View File

@ -12,11 +12,11 @@ class MemberMsg:
def parse(self, json): def parse(self, json):
self.user = User(json) self.user = User(json)
if "Msg" in json: if "extra" in json:
if "action" in json["Msg"]: if "action" in json["extra"]:
self.type = json["Msg"]['action'] self.type = json["extra"]['action']
elif "content" in json["Msg"]: elif "content" in json["extra"]:
self.content = json["Msg"]['content'] self.content = json["extra"]['content']
def __str__(self): def __str__(self):
if self.type == 3: if self.type == 3:
@ -28,6 +28,7 @@ class MemberMsg:
elif self.type == 1: elif self.type == 1:
return "{} 进入了房间".format(self.user) return "{} 进入了房间".format(self.user)
else: else:
print(self.type)
return self.content.format(self.user) return self.content.format(self.user)
def __unicode__(self): def __unicode__(self):

View File

@ -1,8 +1,15 @@
# XiguaLiveDanmakuHelper # XiguaLiveDanmakuHelper
### 西瓜直播弹幕助手 ### 西瓜直播弹幕助手--控制台版
因个人能力有限不懂C#,无法做出界面版,只好用控制台版先顶着 界面版:[q792602257/XiguaDanmakuHelperGUI](https://github.com/q792602257/XiguaDanmakuHelperGUI "C# ver")
### 计划更新: ### 计划更新:
- 使用android app协议,避免出现网页版协议更改后无法使用 + √ ~~使用android app协议~~
- 闲的无聊的时候看一看有没有好用的GUI轮子可以用用
已使用
除从用户ID获取roomID及判断是否在播外其他均改为Android Api
+ √ ~~闲的无聊的时候看一看有没有好用的GUI轮子可以用用~~
已完成
已基于BiliLive_dm制作出初代西瓜直播弹幕姬api未跟进

22
User.py
View File

@ -4,25 +4,33 @@ class User:
brand: str = "" brand: str = ""
level: int = 0 level: int = 0
type: int = 0 type: int = 0
block: bool = False
mute: bool = False
def __init__(self, json=None): def __init__(self, json=None):
if json: if json:
self.parse(json) self.parse(json)
def parse(self, json): def parse(self, json):
if "Msg" in json: if "extra" in json:
if "user" in json["Msg"]: if "user" in json["extra"] and json["extra"]["user"] is not None:
self.ID = json["Msg"]['user']['user_id'] self.ID = json["extra"]['user']['user_id']
self.name = json["Msg"]['user']['name'] self.name = json["extra"]['user']['name']
if "discipulus_info" in json["Msg"]: if "im_discipulus_info" in json["extra"] and json["extra"]["im_discipulus_info"] is not None:
self.level = json["Msg"]["discipulus_info"]["level"] self.level = json["extra"]["im_discipulus_info"]["level"]
self.brand = json["Msg"]["discipulus_info"]["discipulus_group_title"] self.brand = json["extra"]["im_discipulus_info"]["discipulus_group_title"]
if "user_room_auth_status" in json["extra"] and json["extra"]["user_room_auth_status"] is not None:
self.type = json["extra"]["user_room_auth_status"]["user_type"]
self.block = json["extra"]["user_room_auth_status"]["is_block"]
self.mute = json["extra"]["user_room_auth_status"]["is_silence"]
elif "data" in json: elif "data" in json:
if "anchorInfo" in json["data"]: if "anchorInfo" in json["data"]:
self.ID = json["data"]['anchorInfo']['id'] self.ID = json["data"]['anchorInfo']['id']
self.name = json["data"]['anchorInfo']['name'] self.name = json["data"]['anchorInfo']['name']
if self.type is None: if self.type is None:
self.type = 0 self.type = 0
if isinstance(self.level, str):
self.level = int(self.level)
def __str__(self): def __str__(self):
if self.level == 0: if self.level == 0:

View File

@ -104,17 +104,13 @@ class WinMain(Api):
if self._tmp > 10: if self._tmp > 10:
self._tmp = 0 self._tmp = 0
if self._tmp < 5 : if self._tmp < 5 :
return "{} {} --弹幕助手 by JerryYan".format(self.roomLiver, "的直播间") return "{} 的直播间 --弹幕助手 by JerryYan".format(self.roomLiver)
else: else:
if self.roomPopularity == 0: if self.roomPopularity == 0:
self._tmp = 0 self._tmp = 0
return self.getTitle() return self.getTitle()
else: else:
if self.roomMember > 0: return "人气:{} --弹幕助手 by JerryYan".format(self.roomPopularity)
return "观看:{} 人气:{} --弹幕助手 by JerryYan".format(self.roomMember, self.roomPopularity)
else:
return "观看:待刷新 人气:{} --弹幕助手 by JerryYan".format(self.roomPopularity)
def onMessage(self, msg: str): def onMessage(self, msg: str):
set_cmd_text_color(FOREGROUND_DARKGRAY) set_cmd_text_color(FOREGROUND_DARKGRAY)

77
api.py
View File

@ -21,7 +21,7 @@ class XiGuaLiveApi:
roomLiver: User = None roomLiver: User = None
roomPopularity: int = 0 roomPopularity: int = 0
roomMember: int = 0 roomMember: int = 0
_cursor = "" _cursor:str = "0"
def __init__(self, room: int): def __init__(self, room: int):
self.room = room self.room = room
@ -30,11 +30,9 @@ class XiGuaLiveApi:
self._enterRoom() self._enterRoom()
def _updateRoomInfo(self, json): def _updateRoomInfo(self, json):
if "Msg" in json: if "extra" in json:
if "member_count" in json["Msg"]: if "member_count" in json["extra"] and json["extra"]["member_count"] > 0:
self.roomMember = json["Msg"]["member_count"] self.roomPopularity = json["extra"]["member_count"]
if "popularity" in json["Msg"]:
self.roomPopularity = json["Msg"]["popularity"]
elif "data" in json: elif "data" in json:
if "popularity" in json["data"]: if "popularity" in json["data"]:
self.roomPopularity = json["data"]["popularity"] self.roomPopularity = json["data"]["popularity"]
@ -44,7 +42,7 @@ class XiGuaLiveApi:
print(*args) print(*args)
def onPresent(self, gift: Gift): def onPresent(self, gift: Gift):
print("礼物连击 : ", gift) print("礼物连击 :", gift)
def onPresentEnd(self, gift: Gift): def onPresentEnd(self, gift: Gift):
print("感谢", gift) print("感谢", gift)
@ -57,30 +55,47 @@ class XiGuaLiveApi:
print(chat) print(chat)
def onEnter(self, msg: MemberMsg): def onEnter(self, msg: MemberMsg):
print("提示 : ", msg) print("提示 :", msg)
def onSubscribe(self, user: User): def onSubscribe(self, user: User):
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)
def onLike(self, user: User): def onLike(self, user: User):
print("用户", user, "点了喜欢") print("用户", user, "点了喜欢")
def onLeave(self, json: any): def onLeave(self, json: any):
print("消息 : ", "主播离开一小会") print("消息 :", "主播离开一小会")
def _enterRoom(self): def _enterRoom(self):
if not self.isValidRoom: if not self.isValidRoom:
return return
p = s.post("https://live.ixigua.com/api/room/enter/{roomID}".format(roomID=self.roomID)) p = s.post("https://i.snssdk.com/videolive/room/enter&version_code=730"
"&device_platform=android",
data="room_id={roomID}&version_code=730"
"&device_platform=android".format(roomID=self.roomID),
headers={"Content-Type":"application/x-www-form-urlencoded"})
if DEBUG: if DEBUG:
print(p.text) 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()
if "data" not in d:
for i in d["data"]:
if i["block_type"] != 2:
continue
for _i in i["cells"]:
ret.append(_i["room"])
return ret
def updRoomInfo(self): def updRoomInfo(self):
p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=self.room)) p = s.get("https://live.ixigua.com/api/room?anchorId={room}".format(room=self.room))
if DEBUG: if DEBUG:
@ -103,47 +118,47 @@ class XiGuaLiveApi:
def getDanmaku(self): def getDanmaku(self):
if not self.isValidRoom: if not self.isValidRoom:
return return
p = s.get("https://live.ixigua.com/api/msg/list/{roomID}?AnchorID={room}&Cursor={cursor}".format( p = s.get("https://i.snssdk.com/videolive/im/get_msg?cursor={cursor}&room_id={roomID}"
roomID=self.roomID, "&version_code=730&device_platform=android".format(
room=self.room, roomID=self.roomID,
cursor=self._cursor cursor=self._cursor
)) ))
d = p.json() d = p.json()
if "data" not in d or "Extra" not in d["data"] or "Cursor" not in d["data"]["Extra"]: if "data" not in d or "extra" not in d or "cursor" not in d["extra"]:
if DEBUG: if DEBUG:
print(d) print(d)
self.apiChangedError("数据结构改变,请与我联系") self.apiChangedError("数据结构改变,请与我联系")
return return
else: else:
self._cursor = d["data"]["Extra"]["Cursor"] self._cursor = d["extra"]["cursor"]
if DEBUG: if DEBUG:
print("Cursor", self._cursor) print("Cursor", self._cursor)
if "LiveMsgs" not in d["data"]: if len(d['data']) == 0:
self.updRoomInfo() self.updRoomInfo()
return return
for i in d['data']['LiveMsgs']: for i in d['data']:
if DEBUG: if DEBUG:
print(i) print(i)
if "Method" not in i: if "common" not in i and "method" not in i["common"]:
continue continue
if i['Method'] == "VideoLivePresentMessage": if i["common"]['method'] == "VideoLivePresentMessage":
self.onPresent(Gift(i)) self.onPresent(Gift(i))
elif i['Method'] == "VideoLivePresentEndTipMessage": elif i["common"]['method'] == "VideoLivePresentEndTipMessage":
self.onPresentEnd(Gift(i)) self.onPresentEnd(Gift(i))
elif i['Method'] == "VideoLiveRoomAdMessage": elif i["common"]['method'] == "VideoLiveRoomAdMessage":
self.onAd(i) self.onAd(i)
elif i['Method'] == "VideoLiveChatMessage": elif i["common"]['method'] == "VideoLiveChatMessage":
self.onChat(Chat(i)) self.onChat(Chat(i))
elif i['Method'] == "VideoLiveMemberMessage": elif i["common"]['method'] == "VideoLiveMemberMessage":
self._updateRoomInfo(i) self._updateRoomInfo(i)
self.onEnter(MemberMsg(i)) self.onEnter(MemberMsg(i))
elif i['Method'] == "VideoLiveSocialMessage": elif i["common"]['method'] == "VideoLiveSocialMessage":
self.onSubscribe(User(i)) self.onSubscribe(User(i))
elif i['Method'] == "VideoLiveJoinDiscipulusMessage": elif i["common"]['method'] == "VideoLiveJoinDiscipulusMessage":
self.onJoin(User(i)) self.onJoin(User(i))
elif i['Method'] == "VideoLiveControlMessage": elif i["common"]['method'] == "VideoLiveControlMessage":
print("消息:", "主播离开一小会") print("消息:", "主播离开一小会")
elif i['Method'] == "VideoLiveDiggMessage": elif i["common"]['method'] == "VideoLiveDiggMessage":
self.onLike(User(i)) self.onLike(User(i))
else: else:
pass pass

View File

@ -18,8 +18,10 @@ class VideoPart:
self.title = title self.title = title
self.desc = desc self.desc = desc
class Bilibili: class Bilibili:
def __init__(self, cookie=None): def __init__(self, cookie=None):
self.files = []
self.videos = [] self.videos = []
self.session = requests.session() self.session = requests.session()
if cookie: if cookie:
@ -41,12 +43,12 @@ class Bilibili:
:return: if success return True :return: if success return True
else return msg json else return msg json
""" """
APPKEY = '1d8b6e7d45233436' APPKEY = '1d8b6e7d45233436'
ACTIONKEY = 'appkey' ACTIONKEY = 'appkey'
BUILD = 520001 BUILD = 520001
DEVICE = 'android' DEVICE = 'android'
MOBI_APP = 'android' MOBI_APP = 'android'
PLATFORM = 'android' PLATFORM = 'android'
APPSECRET = '560c52ccd288fed045859ed18bffd973' APPSECRET = '560c52ccd288fed045859ed18bffd973'
def md5(s): def md5(s):
@ -81,9 +83,9 @@ class Bilibili:
:return: hash, key :return: hash, key
""" """
r = self.session.post( r = self.session.post(
'https://passport.bilibili.com/api/oauth2/getKey', 'https://passport.bilibili.com/api/oauth2/getKey',
signed_body({'appkey': APPKEY}), signed_body({'appkey': APPKEY}),
) )
# {"ts":1544152439,"code":0,"data":{"hash":"99c7573759582e0b","key":"-----BEGIN PUBLIC----- -----END PUBLIC KEY-----\n"}} # {"ts":1544152439,"code":0,"data":{"hash":"99c7573759582e0b","key":"-----BEGIN PUBLIC----- -----END PUBLIC KEY-----\n"}}
json = r.json() json = r.json()
data = json['data'] data = json['data']
@ -98,19 +100,19 @@ class Bilibili:
self.session.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' self.session.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
h, k = getkey() h, k = getkey()
pwd = base64.b64encode( pwd = base64.b64encode(
rsa.encrypt( rsa.encrypt(
(h + pwd).encode('utf-8'), (h + pwd).encode('utf-8'),
rsa.PublicKey.load_pkcs1_openssl_pem(k.encode()) rsa.PublicKey.load_pkcs1_openssl_pem(k.encode())
) )
) )
user = parse.quote_plus(user) user = parse.quote_plus(user)
pwd = parse.quote_plus(pwd) pwd = parse.quote_plus(pwd)
r = self.session.post( r = self.session.post(
'https://passport.bilibili.com/api/v2/oauth2/login', 'https://passport.bilibili.com/api/v2/oauth2/login',
signed_body('appkey={appkey}&password={password}&username={username}' signed_body('appkey={appkey}&password={password}&username={username}'
.format(appkey=APPKEY, username=user, password=pwd)) .format(appkey=APPKEY, username=user, password=pwd))
) )
try: try:
json = r.json() json = r.json()
except: except:
@ -122,22 +124,21 @@ class Bilibili:
r = self.session.get('https://passport.bilibili.com/captcha') r = self.session.get('https://passport.bilibili.com/captcha')
captcha = cnn_captcha(base64.b64encode(r.content)) captcha = cnn_captcha(base64.b64encode(r.content))
r = self.session.post( r = self.session.post(
'https://passport.bilibili.com/api/v2/oauth2/login', 'https://passport.bilibili.com/api/v2/oauth2/login',
signed_body('actionKey={actionKey}&appkey={appkey}&build={build}&captcha={captcha}&device={device}' signed_body('actionKey={actionKey}&appkey={appkey}&build={build}&captcha={captcha}&device={device}'
'&mobi_app={mobi_app}&password={password}&platform={platform}&username={username}' '&mobi_app={mobi_app}&password={password}&platform={platform}&username={username}'
.format(actionKey=ACTIONKEY, .format(actionKey=ACTIONKEY,
appkey=APPKEY, appkey=APPKEY,
build=BUILD, build=BUILD,
captcha=captcha, captcha=captcha,
device=DEVICE, device=DEVICE,
mobi_app=MOBI_APP, mobi_app=MOBI_APP,
password=pwd, password=pwd,
platform=PLATFORM, platform=PLATFORM,
username=user)), username=user)),
) )
json = r.json() json = r.json()
if json['code'] is not 0: if json['code'] is not 0:
return r.text return r.text
@ -154,7 +155,6 @@ class Bilibili:
return True return True
def upload(self, def upload(self,
parts, parts,
title, title,
@ -186,38 +186,23 @@ class Bilibili:
:type no_reprint: int :type no_reprint: int
""" """
self.preUpload(parts) self.preUpload(parts)
self.finishUpload(title,tid,tag,desc,source,cover,no_reprint) self.finishUpload(title, tid, tag, desc, source, cover, no_reprint)
def preUpload(self,parts): def preUpload(self, parts):
""" """
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)] :param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
:type parts: VideoPart or list<VideoPart> :type parts: VideoPart or list<VideoPart>
:param title: video's title
:type title: str
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
:type tid: int
:param tag: video's tag
:type tag: list<str>
:param desc: video's description
:type desc: str
:param source: (optional) 转载地址
:type source: str
:param cover: (optional) cover's URL, use method *cover_up* to get
:type cover: str
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
:type no_reprint: int
""" """
self.session.headers['Content-Type'] = 'application/json; charset=utf-8' self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
if not isinstance(parts, list): if not isinstance(parts, list):
parts = [parts] parts = [parts]
videos = []
for part in parts: for part in parts:
filepath = part.path filepath = part.path
filename = os.path.basename(filepath) filename = os.path.basename(filepath)
filesize = os.path.getsize(filepath) filesize = os.path.getsize(filepath)
self.files.append(part)
r = self.session.get('https://member.bilibili.com/preupload?' r = self.session.get('https://member.bilibili.com/preupload?'
'os=upos&upcdn=ws&name={name}&size={size}&r=upos&profile=ugcupos%2Fyb&ssl=0' 'os=upos&upcdn=ws&name={name}&size={size}&r=upos&profile=ugcupos%2Fyb&ssl=0'
.format(name=filename, size=filesize)) .format(name=filename, size=filesize))
@ -276,7 +261,7 @@ class Bilibili:
chunks_data, chunks_data,
) )
print('{} : UPLOAD {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), chunks_index, print('{} : UPLOAD {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), chunks_index,
chunks_num), r.text) chunks_num), r.text)
# NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769 # NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769
self.session.post('https:{endpoint}/{upos_uri}?' self.session.post('https:{endpoint}/{upos_uri}?'
@ -291,8 +276,8 @@ class Bilibili:
) )
self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0], self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0],
'title': part.title, 'title': part.title,
'desc': part.desc}) 'desc': part.desc})
def finishUpload(self, def finishUpload(self,
title, title,
@ -303,26 +288,142 @@ class Bilibili:
cover='', cover='',
no_reprint=1, no_reprint=1,
): ):
"""
:param title: video's title
:type title: str
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
:type tid: int
:param tag: video's tag
:type tag: list<str>
:param desc: video's description
:type desc: str
:param source: (optional) 转载地址
:type source: str
:param cover: (optional) cover's URL, use method *cover_up* to get
:type cover: str
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
:type no_reprint: int
"""
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
copyright = 2 if source else 1 copyright = 2 if source else 1
r = self.session.post('https://member.bilibili.com/x/vu/web/add?csrf=' + self.csrf, r = self.session.post('https://member.bilibili.com/x/vu/web/add?csrf=' + self.csrf,
json={ json={
"copyright" : copyright, "copyright": copyright,
"source" : source, "source": source,
"title" : title, "title": title,
"tid" : tid, "tid": tid,
"tag" : ','.join(tag), "tag": ','.join(tag),
"no_reprint": no_reprint, "no_reprint": no_reprint,
"desc" : desc, "desc": desc,
"cover" : cover, "cover": cover,
"mission_id": 0, "mission_id": 0,
"order_id" : 0, "order_id": 0,
"videos" : self.videos} "videos": self.videos}
) )
print(r.text) print(r.text)
for _p in self.videos: for _p in self.files:
os.remove(_p.path) os.remove(_p.path)
def appendUpload(self,
aid,
parts,
title="",
tid="",
tag="",
desc="",
source='',
cover='',
no_reprint=1,
):
"""
:param aid: just aid
:type aid: int
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
:type parts: VideoPart or list<VideoPart>
:param title: video's title
:type title: str
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
:type tid: int
:param tag: video's tag
:type tag: list<str>
:param desc: video's description
:type desc: str
:param source: (optional) 转载地址
:type source: str
:param cover: (optional) cover's URL, use method *cover_up* to get
:type cover: str
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
:type no_reprint: int
"""
self.session.headers['Content-Type'] = 'application/json; charset=utf-8'
p = self.session.get("https://member.bilibili.com/x/web/archive/view?aid={}&history=".format(aid))
j = p.json()
if len(self.videos) == 0:
for i in j['data']['videos']:
self.videos.append({'filename': i['filename'],
'title': i["title"],
'desc': i["desc"]})
if (title == ""): title = j["data"]["archive"]['title']
if (tag == ""): tag = j["data"]["archive"]['tag']
if (no_reprint == ""): no_reprint = j["data"]["archive"]['no_reprint']
if (desc == ""): desc = j["data"]["archive"]['desc']
if (source == ""): source = j["data"]["archive"]['source']
if (tid == ""): tid = j["data"]["archive"]['tid']
self.preUpload(parts)
self.editUpload(aid, title, tid, tag, desc, source, cover, no_reprint)
def editUpload(self,
aid,
title,
tid,
tag,
desc,
source='',
cover='',
no_reprint=1,
):
"""
:param aid: just aid
:type aid: int
:param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)]
:type parts: VideoPart or list<VideoPart>
:param title: video's title
:type title: str
:param tid: video type, see: https://member.bilibili.com/x/web/archive/pre
or https://github.com/uupers/BiliSpider/wiki/%E8%A7%86%E9%A2%91%E5%88%86%E5%8C%BA%E5%AF%B9%E5%BA%94%E8%A1%A8
:type tid: int
:param tag: video's tag
:type tag: list<str>
:param desc: video's description
:type desc: str
:param source: (optional) 转载地址
:type source: str
:param cover: (optional) cover's URL, use method *cover_up* to get
:type cover: str
:param no_reprint: (optional) 0=可以转载, 1=禁止转载(default)
:type no_reprint: int
"""
copyright = 2 if source else 1
r = self.session.post('https://member.bilibili.com/x/vu/web/edit?csrf=' + self.csrf,
json={
"aid": aid,
"copyright": copyright,
"source": source,
"title": title,
"tid": tid,
"tag": ','.join(tag),
"no_reprint": no_reprint,
"desc": desc,
"cover": cover,
"mission_id": 0,
"order_id": 0,
"videos": self.videos}
)
print(r.text)
for _p in self.files:
os.remove(_p.path)
def addChannel(self, name, intro=''): def addChannel(self, name, intro=''):
""" """
@ -333,14 +434,14 @@ class Bilibili:
:type intro: str :type intro: str
""" """
r = self.session.post( r = self.session.post(
url='https://space.bilibili.com/ajax/channel/addChannel', url='https://space.bilibili.com/ajax/channel/addChannel',
data={ data={
'name' : name, 'name': name,
'intro': intro, 'intro': intro,
'aids' : '', 'aids': '',
'csrf' : self.csrf, 'csrf': self.csrf,
}, },
# name=123&intro=123&aids=&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497077610768 # name=123&intro=123&aids=&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497077610768
) )
# return # return
@ -357,13 +458,13 @@ class Bilibili:
""" """
r = self.session.post( r = self.session.post(
url='https://space.bilibili.com/ajax/channel/addVideo', url='https://space.bilibili.com/ajax/channel/addVideo',
data={ data={
'aids': '%2C'.join(aids), 'aids': '%2C'.join(aids),
'cid' : cid, 'cid': cid,
'csrf': self.csrf 'csrf': self.csrf
} }
# aids=9953555%2C9872953&cid=15814&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497079332679 # aids=9953555%2C9872953&cid=15814&csrf=565d7ed17cef2cc8ad054210c4e64324&_=1497079332679
) )
print(r.json()) print(r.json())
@ -380,13 +481,12 @@ class Bilibili:
else: else:
f = img f = img
r = self.session.post( r = self.session.post(
url='https://member.bilibili.com/x/vu/web/cover/up', url='https://member.bilibili.com/x/vu/web/cover/up',
data={ data={
'cover': b'data:image/jpeg;base64,' + (base64.b64encode(f.read())), 'cover': b'data:image/jpeg;base64,' + (base64.b64encode(f.read())),
'csrf': self.csrf, 'csrf': self.csrf,
} }
) )
# print(r.text) # print(r.text)
# {"code":0,"data":{"url":"http://i0.hdslb.com/bfs/archive/67db4a6eae398c309244e74f6e85ae8d813bd7c9.jpg"},"message":"","ttl":1} # {"code":0,"data":{"url":"http://i0.hdslb.com/bfs/archive/67db4a6eae398c309244e74f6e85ae8d813bd7c9.jpg"},"message":"","ttl":1}
return r.json()['data']['url'] return r.json()['data']['url']

View File

@ -12,7 +12,7 @@ q = queue.Queue()
base_uri = "" base_uri = ""
isUpload = False isUpload = False
uq = queue.Queue() uq = queue.Queue()
d = datetime.strftime(datetime.now(),"%Y_%m_%d")
class downloader(XiGuaLiveApi): class downloader(XiGuaLiveApi):
files = [] files = []
@ -32,24 +32,34 @@ class downloader(XiGuaLiveApi):
def onLike(self, user): def onLike(self, user):
pass pass
def onAd(self, i): def onAd(self, i):
pass pass
def onChat(self, chat): def onChat(self, chat):
pass pass
def onEnter(self, msg): def onEnter(self, msg):
pass pass
def onJoin(self, user): def onJoin(self, user):
pass pass
def onLeave(self, json): def onLeave(self, json):
self.updRoomInfo() self.updRoomInfo()
def onMessage(self, msg): def onMessage(self, msg):
pass pass
def onPresent(self, gift): def onPresent(self, gift):
pass pass
def onPresentEnd(self, gift): def onPresentEnd(self, gift):
pass pass
def onSubscribe(self, user): def onSubscribe(self, user):
pass pass
def preDownload(self): def preDownload(self):
global base_uri global base_uri
if self.playlist: if self.playlist:
@ -63,16 +73,17 @@ class downloader(XiGuaLiveApi):
if i not in self.files: if i not in self.files:
self.files.append(i) self.files.append(i)
print("{} : Add Sequence {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), print("{} : Add Sequence {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"),
len(self.files))) len(self.files)))
q.put(i) q.put(i)
self.genNewName() self.genNewName()
def genNewName(self): def genNewName(self):
if len(self.files) > 800: if len(self.files) > 800:
q.put(True) q.put(True)
self.files.clear() self.files.clear()
def download(path=datetime.strftime(datetime.now(),"%Y%m%d_%H%M.ts")): def download(path=datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts")):
global isUpload global isUpload
print("{} : Download Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) print("{} : Download Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
n = False n = False
@ -84,31 +95,31 @@ def download(path=datetime.strftime(datetime.now(),"%Y%m%d_%H%M.ts")):
break break
print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
try: try:
_p = requests.get("{}{}".format(base_uri,i)) _p = requests.get("{}{}".format(base_uri, i))
except: except:
continue continue
f = open(path, "ab") f = open(path, "ab")
f.write(_p.content) f.write(_p.content)
f.close() f.close()
n=True n = True
i = q.get() i = q.get()
if n: if n:
isUpload = True
uq.put(path) uq.put(path)
print("{} : Download Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) print("{} : Download Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
isUpload = True
def upload(date=datetime.strftime(datetime.now(), "%Y_%m_%d")):
def upload(date = datetime.strftime(datetime.now(), "%Y_%m_%d")):
print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M")))
i = uq.get() i = uq.get()
while True: while True:
if isinstance(i, bool): if isinstance(i, bool):
print("{} : Upload Daemon Receive Command {}"
.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
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="https://live.ixigua.com/userlive/97621754276", no_reprint=0)
print("{} : Upload Daemon Receive Command {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i))
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:
@ -140,6 +151,7 @@ if __name__ == "__main__":
input("房间不存在") input("房间不存在")
sys.exit() sys.exit()
print("=" * 30) print("=" * 30)
d = datetime.strftime(datetime.now(), "%Y_%m_%d")
_preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts") _preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts")
t = threading.Thread(target=download, args=(_preT,)) t = threading.Thread(target=download, args=(_preT,))
ut = threading.Thread(target=upload, args=(d,)) ut = threading.Thread(target=upload, args=(d,))
@ -162,7 +174,9 @@ if __name__ == "__main__":
pass pass
time.sleep(3) time.sleep(3)
else: else:
q.put(False) if d is not None:
q.put(False)
d = None
if isUpload: if isUpload:
uq.put(True) uq.put(True)
isUpload = False isUpload = False
@ -170,5 +184,4 @@ if __name__ == "__main__":
pass pass
# print("主播未开播等待1分钟后重试") # print("主播未开播等待1分钟后重试")
time.sleep(60) time.sleep(60)
d=None
api.updRoomInfo() api.updRoomInfo()