diff --git a/bilibili.py b/bilibili.py index d4dbe60..9dc29bd 100644 --- a/bilibili.py +++ b/bilibili.py @@ -25,6 +25,7 @@ class VideoPart: class Bilibili: def __init__(self, cookie=None): + self.videos = [] self.session = requests.session() if cookie: self.session.headers["cookie"] = cookie @@ -171,6 +172,29 @@ class Bilibili: ): """ + :param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)] + :type parts: VideoPart or list + :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 + :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.preUpload(parts) + self.finishUpload(title,tid,tag,desc,source,cover,no_reprint) + + def preUpload(self,parts): + """ :param parts: e.g. VideoPart('part path', 'part title', 'part desc'), or [VideoPart(...), VideoPart(...)] :type parts: VideoPart or list :param title: video's title @@ -227,7 +251,8 @@ class Bilibili: biz_id = json['biz_id'] chunk_size = json['chunk_size'] self.session.headers['X-Upos-Auth'] = auth # add auth header - r = self.session.post('https:{}/{}?uploads&output=json'.format(endpoint, upos_uri.replace('upos://', ''))) + r = self.session.post( + 'https:{}/{}?uploads&output=json'.format(endpoint, upos_uri.replace('upos://', ''))) # {"upload_id":"72eb747b9650b8c7995fdb0efbdc2bb6","key":"\/i181012ws2wg1tb7tjzswk2voxrwlk1u.mp4","OK":1,"bucket":"ugc"} json = r.json() upload_id = json['upload_id'] @@ -244,7 +269,7 @@ class Bilibili: 'partNumber={part_number}&uploadId={upload_id}&chunk={chunk}&chunks={chunks}&size={size}&start={start}&end={end}&total={total}' .format(endpoint=endpoint, upos_uri=upos_uri.replace('upos://', ''), - part_number=chunks_index+1, # starts with 1 + part_number=chunks_index + 1, # starts with 1 upload_id=upload_id, chunk=chunks_index, chunks=chunks_num, @@ -255,7 +280,8 @@ class Bilibili: ), chunks_data, ) - print('{} : {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M") ,chunks_index, chunks_num), r.text) + print('{} : UPLOAD {}/{}'.format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), chunks_index, + chunks_num), r.text) # NOT DELETE! Refer to https://github.com/comwrg/bilibiliupload/issues/15#issuecomment-424379769 self.session.post('https:{endpoint}/{upos_uri}?' @@ -265,15 +291,23 @@ class Bilibili: name=filename, upload_id=upload_id, biz_id=biz_id, - ), - {"parts": [{"partNumber": i, "eTag": "etag"} for i in range(1, chunks_num+1)]}, - ) + ), + {"parts": [{"partNumber": i, "eTag": "etag"} for i in range(1, chunks_num + 1)]}, + ) - videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0], - 'title' : part.title, - 'desc' : part.desc}) + self.videos.append({'filename': upos_uri.replace('upos://ugc/', '').split('.')[0], + 'title': part.title, + 'desc': part.desc}) - # if source is empty, copyright=1, else copyright=2 + def finishUpload(self, + title, + tid, + tag, + desc, + source='', + cover='', + no_reprint=1, + ): copyright = 2 if source else 1 r = self.session.post('https://member.bilibili.com/x/vu/web/add?csrf=' + self.csrf, json={ @@ -287,10 +321,12 @@ class Bilibili: "cover" : cover, "mission_id": 0, "order_id" : 0, - "videos" : videos} + "videos" : self.videos} ) print(r.text) + + def addChannel(self, name, intro=''): """ diff --git a/liveDownloader.py b/liveDownloader.py index 319a26b..5bbf8b2 100644 --- a/liveDownloader.py +++ b/liveDownloader.py @@ -12,9 +12,9 @@ from bilibili import * q = queue.Queue() base_uri = "" isUpload = False -OutFileName = [] env = dotenv.main.DotEnv(".env") - +uq = queue.Queue() +d = datetime.strftime(datetime.now(),"%Y_%m_%d") class downloader(XiGuaLiveApi): files = [] @@ -32,7 +32,6 @@ class downloader(XiGuaLiveApi): else: self.playlist = self._rawRoomInfo["playInfo"]["Main"]["1"]["Url"]["HlsUrl"] - def onLike(self, user): pass def onAd(self, i): @@ -65,31 +64,63 @@ class downloader(XiGuaLiveApi): for i in p.files: if i not in self.files: self.files.append(i) + print("{} : Add Sequence {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), + len(self.files))) q.put(i) self.genNewName() def genNewName(self): - if len(self.files) > 1500: - q.put(False) + if len(self.files) > 1000: + q.put(True) self.files.clear() - return True - else: - return False + def download(path=datetime.strftime(datetime.now(),"%Y%m%d_%H%M.ts")): - print("Download Daemon Starting") - OutFileName.append(path) + print("{} : Download Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) + n = False + i = q.get() while True: - i = q.get() if isinstance(i, bool): - print("Recive Command {}".format(i)) + print("{} : Download Daemon Receive Command {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) break - _p = requests.get("{}{}".format(base_uri,i)) - print("Download : {}".format(i)) + print("{} : Download {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) + try: + _p = requests.get("{}{}".format(base_uri,i)) + except: + continue f = open(path, "ab") f.write(_p.content) f.close() + n=True + i = q.get() + if n: + uq.put(path) + print("{} : Download Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) +def upload(date = datetime.strftime(datetime.now(), "%Y_%m_%d")): + print("{} : Upload Daemon Starting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) + i = uq.get() + while True: + if isinstance(i, bool): + if i is True: + b.finishUpload("【永恒de草薙直播录播】直播于 {} 自动投递实际测试".format(date), + 17, ["永恒de草薙", "三国", "三国战记", "自动投递", "直播", "录播"], + "自动投递实际测试\n原主播:永恒de草薙\n直播时间:晚上6点多到白天6点左右", + 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 + print("{} : Upload {}".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"), i)) + try: + b.preUpload(VideoPart(i, i)) + except: + continue + i = uq.get() + print("{} : Upload Daemon Quiting".format(datetime.strftime(datetime.now(), "%y%m%d %H%M"))) + + +b = Bilibili() +b.login(env.get("b_u"), env.get("b_p")) + if __name__ == "__main__": room = 97621754276 # 永恒 # room = 75366565294 @@ -108,17 +139,22 @@ if __name__ == "__main__": input("房间不存在") sys.exit() print("=" * 30) - _preT = datetime.strftime(datetime.now(), "%Y%m%d_%H.ts") + _preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts") t = threading.Thread(target=download, args=(_preT,)) - t.setDaemon(True) - t.start() + ut = threading.Thread(target=upload, args=(d,)) while True: if api.isLive: + if d is None: + d = datetime.strftime(datetime.now(), "%Y_%m_%d") if not t.is_alive(): - _preT = datetime.strftime(datetime.now(), "%Y%m%d_%H.ts") + _preT = datetime.strftime(datetime.now(), "%Y%m%d_%H%M.ts") t = threading.Thread(target=download, args=(_preT,)) t.setDaemon(True) t.start() + if not ut.is_alive(): + ut = threading.Thread(target=upload, args=(d,)) + ut.setDaemon(True) + ut.start() api.preDownload() isUpload = True time.sleep(3) @@ -126,22 +162,10 @@ if __name__ == "__main__": q.put(False) if isUpload: print("自动投稿中,请稍后") - b = Bilibili() - b.login(env.get("b_u"), env.get("b_p")) - u = threading.Thread(target=b.upload,args=([VideoPart(n) for n in OutFileName], - "【永恒de草薙直播的录播】(三国战记) live at {} 自动投递实际测试".format(OutFileName[0]), - 17, ["永恒de草薙", "三国", "三国战记", "自动投递", "直播", "录播"], - "自动投递实际测试\n原主播:永恒de草薙\n直播时间:晚上6点多到白天6点左右",), - kwargs={"source": "https://live.ixigua.com/userlive/97621754276", "no_reprint": 0}) - u.setDaemon(True) - u.start() - u.join() - # reset all for long time running - OutFileName = [] - api.files = [] - isUpload = False + uq.put(True) else: pass # print("主播未开播,等待1分钟后重试") time.sleep(60) + d=None api.updRoomInfo()