diff --git a/README.md b/README.md index f480b46..b0d68b7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# bilibiliupload +# biliup ![](https://img.shields.io/badge/python-v3.7%2B-blue) ![GitHub](https://img.shields.io/github/license/ForgQi/bilibiliupload) -支持自动录制各大直播平台,上传直播录像到bilibili。 +支持自动录制各大直播平台实时流,上传到bilibili。也支持twitch直播回放列表自动搬运至b站,如链接https://www.twitch.tv/xxxx/videos?filter=archives&sort=time * 自动选择上传线路,保证国内外vps上传质量和速度 * 可分别控制下载与上传并发量 diff --git a/biliup/plugins/bili_webup.py b/biliup/plugins/bili_webup.py index 9e1a0fa..6da8ebf 100644 --- a/biliup/plugins/bili_webup.py +++ b/biliup/plugins/bili_webup.py @@ -43,6 +43,8 @@ class BiliWeb(UploadBase): def upload(self, file_list): video = Data() with BiliBili(video) as bili: + bili.app_key = self.user.get('app_key') + bili.appsec = self.user.get('appsec') bili.login(self.persistence_path, self.user) for file in file_list: video_part = bili.upload_file(file, self.lines, self.threads) # 上传视频 @@ -66,9 +68,11 @@ class BiliWeb(UploadBase): class BiliBili: def __init__(self, video: 'Data'): - # self.app_key = 'bca7e84c2d947ac6' - self.app_key = 'aae92bc66f3edfab' - self.appsec = 'af125a0d5279fd576c1b4418a3e8276d' + self.app_key = None + self.appsec = None + if self.app_key is None or self.appsec is None: + self.app_key = 'aae92bc66f3edfab' + self.appsec = 'af125a0d5279fd576c1b4418a3e8276d' self.__session = requests.Session() self.video = video self.__session.mount('https://', HTTPAdapter(max_retries=Retry(total=5, method_whitelist=False))) @@ -170,7 +174,6 @@ class BiliBili: raise Exception(data) def sign(self, param): - # salt = '60698ba2f68e01ce44738920a0ffe768' return hashlib.md5(f"{param}{self.appsec}".encode()).hexdigest() def get_key(self): diff --git a/biliup/plugins/twitch.py b/biliup/plugins/twitch.py index 46caeae..d674e9b 100644 --- a/biliup/plugins/twitch.py +++ b/biliup/plugins/twitch.py @@ -24,6 +24,63 @@ _OPERATION_HASHES = { _CLIENT_ID = 'kimne78kx3ncx6brgo4mv6wki5h1ko' +@Plugin.download(regexp=r'https?://(?:(?:www|go|m)\.)?twitch\.tv/(?P[^/]+)/(?:videos|profile)') +class TwitchVideos(DownloadBase): + def __init__(self, fname, url, suffix='mp4'): + DownloadBase.__init__(self, fname, url, suffix=suffix) + + def check_stream(self): + with youtube_dl.YoutubeDL({'download_archive': 'archive.txt'}) as ydl: + info = ydl.extract_info(self.url, download=False) + for entry in info['entries']: + if ydl.in_download_archive(entry): + continue + self.raw_stream_url = entry['url'] + ydl.record_download_archive(entry) + return True + + class BatchCheck(BatchCheckBase): + def __init__(self, urls): + BatchCheckBase.__init__(self, pattern_id=VALID_URL_BASE, urls=urls) + + def check(self): + with youtube_dl.YoutubeDL({'download_archive': 'archive.txt'}) as ydl: + for channel_name, url in self.not_live(): + info = ydl.extract_info(url, download=False) + for entry in info['entries']: + if ydl.in_download_archive(entry): + continue + yield url + time.sleep(10) + # ydl.record_download_archive(entry) + + def not_live(self): + gql = self.get_streamer() + i = -1 + for data in gql: + i += 1 + user = data['data'].get('user') + if not user: + continue + stream = user['stream'] + if not stream: + yield self.usr_list[i], self.usr_dict.get(self.usr_list[i]) + + def get_streamer(self): + for channel_name in self.usr_list: + op = { + 'operationName': 'StreamMetadata', + 'variables': {'channelLogin': channel_name.lower()} + } + op['extensions'] = { + 'persistedQuery': { + 'version': 1, + 'sha256Hash': _OPERATION_HASHES[op['operationName']], + } + } + yield get_streamer(op) + + @Plugin.download(regexp=VALID_URL_BASE) class Twitch(DownloadBase): def __init__(self, fname, url, suffix='flv'): @@ -83,12 +140,16 @@ class Twitch(DownloadBase): } } ops.append(op) - gql = requests.post( - 'https://gql.twitch.tv/gql', - json=ops, - headers={ - 'Content-Type': 'text/plain;charset=UTF-8', - 'Client-ID': _CLIENT_ID, - }, timeout=15) - gql.close() - return gql.json() + return get_streamer(ops) + + +def get_streamer(ops): + gql = requests.post( + 'https://gql.twitch.tv/gql', + json=ops, + headers={ + 'Content-Type': 'text/plain;charset=UTF-8', + 'Client-ID': _CLIENT_ID, + }, timeout=15) + gql.close() + return gql.json() \ No newline at end of file diff --git a/config(demo).yaml b/config(demo).yaml index 2e01e79..7db077f 100644 --- a/config(demo).yaml +++ b/config(demo).yaml @@ -8,6 +8,8 @@ user: # 在填了cookies的情况下优先使用cookies上传,如需使用用 account: username: your usrname password: your password +# app_key: bca7e84c2d947ac6 # 若账号密码方式无法登录可尝试更改此值 +# appsec: 60698ba2f68e01ce44738920a0ffe768 # 值可以参考 https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/other/API_auth.md # b站上传线路选择,默认为自动模式,目前可手动切换为bda2, kodo, ws, qn lines: AUTO