From d5de6b19b63e1c7ddc56c1be27995d99e555ede1 Mon Sep 17 00:00:00 2001 From: fireattack Date: Mon, 26 Aug 2024 21:59:10 +0800 Subject: [PATCH 01/39] Disable danmaku download temporally until fixed --- nico.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/nico.py b/nico.py index f21cac9..457c762 100644 --- a/nico.py +++ b/nico.py @@ -260,16 +260,19 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v result = ws.recv() verbose and print("Received '%s'" % result) data = json.loads(result) - if data['type'] == 'room': - room_info = data - if comments in ['yes', 'only']: - ex.submit(self.download_comments, room_info, end_time_epoch, filename) - elif data['type'] == 'stream': + if data['type'] == 'stream': stream_info = data - # just grab all the info even if we don't need it, it doesn't save any time anyway. - if room_info and stream_info: - print('Got all the info we needed. Close WS.') break + # if data['type'] == 'room': + # room_info = data + # if comments in ['yes', 'only']: + # ex.submit(self.download_comments, room_info, end_time_epoch, filename) + # elif data['type'] == 'stream': + # stream_info = data + # # just grab all the info even if we don't need it, it doesn't save any time anyway. + # if room_info and stream_info: + # print('Got all the info we needed. Close WS.') + # break ws.close() if dump: From 5bfefe26f897ee9a8b295fc82ed388282d550d4b Mon Sep 17 00:00:00 2001 From: fireattack Date: Fri, 13 Sep 2024 18:00:43 +0800 Subject: [PATCH 02/39] Drop browser_cookie3 and use rookiepy instead --- nico.py | 26 ++++++++++---------------- util.py | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/nico.py b/nico.py index 457c762..78fc603 100644 --- a/nico.py +++ b/nico.py @@ -7,7 +7,6 @@ from urllib.request import getproxies from pathlib import Path -import browser_cookie3 import websocket from rich.console import Console from rich.table import Table @@ -28,18 +27,10 @@ def validate_cookie(cookies): else: print(f'WARN: Cannot find user_session in cookie. You\'re probably not logged in.') # exit(1) # make it non-fatal - - if cookies.lower() in ['chrome', 'firefox', 'edge']: - print(f'Fetching cookies from browser {cookies}...') - cookies = cookies.lower() - if cookies == 'chrome': - cookies = browser_cookie3.chrome(domain_name='.nicovideo.jp') - elif cookies == 'firefox': - cookies = browser_cookie3.firefox(domain_name='.nicovideo.jp') - elif cookies == 'edge': - cookies = browser_cookie3.edge(domain_name='.nicovideo.jp') + if isinstance(cookies, str) and cookies.lower() in ['chrome', 'firefox', 'edge']: + cookies = load_cookie(cookies + '/nicovideo.jp') validate_cookie(cookies) - elif cookies.startswith('user_session_'): + elif isinstance(cookies, str) and cookies.startswith('user_session_'): cookies = {'user_session': cookies} elif Path(cookies).exists(): print(f'Loading cookies from file {cookies}...') @@ -59,10 +50,10 @@ def validate_cookie(cookies): elif proxy == 'auto': proxies = getproxies() if proxy := proxies.get('http'): - print(f'INFO: automatically use system proxy {proxy}') - + print(f'INFO: Automatically use system proxy {proxy}') # I don't think system proxy would be missing scheme, but just in case if proxy and '://' not in proxy: + print('WARN: Proxy is missing scheme. Assuming http://') proxy = f'http://{proxy}' self.session.proxies = {'http': proxy, 'https': proxy} @@ -253,7 +244,8 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v room_info = None stream_info = None - ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) + #TODO: fix danmaku downloading with the new method + # ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) while True: verbose and print("Receiving...") @@ -263,6 +255,7 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v if data['type'] == 'stream': stream_info = data break + #TODO: danmaku downloading is temporarily disabled until the new method is implemented # if data['type'] == 'room': # room_info = data # if comments in ['yes', 'only']: @@ -315,7 +308,8 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v print('CMD is:') print(cmd) run(cmd, shell=True) - ex.shutdown(wait=True) # ensure download_comments is finished + # TODO: fix danmaku downloading with the new method + # ex.shutdown(wait=True) # ensure download_comments is finished return_value.update({ 'master_m3u8_url': master_m3u8_url, diff --git a/util.py b/util.py index 3648919..6f3e48a 100644 --- a/util.py +++ b/util.py @@ -14,7 +14,7 @@ # so we can use this file in other projects without installing them. # or to copy and paste the functions to other public projects directly. # to install them all, you can do: -# pip install requests lxml beautifulsoup4 python-dateutil pytz pyperclip wcwidth rich browser_cookie3 +# pip install requests lxml beautifulsoup4 python-dateutil pytz pyperclip wcwidth rich rookiepy # ==================== CONSTANTS ==================== @@ -248,6 +248,23 @@ def save(self, f): s += '\t'.join([str(cell) for cell in row]) + '\n' f.write_text(s, encoding='utf8') +def multi_col_print(data, columns=5): + '''Print a list of data in a table with columns''' + from rich.console import Console + from rich.table import Table + + table = Table(show_header=False, box=None) + for _ in range(columns): + table.add_column(style='cyan') + # add data to table vertically + row_count = len(data) // columns + 1 + for i in range(row_count): + row = data[i::row_count] + table.add_row(*row) + + console = Console() + console.print(table) + def array_to_range_text(a, sep=', ', dash='-'): s = '' prev_seg = None @@ -815,7 +832,8 @@ def load_cookie(s): from http.cookiejar import MozillaCookieJar from requests.cookies import RequestsCookieJar, create_cookie import browser_cookie3 - # pip install browser_cookie3 + import rookiepy + # pip install browser_cookie3 rookiepy def convert(cj): cookies = RequestsCookieJar() @@ -833,14 +851,22 @@ def convert(cj): return cookies if m := re.search(r'^(chrome|firefox|edge)(/.+)?', str(s), re.IGNORECASE): - domain_name = m[2].lstrip('/') if m[2] else "" + # domain_name = m[2].lstrip('/') if m[2] else None + # if m[1] == 'chrome': + # cj = browser_cookie3.chrome(domain_name=domain_name) + # elif m[1] == 'firefox': + # cj = browser_cookie3.firefox(domain_name=domain_name) + # elif m[1] == 'edge': + # cj = browser_cookie3.edge(domain_name=domain_name) + # return convert(cj) + domains = [m[2].lstrip('/')] if m[2] else None if m[1] == 'chrome': - cj = browser_cookie3.chrome(domain_name=domain_name) + rcookies = rookiepy.chrome(domains=domains) elif m[1] == 'firefox': - cj = browser_cookie3.firefox(domain_name=domain_name) + rcookies = rookiepy.firefox(domains=domains) elif m[1] == 'edge': - cj = browser_cookie3.edge(domain_name=domain_name) - return convert(cj) + rcookies = rookiepy.edge(domains=domains) + return convert(rookiepy.to_cookiejar(rcookies)) if Path(s).exists(): cj = MozillaCookieJar(s) From 4df6801da81c2c03cd8d87512743a30fb9db9219 Mon Sep 17 00:00:00 2001 From: fireattack Date: Sat, 21 Sep 2024 16:03:11 +0800 Subject: [PATCH 03/39] nico: use `NDGRClient` to download comments --- README.md | 5 +++ nico.py | 103 +++++++++++++++--------------------------------------- util.py | 2 +- 3 files changed, 35 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 3004895..19715b4 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,11 @@ pip install browser-cookie3 websocket-client rich python-dateutil pytz requests npm i minyami -g ``` +If you want to download comments, you need to install [NDGRClient](https://github.com/tsukumijima/NDGRClient), too. +``` +pip install git+https://github.com/tsukumijima/NDGRClient +``` + CLI: ``` diff --git a/nico.py b/nico.py index 78fc603..b7bff09 100644 --- a/nico.py +++ b/nico.py @@ -86,63 +86,27 @@ def fetch_page(self, url): live_data = json.loads(soup.select_one('#embedded-data')['data-props']) return live_data - def download_comments(self, room_info, when, filename): - chats_all = [] - url = room_info["data"]["messageServer"]["uri"] - thread_id = room_info["data"]["threadId"] - - ws = self.create_ws(url) - print(f'Start download comments from thread {thread_id}') - sending = True - while sending: - message = [ - {"ping": {"content": "rs:0"}}, - {"ping": {"content": "ps:0"}}, - { - "thread": { - "thread": thread_id, - "version": "20090904", - "res_from": -1000, - "when": when + 10 - } - }, - {"ping": {"content": "pf:0"}}, - {"ping": {"content": "rf:0"}} - ] - ws.send(json.dumps(message)) - - first_chat = True - chats = [] - while True: - result = ws.recv() - data = json.loads(result) - if "chat" in data: - if first_chat: - first_chat = False - # if the date of chat does not change from last batch, - # we assume we have fetched all the comments. - if data["chat"]["date"] == when: - sending = False - break - when = data["chat"]["date"] - chats.append(data) - else: - # reach the end of this batch - if "ping" in data and 'rf' in data["ping"]["content"]: - break - chats_all.extend(chats) - ws.close() + def download_comments(self, video_id, filename): + from ndgr_client import NDGRClient + import asyncio + + async def download(video_id, output, cookies, verbose=False): + ndgr_client = NDGRClient(video_id, verbose=verbose, console_output=True) + await ndgr_client.login(cookies=cookies) + + comments = await ndgr_client.downloadBackwardComments() + comments_count = len(comments) - # remove duplicate from chats_all - _ = [] - for d in chats_all: - if d not in _: - _.append(d) - chats_all = _ - chats_all.sort(key=lambda x: (x['chat']['date'], x['chat'].get('vpos', 0))) + with output.open(mode='w', encoding='utf-8') as f: + f.write('\n\n') + f.write(NDGRClient.convertToXMLString(comments)) + f.write('\n\n') + print(f'Total comments for {video_id}: {comments_count}') + print(f'Saved to {output}.') - dump_json(chats_all, self.save_dir / f'{filename}.json') - print(f'Total unique comments: {len(chats_all)}. Saved to "{filename}.json".') + cookies = self.session.cookies.get_dict() + output = self.save_dir / f'{filename}.xml' + asyncio.run(download(video_id, output, cookies)) def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', verbose=False, dump=False, auto_reserve=False): video_id, url, video_type = self._parse_url_or_video_id(url_or_video_id) @@ -244,9 +208,6 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v room_info = None stream_info = None - #TODO: fix danmaku downloading with the new method - # ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) - while True: verbose and print("Receiving...") result = ws.recv() @@ -255,31 +216,24 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v if data['type'] == 'stream': stream_info = data break - #TODO: danmaku downloading is temporarily disabled until the new method is implemented - # if data['type'] == 'room': - # room_info = data - # if comments in ['yes', 'only']: - # ex.submit(self.download_comments, room_info, end_time_epoch, filename) - # elif data['type'] == 'stream': - # stream_info = data - # # just grab all the info even if we don't need it, it doesn't save any time anyway. - # if room_info and stream_info: - # print('Got all the info we needed. Close WS.') - # break ws.close() if dump: dump_json(room_info, self.save_dir / f'{filename}.roominfo.json') dump_json(stream_info, self.save_dir / f'{filename}.streaminfo.json') - return_value.update({ 'room_info': room_info, 'stream_info': stream_info }) + ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) + if comments in ['yes', 'only']: + print('Downloading comments...') + ex.submit(self.download_comments, video_id, filename) + if comments == 'only': ex.shutdown(wait=True) - return_value['danmaku'] = self.save_dir / f'{filename}.json' + return_value['danmaku'] = self.save_dir / f'{filename}.xml' return return_value master_m3u8_url = stream_info['data']['uri'] @@ -300,6 +254,8 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v # See: https://stackoverflow.com/questions/74700723/ # Make sure to also use shell=True for *nix systems output = self.save_dir / f'{filename}.ts' + + # print(f'"{playlist_url}", "--key", "{audience_token},{max_quality}"') # a format that can be copied to launch.json cmd = f'minyami -d "{playlist_url}" --key {audience_token},{max_quality} -o "{output}"' if self.proxy: cmd += f' --proxy "{self.proxy}"' @@ -308,8 +264,7 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v print('CMD is:') print(cmd) run(cmd, shell=True) - # TODO: fix danmaku downloading with the new method - # ex.shutdown(wait=True) # ensure download_comments is finished + ex.shutdown(wait=True) # ensure download_comments is finished return_value.update({ 'master_m3u8_url': master_m3u8_url, @@ -357,7 +312,7 @@ def _split_lines(self, text, width): parser.add_argument('--dump', action='store_true', help='Dump all the metadata to json files.') parser.add_argument('--thumb', action='store_true', help='Download thumbnail only. Only works for video type (not live type).') parser.add_argument('--cookies', '-c', default='chrome', help='R|Cookie source. [Default: chrome]\nProvide either:\n - A browser name to fetch from;\n - The value of "user_session";\n - A Netscape-style cookie file.') - parser.add_argument('--comments', '-d', default='yes', choices=['yes', 'no', 'only'], help='Control if comments (danmaku) are downloaded. [Default: yes]') + parser.add_argument('--comments', '-d', default='no', choices=['yes', 'no', 'only'], help='Control if comments (danmaku) are downloaded. [Default: yes]') parser.add_argument('--proxy', default='auto', help='Specify a proxy, "none", or "auto" (automatically detects system proxy settings). [Default: auto]') parser.add_argument('--save-dir', '-o', help='Specify the directory to save the downloaded files. [Default: current directory]') parser.add_argument('--reserve', action='store_true', help='Automatically reserve timeshift ticket if not reserved yet. [Default: no]') diff --git a/util.py b/util.py index 6f3e48a..44dd300 100644 --- a/util.py +++ b/util.py @@ -831,7 +831,7 @@ def load_cookie(s): """ from http.cookiejar import MozillaCookieJar from requests.cookies import RequestsCookieJar, create_cookie - import browser_cookie3 + # import browser_cookie3 import rookiepy # pip install browser_cookie3 rookiepy From ad08519bb550d76a0aab9ac2e848aca5a3fe6e28 Mon Sep 17 00:00:00 2001 From: fireattack Date: Tue, 24 Sep 2024 17:44:06 +0800 Subject: [PATCH 04/39] nico: minor refactoring around danmaku --- README.md | 2 +- nico.py | 46 +++++++++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 19715b4..51398ff 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ options: - The value of "user_session"; - A Netscape-style cookie file. --comments {yes,no,only}, -d {yes,no,only} - Control if comments (danmaku) are downloaded. [Default: yes] + Control if comments (danmaku) are downloaded. [Default: no] --proxy PROXY Specify a proxy, "none", or "auto" (automatically detects system proxy settings). [Default: auto] --save-dir SAVE_DIR, -o SAVE_DIR Specify the directory to save the downloaded files. [Default: current directory] diff --git a/nico.py b/nico.py index b7bff09..ae2cbd8 100644 --- a/nico.py +++ b/nico.py @@ -86,9 +86,14 @@ def fetch_page(self, url): live_data = json.loads(soup.select_one('#embedded-data')['data-props']) return live_data - def download_comments(self, video_id, filename): - from ndgr_client import NDGRClient + def download_comments(self, video_id, output): import asyncio + try: + from ndgr_client import NDGRClient + except ImportError: + print('ERROR: Please install ndgr_client first.', style='bold red') + print('You can install it by running: "pip install git+https://github.com/tsukumijima/NDGRClient"') + return async def download(video_id, output, cookies, verbose=False): ndgr_client = NDGRClient(video_id, verbose=verbose, console_output=True) @@ -105,7 +110,6 @@ async def download(video_id, output, cookies, verbose=False): print(f'Saved to {output}.') cookies = self.session.cookies.get_dict() - output = self.save_dir / f'{filename}.xml' asyncio.run(download(video_id, output, cookies)) def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', verbose=False, dump=False, auto_reserve=False): @@ -169,9 +173,10 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v if auto_reserve or input('WARN: You do not have timeshift ticket. Do you want to reserve/activate it now? Y/[N] ').lower() == 'y': print('Reserving...') # POST = reserve, PATCH = activate/use - r = self.session.post(f'https://live2.nicovideo.jp/api/v2/programs/{video_id}/timeshift/reservation') + reservation_url = f'https://live2.nicovideo.jp/api/v2/programs/{video_id}/timeshift/reservation' + r = self.session.post(reservation_url) print('Tried POST, response:', r.status_code) - r = self.session.patch(f'https://live2.nicovideo.jp/api/v2/programs/{video_id}/timeshift/reservation') + r = self.session.patch(reservation_url) print('Tried PATCH, response:', r.status_code) if not r.status_code == 200: print('Reserving or activating failed. Please try reserving it manually in the webpage.') @@ -204,8 +209,24 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v # websocket.enableTrace(True) ws = self.create_ws(ws_url) verbose and print("Sent startWatching") - ws.send('{"type":"startWatching","data":{"stream":{"quality":"' + max_quality + '","protocol":"hls","latency":"low","chasePlay":false},"room":{"protocol":"webSocket","commentable":true},"reconnect":false}}') - room_info = None + start_watching_payload = { + "type": "startWatching", + "data": { + "stream": { + "quality": max_quality, + "protocol": "hls", + "latency": "low", + "chasePlay": False + }, + "room": { + "protocol": "webSocket", + "commentable": True + }, + "reconnect": False + } + } + verbose and print('Payload:', start_watching_payload) + ws.send(json.dumps(start_watching_payload)) stream_info = None while True: @@ -219,21 +240,20 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v ws.close() if dump: - dump_json(room_info, self.save_dir / f'{filename}.roominfo.json') dump_json(stream_info, self.save_dir / f'{filename}.streaminfo.json') return_value.update({ - 'room_info': room_info, 'stream_info': stream_info }) ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) if comments in ['yes', 'only']: print('Downloading comments...') - ex.submit(self.download_comments, video_id, filename) + danmaku_output = self.save_dir / f'{filename}.xml' + ex.submit(self.download_comments, video_id, danmaku_output) if comments == 'only': ex.shutdown(wait=True) - return_value['danmaku'] = self.save_dir / f'{filename}.xml' + return_value['danmaku'] = danmaku_output return return_value master_m3u8_url = stream_info['data']['uri'] @@ -270,7 +290,7 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', v 'master_m3u8_url': master_m3u8_url, 'playlist_m3u8_url': playlist_url, 'output': output, - 'danmaku': self.save_dir / f'{filename}.json' if comments in ['yes', 'only'] else None + 'danmaku': danmaku_output if comments in ['yes', 'only'] else None }) return return_value @@ -312,7 +332,7 @@ def _split_lines(self, text, width): parser.add_argument('--dump', action='store_true', help='Dump all the metadata to json files.') parser.add_argument('--thumb', action='store_true', help='Download thumbnail only. Only works for video type (not live type).') parser.add_argument('--cookies', '-c', default='chrome', help='R|Cookie source. [Default: chrome]\nProvide either:\n - A browser name to fetch from;\n - The value of "user_session";\n - A Netscape-style cookie file.') - parser.add_argument('--comments', '-d', default='no', choices=['yes', 'no', 'only'], help='Control if comments (danmaku) are downloaded. [Default: yes]') + parser.add_argument('--comments', '-d', default='no', choices=['yes', 'no', 'only'], help='Control if comments (danmaku) are downloaded. [Default: no]') parser.add_argument('--proxy', default='auto', help='Specify a proxy, "none", or "auto" (automatically detects system proxy settings). [Default: auto]') parser.add_argument('--save-dir', '-o', help='Specify the directory to save the downloaded files. [Default: current directory]') parser.add_argument('--reserve', action='store_true', help='Automatically reserve timeshift ticket if not reserved yet. [Default: no]') From 25f798693eb2322e6b4b7f7bcdbe66610ac66721 Mon Sep 17 00:00:00 2001 From: fireattack Date: Sun, 29 Sep 2024 04:19:36 +0800 Subject: [PATCH 05/39] nico: remove default cookie option, add a way to set settings in nico.txt --- README.md | 2 +- nico.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 51398ff..d988adb 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ options: --dump Dump all the metadata to json files. --thumb Download thumbnail only. Only works for video type (not live type). --cookies COOKIES, -c COOKIES - Cookie source. [Default: chrome] + Cookie source. Provide either: - A browser name to fetch from; - The value of "user_session"; diff --git a/nico.py b/nico.py index ae2cbd8..53fbd33 100644 --- a/nico.py +++ b/nico.py @@ -21,7 +21,7 @@ class NicoDownloader(): def __init__(self, cookies, proxy=None, save_dir=None): def validate_cookie(cookies): for cookie in cookies: - if cookie.name == 'user_session': + if cookie.name == 'user_session' and cookie.value: print('Find user_session in cookie:', cookie.value) break else: @@ -112,7 +112,7 @@ async def download(video_id, output, cookies, verbose=False): cookies = self.session.cookies.get_dict() asyncio.run(download(video_id, output, cookies)) - def download_timeshift(self, url_or_video_id, info_only=False, comments='yes', verbose=False, dump=False, auto_reserve=False): + def download_timeshift(self, url_or_video_id, info_only=False, comments='no', verbose=False, dump=False, auto_reserve=False): video_id, url, video_type = self._parse_url_or_video_id(url_or_video_id) return_value = { @@ -316,8 +316,17 @@ def download_thumbnail(self, url_or_video_id, info_only=False, dump=False): download(thumbnail_url, filename=self.save_dir / video_id) if __name__ == "__main__": + import shlex + import sys import argparse + # auto load arguments from nico.txt + for f in [Path(__file__).parent / 'nico.txt', Path('nico.txt')]: + if f.exists(): + with open(f, encoding='utf8') as f: + sys.argv.extend(shlex.split(f.read().replace('\\', '\\\\'))) + break + # https://stackoverflow.com/questions/3853722/how-to-insert-newlines-on-argparse-help-text class SmartFormatter(argparse.HelpFormatter): def _split_lines(self, text, width): @@ -331,7 +340,7 @@ def _split_lines(self, text, width): parser.add_argument('--info', '-i', action='store_true', help='Print info only.') parser.add_argument('--dump', action='store_true', help='Dump all the metadata to json files.') parser.add_argument('--thumb', action='store_true', help='Download thumbnail only. Only works for video type (not live type).') - parser.add_argument('--cookies', '-c', default='chrome', help='R|Cookie source. [Default: chrome]\nProvide either:\n - A browser name to fetch from;\n - The value of "user_session";\n - A Netscape-style cookie file.') + parser.add_argument('--cookies', '-c', help='R|Cookie source.\nProvide either:\n - A browser name to fetch from;\n - The value of "user_session";\n - A Netscape-style cookie file.') parser.add_argument('--comments', '-d', default='no', choices=['yes', 'no', 'only'], help='Control if comments (danmaku) are downloaded. [Default: no]') parser.add_argument('--proxy', default='auto', help='Specify a proxy, "none", or "auto" (automatically detects system proxy settings). [Default: auto]') parser.add_argument('--save-dir', '-o', help='Specify the directory to save the downloaded files. [Default: current directory]') From 2e2e2bb7bc697f3364a8e90bf188c95ab319577f Mon Sep 17 00:00:00 2001 From: fireattack Date: Thu, 3 Oct 2024 22:14:01 +0800 Subject: [PATCH 06/39] nico: native danmaku downloader --- nico.py | 96 +- proto/__init__.py | 0 .../nicolive/chat/data/atoms/moderator_pb2.py | 51 ++ .../chat/data/atoms/moderator_pb2.pyi | 195 +++++ .../nicolive/chat/data/atoms/sensitive_pb2.py | 34 + .../chat/data/atoms/sensitive_pb2.pyi | 8 + proto/dwango/nicolive/chat/data/atoms_pb2.py | 111 +++ proto/dwango/nicolive/chat/data/atoms_pb2.pyi | 826 ++++++++++++++++++ .../dwango/nicolive/chat/data/message_pb2.py | 38 + .../dwango/nicolive/chat/data/message_pb2.pyi | 63 ++ proto/dwango/nicolive/chat/data/origin_pb2.py | 38 + .../dwango/nicolive/chat/data/origin_pb2.pyi | 42 + proto/dwango/nicolive/chat/data/state_pb2.py | 38 + proto/dwango/nicolive/chat/data/state_pb2.pyi | 80 ++ .../nicolive/chat/service/edge/payload_pb2.py | 58 ++ .../chat/service/edge/payload_pb2.pyi | 231 +++++ 16 files changed, 1881 insertions(+), 28 deletions(-) create mode 100644 proto/__init__.py create mode 100644 proto/dwango/nicolive/chat/data/atoms/moderator_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/atoms/moderator_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/data/atoms_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/atoms_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/data/message_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/message_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/data/origin_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/origin_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/data/state_pb2.py create mode 100644 proto/dwango/nicolive/chat/data/state_pb2.pyi create mode 100644 proto/dwango/nicolive/chat/service/edge/payload_pb2.py create mode 100644 proto/dwango/nicolive/chat/service/edge/payload_pb2.pyi diff --git a/nico.py b/nico.py index 53fbd33..3b58976 100644 --- a/nico.py +++ b/nico.py @@ -6,15 +6,36 @@ from urllib.parse import urljoin, urlparse from urllib.request import getproxies from pathlib import Path - import websocket from rich.console import Console from rich.table import Table + from util import download, dump_json, get, MyTime, requests_retry_session, safeify, to_jp_time, load_cookie +from proto.dwango.nicolive.chat.service.edge import payload_pb2 as chat +import google.protobuf.json_format console = Console() print = console.print +# based on https://github.com/rinsuki-lab/ndgr-reader/blob/main/src/protobuf-stream-reader.ts +def read_protobuf_message(data): + offset = 0 + result = 0 + i = 0 + while True: + if offset >= len(data): + return None + current = data[offset] + result |= (current & 0x7F) << i + offset += 1 + i += 7 + if not (current & 0x80): + break + if offset + result > len(data): + return None + return data[offset:offset + result] + + class NicoDownloader(): HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'} @@ -86,31 +107,43 @@ def fetch_page(self, url): live_data = json.loads(soup.select_one('#embedded-data')['data-props']) return live_data - def download_comments(self, video_id, output): - import asyncio - try: - from ndgr_client import NDGRClient - except ImportError: - print('ERROR: Please install ndgr_client first.', style='bold red') - print('You can install it by running: "pip install git+https://github.com/tsukumijima/NDGRClient"') - return - - async def download(video_id, output, cookies, verbose=False): - ndgr_client = NDGRClient(video_id, verbose=verbose, console_output=True) - await ndgr_client.login(cookies=cookies) - - comments = await ndgr_client.downloadBackwardComments() - comments_count = len(comments) + def download_comments_native(self, message_server_info, output): + view_uri = message_server_info['data']['viewUri'] + #"vposBaseTime": "2024-09-25T21:50:00+09:00", + vpos_base_time_dt = datetime.strptime(message_server_info['data']['vposBaseTime'], '%Y-%m-%dT%H:%M:%S%z') + vpos_base_time_epoch = int(vpos_base_time_dt.timestamp()) + print(f'vpos Base time: {vpos_base_time_dt} ({vpos_base_time_epoch})') - with output.open(mode='w', encoding='utf-8') as f: - f.write('\n\n') - f.write(NDGRClient.convertToXMLString(comments)) - f.write('\n\n') - print(f'Total comments for {video_id}: {comments_count}') - print(f'Saved to {output}.') + at = 'now' + backward_api_uri = None + while True: + url = f'{view_uri}?&at={at}' + print(f'Fetch {url}') + r = self.session.get(url, timeout=30) + message = read_protobuf_message(r.content) + chunked_entry = chat.ChunkedEntry() + chunked_entry.ParseFromString(message) + if chunked_entry.HasField('next'): + at = chunked_entry.next.at + elif chunked_entry.HasField('backward'): + backward_api_uri = chunked_entry.backward.segment.uri + break + messages = [] + while True: + print(f'Fetch {backward_api_uri}') + r2 = self.session.get(backward_api_uri, timeout=30) + packed_segment = chat.PackedSegment() + packed_segment.ParseFromString(r2.content) + # prepend to messages + messages = [message for message in packed_segment.messages] + messages + if packed_segment.HasField('next'): + backward_api_uri = packed_segment.next.uri + else: + break + print(f'Find {len(messages)} messages.') + dump_json([google.protobuf.json_format.MessageToDict(message) for message in messages], output) + # TODO: convert the json to a format that is compatible with nicoxml2ass - cookies = self.session.cookies.get_dict() - asyncio.run(download(video_id, output, cookies)) def download_timeshift(self, url_or_video_id, info_only=False, comments='no', verbose=False, dump=False, auto_reserve=False): video_id, url, video_type = self._parse_url_or_video_id(url_or_video_id) @@ -128,8 +161,8 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='no', ve live_data = self.fetch_page(url) title = live_data['program']['title'] - end_time_epoch = live_data["program"]["endTime"] begin_time_epoch = live_data["program"]["beginTime"] + end_time_epoch = live_data["program"]["endTime"] begin_time_dt = to_jp_time(datetime.fromtimestamp(begin_time_epoch)) end_time_dt = to_jp_time(datetime.fromtimestamp(end_time_epoch)) @@ -228,6 +261,7 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='no', ve verbose and print('Payload:', start_watching_payload) ws.send(json.dumps(start_watching_payload)) stream_info = None + message_server_info = None while True: verbose and print("Receiving...") @@ -236,20 +270,26 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='no', ve data = json.loads(result) if data['type'] == 'stream': stream_info = data + elif data['type'] == 'messageServer': + message_server_info = data + if stream_info and message_server_info: + print('Got all the info we needed. Close WS connection.') break ws.close() if dump: dump_json(stream_info, self.save_dir / f'{filename}.streaminfo.json') + dump_json(message_server_info, self.save_dir / f'{filename}.msgserverinfo.json') return_value.update({ - 'stream_info': stream_info + 'stream_info': stream_info, + 'message_server_info': message_server_info }) ex = concurrent.futures.ThreadPoolExecutor(max_workers=1) if comments in ['yes', 'only']: print('Downloading comments...') - danmaku_output = self.save_dir / f'{filename}.xml' - ex.submit(self.download_comments, video_id, danmaku_output) + danmaku_output = self.save_dir / f'{filename}.json' + ex.submit(self.download_comments_native, message_server_info, end_time_dt, danmaku_output) if comments == 'only': ex.shutdown(wait=True) diff --git a/proto/__init__.py b/proto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.py b/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.py new file mode 100644 index 0000000..866e905 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/atoms/moderator.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/atoms/moderator.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/dwango/nicolive/chat/data/atoms/moderator.proto\x12\x1f\x64wango.nicolive.chat.data.atoms\x1a\x1fgoogle/protobuf/timestamp.proto\"j\n\x11ModeratorUserInfo\x12\x0f\n\x07user_id\x18\x01 \x01(\x03\x12\x15\n\x08nickname\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07iconUrl\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x0b\n\t_nicknameB\n\n\x08_iconUrl\"\x8b\x02\n\x10ModeratorUpdated\x12W\n\toperation\x18\x01 \x01(\x0e\x32\x44.dwango.nicolive.chat.data.atoms.ModeratorUpdated.ModeratorOperation\x12\x44\n\x08operator\x18\x02 \x01(\x0b\x32\x32.dwango.nicolive.chat.data.atoms.ModeratorUserInfo\x12-\n\tupdatedAt\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\")\n\x12ModeratorOperation\x12\x07\n\x03\x41\x44\x44\x10\x00\x12\n\n\x06\x44\x45LETE\x10\x01\"\xbb\x03\n\x0bSSNGUpdated\x12M\n\toperation\x18\x01 \x01(\x0e\x32:.dwango.nicolive.chat.data.atoms.SSNGUpdated.SSNGOperation\x12\x0f\n\x07ssng_id\x18\x02 \x01(\x03\x12\x44\n\x08operator\x18\x03 \x01(\x0b\x32\x32.dwango.nicolive.chat.data.atoms.ModeratorUserInfo\x12H\n\x04type\x18\x04 \x01(\x0e\x32\x35.dwango.nicolive.chat.data.atoms.SSNGUpdated.SSNGTypeH\x00\x88\x01\x01\x12\x13\n\x06source\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x32\n\tupdatedAt\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x02\x88\x01\x01\"$\n\rSSNGOperation\x12\x07\n\x03\x41\x44\x44\x10\x00\x12\n\n\x06\x44\x45LETE\x10\x01\"+\n\x08SSNGType\x12\x08\n\x04USER\x10\x00\x12\x08\n\x04WORD\x10\x01\x12\x0b\n\x07\x43OMMAND\x10\x02\x42\x07\n\x05_typeB\t\n\x07_sourceB\x0c\n\n_updatedAt\"\xa3\x02\n\x16ModerationAnnouncement\x12\x14\n\x07message\x18\x01 \x01(\tH\x00\x88\x01\x01\x12]\n\x0eguidelineItems\x18\x02 \x03(\x0e\x32\x45.dwango.nicolive.chat.data.atoms.ModerationAnnouncement.GuidelineItem\x12-\n\tupdatedAt\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"Y\n\rGuidelineItem\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06SEXUAL\x10\x01\x12\x08\n\x04SPAM\x10\x02\x12\x0b\n\x07SLANDER\x10\x03\x12\x18\n\x14PERSONAL_INFORMATION\x10\x04\x42\n\n\x08_messageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.atoms.moderator_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_MODERATORUSERINFO']._serialized_start=117 + _globals['_MODERATORUSERINFO']._serialized_end=223 + _globals['_MODERATORUPDATED']._serialized_start=226 + _globals['_MODERATORUPDATED']._serialized_end=493 + _globals['_MODERATORUPDATED_MODERATOROPERATION']._serialized_start=452 + _globals['_MODERATORUPDATED_MODERATOROPERATION']._serialized_end=493 + _globals['_SSNGUPDATED']._serialized_start=496 + _globals['_SSNGUPDATED']._serialized_end=939 + _globals['_SSNGUPDATED_SSNGOPERATION']._serialized_start=824 + _globals['_SSNGUPDATED_SSNGOPERATION']._serialized_end=860 + _globals['_SSNGUPDATED_SSNGTYPE']._serialized_start=862 + _globals['_SSNGUPDATED_SSNGTYPE']._serialized_end=905 + _globals['_MODERATIONANNOUNCEMENT']._serialized_start=942 + _globals['_MODERATIONANNOUNCEMENT']._serialized_end=1233 + _globals['_MODERATIONANNOUNCEMENT_GUIDELINEITEM']._serialized_start=1132 + _globals['_MODERATIONANNOUNCEMENT_GUIDELINEITEM']._serialized_end=1221 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.pyi b/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.pyi new file mode 100644 index 0000000..46df076 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms/moderator_pb2.pyi @@ -0,0 +1,195 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import google.protobuf.timestamp_pb2 +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class ModeratorUserInfo(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + USER_ID_FIELD_NUMBER: builtins.int + NICKNAME_FIELD_NUMBER: builtins.int + ICONURL_FIELD_NUMBER: builtins.int + user_id: builtins.int + nickname: builtins.str + iconUrl: builtins.str + def __init__( + self, + *, + user_id: builtins.int = ..., + nickname: builtins.str | None = ..., + iconUrl: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_iconUrl", b"_iconUrl", "_nickname", b"_nickname", "iconUrl", b"iconUrl", "nickname", b"nickname"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_iconUrl", b"_iconUrl", "_nickname", b"_nickname", "iconUrl", b"iconUrl", "nickname", b"nickname", "user_id", b"user_id"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_iconUrl", b"_iconUrl"]) -> typing.Literal["iconUrl"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_nickname", b"_nickname"]) -> typing.Literal["nickname"] | None: ... + +global___ModeratorUserInfo = ModeratorUserInfo + +@typing.final +class ModeratorUpdated(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _ModeratorOperation: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _ModeratorOperationEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ModeratorUpdated._ModeratorOperation.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + ADD: ModeratorUpdated._ModeratorOperation.ValueType # 0 + DELETE: ModeratorUpdated._ModeratorOperation.ValueType # 1 + + class ModeratorOperation(_ModeratorOperation, metaclass=_ModeratorOperationEnumTypeWrapper): ... + ADD: ModeratorUpdated.ModeratorOperation.ValueType # 0 + DELETE: ModeratorUpdated.ModeratorOperation.ValueType # 1 + + OPERATION_FIELD_NUMBER: builtins.int + OPERATOR_FIELD_NUMBER: builtins.int + UPDATEDAT_FIELD_NUMBER: builtins.int + operation: global___ModeratorUpdated.ModeratorOperation.ValueType + @property + def operator(self) -> global___ModeratorUserInfo: ... + @property + def updatedAt(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def __init__( + self, + *, + operation: global___ModeratorUpdated.ModeratorOperation.ValueType = ..., + operator: global___ModeratorUserInfo | None = ..., + updatedAt: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["operator", b"operator", "updatedAt", b"updatedAt"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["operation", b"operation", "operator", b"operator", "updatedAt", b"updatedAt"]) -> None: ... + +global___ModeratorUpdated = ModeratorUpdated + +@typing.final +class SSNGUpdated(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _SSNGOperation: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _SSNGOperationEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SSNGUpdated._SSNGOperation.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + ADD: SSNGUpdated._SSNGOperation.ValueType # 0 + DELETE: SSNGUpdated._SSNGOperation.ValueType # 1 + + class SSNGOperation(_SSNGOperation, metaclass=_SSNGOperationEnumTypeWrapper): ... + ADD: SSNGUpdated.SSNGOperation.ValueType # 0 + DELETE: SSNGUpdated.SSNGOperation.ValueType # 1 + + class _SSNGType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _SSNGTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SSNGUpdated._SSNGType.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + USER: SSNGUpdated._SSNGType.ValueType # 0 + WORD: SSNGUpdated._SSNGType.ValueType # 1 + COMMAND: SSNGUpdated._SSNGType.ValueType # 2 + + class SSNGType(_SSNGType, metaclass=_SSNGTypeEnumTypeWrapper): ... + USER: SSNGUpdated.SSNGType.ValueType # 0 + WORD: SSNGUpdated.SSNGType.ValueType # 1 + COMMAND: SSNGUpdated.SSNGType.ValueType # 2 + + OPERATION_FIELD_NUMBER: builtins.int + SSNG_ID_FIELD_NUMBER: builtins.int + OPERATOR_FIELD_NUMBER: builtins.int + TYPE_FIELD_NUMBER: builtins.int + SOURCE_FIELD_NUMBER: builtins.int + UPDATEDAT_FIELD_NUMBER: builtins.int + operation: global___SSNGUpdated.SSNGOperation.ValueType + ssng_id: builtins.int + type: global___SSNGUpdated.SSNGType.ValueType + source: builtins.str + @property + def operator(self) -> global___ModeratorUserInfo: ... + @property + def updatedAt(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def __init__( + self, + *, + operation: global___SSNGUpdated.SSNGOperation.ValueType = ..., + ssng_id: builtins.int = ..., + operator: global___ModeratorUserInfo | None = ..., + type: global___SSNGUpdated.SSNGType.ValueType | None = ..., + source: builtins.str | None = ..., + updatedAt: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_source", b"_source", "_type", b"_type", "_updatedAt", b"_updatedAt", "operator", b"operator", "source", b"source", "type", b"type", "updatedAt", b"updatedAt"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_source", b"_source", "_type", b"_type", "_updatedAt", b"_updatedAt", "operation", b"operation", "operator", b"operator", "source", b"source", "ssng_id", b"ssng_id", "type", b"type", "updatedAt", b"updatedAt"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_source", b"_source"]) -> typing.Literal["source"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_type", b"_type"]) -> typing.Literal["type"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_updatedAt", b"_updatedAt"]) -> typing.Literal["updatedAt"] | None: ... + +global___SSNGUpdated = SSNGUpdated + +@typing.final +class ModerationAnnouncement(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _GuidelineItem: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _GuidelineItemEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ModerationAnnouncement._GuidelineItem.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNKNOWN: ModerationAnnouncement._GuidelineItem.ValueType # 0 + SEXUAL: ModerationAnnouncement._GuidelineItem.ValueType # 1 + SPAM: ModerationAnnouncement._GuidelineItem.ValueType # 2 + SLANDER: ModerationAnnouncement._GuidelineItem.ValueType # 3 + PERSONAL_INFORMATION: ModerationAnnouncement._GuidelineItem.ValueType # 4 + + class GuidelineItem(_GuidelineItem, metaclass=_GuidelineItemEnumTypeWrapper): ... + UNKNOWN: ModerationAnnouncement.GuidelineItem.ValueType # 0 + SEXUAL: ModerationAnnouncement.GuidelineItem.ValueType # 1 + SPAM: ModerationAnnouncement.GuidelineItem.ValueType # 2 + SLANDER: ModerationAnnouncement.GuidelineItem.ValueType # 3 + PERSONAL_INFORMATION: ModerationAnnouncement.GuidelineItem.ValueType # 4 + + MESSAGE_FIELD_NUMBER: builtins.int + GUIDELINEITEMS_FIELD_NUMBER: builtins.int + UPDATEDAT_FIELD_NUMBER: builtins.int + message: builtins.str + @property + def guidelineItems(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[global___ModerationAnnouncement.GuidelineItem.ValueType]: ... + @property + def updatedAt(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def __init__( + self, + *, + message: builtins.str | None = ..., + guidelineItems: collections.abc.Iterable[global___ModerationAnnouncement.GuidelineItem.ValueType] | None = ..., + updatedAt: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_message", b"_message", "message", b"message", "updatedAt", b"updatedAt"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_message", b"_message", "guidelineItems", b"guidelineItems", "message", b"message", "updatedAt", b"updatedAt"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_message", b"_message"]) -> typing.Literal["message"] | None: ... + +global___ModerationAnnouncement = ModerationAnnouncement diff --git a/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.py b/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.py new file mode 100644 index 0000000..973c011 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/atoms/sensitive.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/atoms/sensitive.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/dwango/nicolive/chat/data/atoms/sensitive.proto\x12\x1f\x64wango.nicolive.chat.data.atomsb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.atoms.sensitive_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.pyi b/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.pyi new file mode 100644 index 0000000..dd854e2 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms/sensitive_pb2.pyi @@ -0,0 +1,8 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import google.protobuf.descriptor + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor diff --git a/proto/dwango/nicolive/chat/data/atoms_pb2.py b/proto/dwango/nicolive/chat/data/atoms_pb2.py new file mode 100644 index 0000000..4d031be --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms_pb2.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/atoms.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/atoms.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%dwango/nicolive/chat/data/atoms.proto\x12\x19\x64wango.nicolive.chat.data\x1a\x1egoogle/protobuf/duration.proto\"\xbc\t\n\x04\x43hat\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x0c\n\x04vpos\x18\x03 \x01(\x05\x12\x45\n\x0e\x61\x63\x63ount_status\x18\x04 \x01(\x0e\x32-.dwango.nicolive.chat.data.Chat.AccountStatus\x12\x11\n\x04name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0braw_user_id\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1b\n\x0ehashed_user_id\x18\x06 \x01(\tH\x02\x88\x01\x01\x12:\n\x08modifier\x18\x07 \x01(\x0b\x32(.dwango.nicolive.chat.data.Chat.Modifier\x12\n\n\x02no\x18\x08 \x01(\x05\x1a\xe3\x06\n\x08Modifier\x12>\n\x08position\x18\x01 \x01(\x0e\x32,.dwango.nicolive.chat.data.Chat.Modifier.Pos\x12;\n\x04size\x18\x02 \x01(\x0e\x32-.dwango.nicolive.chat.data.Chat.Modifier.Size\x12I\n\x0bnamed_color\x18\x03 \x01(\x0e\x32\x32.dwango.nicolive.chat.data.Chat.Modifier.ColorNameH\x00\x12H\n\nfull_color\x18\x04 \x01(\x0b\x32\x32.dwango.nicolive.chat.data.Chat.Modifier.FullColorH\x00\x12;\n\x04\x66ont\x18\x05 \x01(\x0e\x32-.dwango.nicolive.chat.data.Chat.Modifier.Font\x12\x41\n\x07opacity\x18\x06 \x01(\x0e\x32\x30.dwango.nicolive.chat.data.Chat.Modifier.Opacity\x1a,\n\tFullColor\x12\t\n\x01r\x18\x01 \x01(\x05\x12\t\n\x01g\x18\x02 \x01(\x05\x12\t\n\x01\x62\x18\x03 \x01(\x05\"\"\n\x03Pos\x12\x08\n\x04naka\x10\x00\x12\t\n\x05shita\x10\x01\x12\x06\n\x02ue\x10\x02\"&\n\x04Size\x12\n\n\x06medium\x10\x00\x12\t\n\x05small\x10\x01\x12\x07\n\x03\x62ig\x10\x02\"\xed\x01\n\tColorName\x12\t\n\x05white\x10\x00\x12\x07\n\x03red\x10\x01\x12\x08\n\x04pink\x10\x02\x12\n\n\x06orange\x10\x03\x12\n\n\x06yellow\x10\x04\x12\t\n\x05green\x10\x05\x12\x08\n\x04\x63yan\x10\x06\x12\x08\n\x04\x62lue\x10\x07\x12\n\n\x06purple\x10\x08\x12\t\n\x05\x62lack\x10\t\x12\n\n\x06white2\x10\n\x12\x08\n\x04red2\x10\x0b\x12\t\n\x05pink2\x10\x0c\x12\x0b\n\x07orange2\x10\r\x12\x0b\n\x07yellow2\x10\x0e\x12\n\n\x06green2\x10\x0f\x12\t\n\x05\x63yan2\x10\x10\x12\t\n\x05\x62lue2\x10\x11\x12\x0b\n\x07purple2\x10\x12\x12\n\n\x06\x62lack2\x10\x13\"*\n\x04\x46ont\x12\n\n\x06\x64\x65\x66ont\x10\x00\x12\n\n\x06mincho\x10\x01\x12\n\n\x06gothic\x10\x02\"&\n\x07Opacity\x12\n\n\x06Normal\x10\x00\x12\x0f\n\x0bTranslucent\x10\x01\x42\x07\n\x05\x63olor\"*\n\rAccountStatus\x12\x0c\n\x08Standard\x10\x00\x12\x0b\n\x07Premium\x10\x01\x42\x07\n\x05_nameB\x0e\n\x0c_raw_user_idB\x11\n\x0f_hashed_user_id\"\x96\x01\n\x0fOperatorComment\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x11\n\x04name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12:\n\x08modifier\x18\x03 \x01(\x0b\x32(.dwango.nicolive.chat.data.Chat.Modifier\x12\x11\n\x04link\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05_nameB\x07\n\x05_link\"Q\n\x04Jump\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\'\n\x04wait\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\"Q\n\x08Redirect\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\'\n\x04wait\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\"\xc7\x01\n\x12SimpleNotification\x12\x10\n\x06ichiba\x18\x01 \x01(\tH\x00\x12\x0f\n\x05quote\x18\x02 \x01(\tH\x00\x12\x11\n\x07\x65motion\x18\x03 \x01(\tH\x00\x12\x10\n\x06\x63ruise\x18\x04 \x01(\tH\x00\x12\x1a\n\x10program_extended\x18\x05 \x01(\tH\x00\x12\x14\n\nranking_in\x18\x06 \x01(\tH\x00\x12\x19\n\x0franking_updated\x18\x08 \x01(\tH\x00\x12\x11\n\x07visited\x18\x07 \x01(\tH\x00\x42\t\n\x07message\"\xd1\x01\n\x04Gift\x12\x0f\n\x07item_id\x18\x01 \x01(\t\x12\x1f\n\x12\x61\x64vertiser_user_id\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x17\n\x0f\x61\x64vertiser_name\x18\x03 \x01(\t\x12\r\n\x05point\x18\x04 \x01(\x03\x12\x0f\n\x07message\x18\x05 \x01(\t\x12\x11\n\titem_name\x18\x06 \x01(\t\x12\x1e\n\x11\x63ontribution_rank\x18\x07 \x01(\x05H\x01\x88\x01\x01\x42\x15\n\x13_advertiser_user_idB\x14\n\x12_contribution_rank\"\x87\x04\n\x06Nicoad\x12\x32\n\x02v0\x18\x01 \x01(\x0b\x32$.dwango.nicolive.chat.data.Nicoad.V0H\x00\x12\x32\n\x02v1\x18\x02 \x01(\x0b\x32$.dwango.nicolive.chat.data.Nicoad.V1H\x00\x1a\xd9\x02\n\x02V0\x12;\n\x06latest\x18\x01 \x01(\x0b\x32+.dwango.nicolive.chat.data.Nicoad.V0.Latest\x12=\n\x07ranking\x18\x02 \x03(\x0b\x32,.dwango.nicolive.chat.data.Nicoad.V0.Ranking\x12\x13\n\x0btotal_point\x18\x03 \x01(\x05\x1aM\n\x06Latest\x12\x12\n\nadvertiser\x18\x01 \x01(\t\x12\r\n\x05point\x18\x02 \x01(\x05\x12\x14\n\x07message\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_message\x1as\n\x07Ranking\x12\x12\n\nadvertiser\x18\x01 \x01(\t\x12\x0c\n\x04rank\x18\x02 \x01(\x05\x12\x14\n\x07message\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tuser_rank\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\n\n\x08_messageB\x0c\n\n_user_rank\x1a-\n\x02V1\x12\x16\n\x0etotal_ad_point\x18\x01 \x01(\x05\x12\x0f\n\x07message\x18\x02 \x01(\tB\n\n\x08versions\"t\n\x0b\x43ommentLock\x12=\n\x06status\x18\x01 \x01(\x0e\x32-.dwango.nicolive.chat.data.CommentLock.Status\"&\n\x06Status\x12\x10\n\x0cUnrestricted\x10\x00\x12\n\n\x06Locked\x10\x01\"\x80\x01\n\x0b\x43ommentMode\x12=\n\x06layout\x18\x01 \x01(\x0e\x32-.dwango.nicolive.chat.data.CommentMode.Layout\"2\n\x06Layout\x12\n\n\x06Normal\x10\x00\x12\x0c\n\x08SplitTop\x10\x01\x12\x0e\n\nBackground\x10\x02\"\x0c\n\nGameUpdate\"\xe4\x01\n\nTrialPanel\x12:\n\x05panel\x18\x01 \x01(\x0e\x32+.dwango.nicolive.chat.data.TrialPanel.Panel\x12\x44\n\x10unqualified_user\x18\x02 \x01(\x0e\x32*.dwango.nicolive.chat.data.TrialPanel.Mode\" \n\x05Panel\x12\n\n\x06Hidden\x10\x00\x12\x0b\n\x07\x44isplay\x10\x01\"2\n\x04Mode\x12\x0b\n\x07\x41llowed\x10\x00\x12\x0e\n\nRestricted\x10\x01\x12\r\n\tForbidden\x10\x02\"o\n\rProgramStatus\x12=\n\x05state\x18\x01 \x01(\x0e\x32..dwango.nicolive.chat.data.ProgramStatus.State\"\x1f\n\x05State\x12\x0b\n\x07Unknown\x10\x00\x12\t\n\x05\x45nded\x10\x01\"\xa9\x01\n\nTagUpdated\x12\x37\n\x04tags\x18\x01 \x03(\x0b\x32).dwango.nicolive.chat.data.TagUpdated.Tag\x12\x14\n\x0cowner_locked\x18\x02 \x01(\x08\x1aL\n\x03Tag\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x0e\n\x06locked\x18\x02 \x01(\x08\x12\x10\n\x08reserved\x18\x03 \x01(\x08\x12\x15\n\rnicopedia_uri\x18\x04 \x01(\t\"\xa8\x01\n\nStatistics\x12\x14\n\x07viewers\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x15\n\x08\x63omments\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\tad_points\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x18\n\x0bgift_points\x18\x04 \x01(\x03H\x03\x88\x01\x01\x42\n\n\x08_viewersB\x0b\n\t_commentsB\x0c\n\n_ad_pointsB\x0e\n\x0c_gift_pointsJ\x04\x08\x05\x10\x06\"\xe8\x01\n\x07Marquee\x12@\n\x07\x64isplay\x18\x01 \x01(\x0b\x32*.dwango.nicolive.chat.data.Marquee.DisplayH\x00\x88\x01\x01\x1a\x8e\x01\n\x07\x44isplay\x12\x44\n\x10operator_comment\x18\x01 \x01(\x0b\x32*.dwango.nicolive.chat.data.OperatorComment\x12\x30\n\x08\x64uration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x42\x0b\n\t_durationB\n\n\x08_display\"\x83\x02\n\x07\x45nquete\x12\x10\n\x08question\x18\x01 \x01(\t\x12:\n\x07\x63hoices\x18\x02 \x03(\x0b\x32).dwango.nicolive.chat.data.Enquete.Choice\x12\x39\n\x06status\x18\x03 \x01(\x0e\x32).dwango.nicolive.chat.data.Enquete.Status\x1a\x43\n\x06\x43hoice\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x16\n\tper_mille\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0c\n\n_per_mille\"*\n\x06Status\x12\n\n\x06\x43losed\x10\x00\x12\x08\n\x04Poll\x10\x01\x12\n\n\x06Result\x10\x02\"{\n\tMoveOrder\x12/\n\x04jump\x18\x01 \x01(\x0b\x32\x1f.dwango.nicolive.chat.data.JumpH\x00\x12\x37\n\x08redirect\x18\x02 \x01(\x0b\x32#.dwango.nicolive.chat.data.RedirectH\x00\x42\x04\n\x02tob\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.atoms_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CHAT']._serialized_start=101 + _globals['_CHAT']._serialized_end=1313 + _globals['_CHAT_MODIFIER']._serialized_start=358 + _globals['_CHAT_MODIFIER']._serialized_end=1225 + _globals['_CHAT_MODIFIER_FULLCOLOR']._serialized_start=772 + _globals['_CHAT_MODIFIER_FULLCOLOR']._serialized_end=816 + _globals['_CHAT_MODIFIER_POS']._serialized_start=818 + _globals['_CHAT_MODIFIER_POS']._serialized_end=852 + _globals['_CHAT_MODIFIER_SIZE']._serialized_start=854 + _globals['_CHAT_MODIFIER_SIZE']._serialized_end=892 + _globals['_CHAT_MODIFIER_COLORNAME']._serialized_start=895 + _globals['_CHAT_MODIFIER_COLORNAME']._serialized_end=1132 + _globals['_CHAT_MODIFIER_FONT']._serialized_start=1134 + _globals['_CHAT_MODIFIER_FONT']._serialized_end=1176 + _globals['_CHAT_MODIFIER_OPACITY']._serialized_start=1178 + _globals['_CHAT_MODIFIER_OPACITY']._serialized_end=1216 + _globals['_CHAT_ACCOUNTSTATUS']._serialized_start=1227 + _globals['_CHAT_ACCOUNTSTATUS']._serialized_end=1269 + _globals['_OPERATORCOMMENT']._serialized_start=1316 + _globals['_OPERATORCOMMENT']._serialized_end=1466 + _globals['_JUMP']._serialized_start=1468 + _globals['_JUMP']._serialized_end=1549 + _globals['_REDIRECT']._serialized_start=1551 + _globals['_REDIRECT']._serialized_end=1632 + _globals['_SIMPLENOTIFICATION']._serialized_start=1635 + _globals['_SIMPLENOTIFICATION']._serialized_end=1834 + _globals['_GIFT']._serialized_start=1837 + _globals['_GIFT']._serialized_end=2046 + _globals['_NICOAD']._serialized_start=2049 + _globals['_NICOAD']._serialized_end=2568 + _globals['_NICOAD_V0']._serialized_start=2164 + _globals['_NICOAD_V0']._serialized_end=2509 + _globals['_NICOAD_V0_LATEST']._serialized_start=2315 + _globals['_NICOAD_V0_LATEST']._serialized_end=2392 + _globals['_NICOAD_V0_RANKING']._serialized_start=2394 + _globals['_NICOAD_V0_RANKING']._serialized_end=2509 + _globals['_NICOAD_V1']._serialized_start=2511 + _globals['_NICOAD_V1']._serialized_end=2556 + _globals['_COMMENTLOCK']._serialized_start=2570 + _globals['_COMMENTLOCK']._serialized_end=2686 + _globals['_COMMENTLOCK_STATUS']._serialized_start=2648 + _globals['_COMMENTLOCK_STATUS']._serialized_end=2686 + _globals['_COMMENTMODE']._serialized_start=2689 + _globals['_COMMENTMODE']._serialized_end=2817 + _globals['_COMMENTMODE_LAYOUT']._serialized_start=2767 + _globals['_COMMENTMODE_LAYOUT']._serialized_end=2817 + _globals['_GAMEUPDATE']._serialized_start=2819 + _globals['_GAMEUPDATE']._serialized_end=2831 + _globals['_TRIALPANEL']._serialized_start=2834 + _globals['_TRIALPANEL']._serialized_end=3062 + _globals['_TRIALPANEL_PANEL']._serialized_start=2978 + _globals['_TRIALPANEL_PANEL']._serialized_end=3010 + _globals['_TRIALPANEL_MODE']._serialized_start=3012 + _globals['_TRIALPANEL_MODE']._serialized_end=3062 + _globals['_PROGRAMSTATUS']._serialized_start=3064 + _globals['_PROGRAMSTATUS']._serialized_end=3175 + _globals['_PROGRAMSTATUS_STATE']._serialized_start=3144 + _globals['_PROGRAMSTATUS_STATE']._serialized_end=3175 + _globals['_TAGUPDATED']._serialized_start=3178 + _globals['_TAGUPDATED']._serialized_end=3347 + _globals['_TAGUPDATED_TAG']._serialized_start=3271 + _globals['_TAGUPDATED_TAG']._serialized_end=3347 + _globals['_STATISTICS']._serialized_start=3350 + _globals['_STATISTICS']._serialized_end=3518 + _globals['_MARQUEE']._serialized_start=3521 + _globals['_MARQUEE']._serialized_end=3753 + _globals['_MARQUEE_DISPLAY']._serialized_start=3599 + _globals['_MARQUEE_DISPLAY']._serialized_end=3741 + _globals['_ENQUETE']._serialized_start=3756 + _globals['_ENQUETE']._serialized_end=4015 + _globals['_ENQUETE_CHOICE']._serialized_start=3904 + _globals['_ENQUETE_CHOICE']._serialized_end=3971 + _globals['_ENQUETE_STATUS']._serialized_start=3973 + _globals['_ENQUETE_STATUS']._serialized_end=4015 + _globals['_MOVEORDER']._serialized_start=4017 + _globals['_MOVEORDER']._serialized_end=4140 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/atoms_pb2.pyi b/proto/dwango/nicolive/chat/data/atoms_pb2.pyi new file mode 100644 index 0000000..c29b24e --- /dev/null +++ b/proto/dwango/nicolive/chat/data/atoms_pb2.pyi @@ -0,0 +1,826 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.duration_pb2 +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Chat(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _AccountStatus: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _AccountStatusEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat._AccountStatus.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Standard: Chat._AccountStatus.ValueType # 0 + Premium: Chat._AccountStatus.ValueType # 1 + + class AccountStatus(_AccountStatus, metaclass=_AccountStatusEnumTypeWrapper): ... + Standard: Chat.AccountStatus.ValueType # 0 + Premium: Chat.AccountStatus.ValueType # 1 + + @typing.final + class Modifier(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Pos: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _PosEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat.Modifier._Pos.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + naka: Chat.Modifier._Pos.ValueType # 0 + shita: Chat.Modifier._Pos.ValueType # 1 + ue: Chat.Modifier._Pos.ValueType # 2 + + class Pos(_Pos, metaclass=_PosEnumTypeWrapper): ... + naka: Chat.Modifier.Pos.ValueType # 0 + shita: Chat.Modifier.Pos.ValueType # 1 + ue: Chat.Modifier.Pos.ValueType # 2 + + class _Size: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _SizeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat.Modifier._Size.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + medium: Chat.Modifier._Size.ValueType # 0 + small: Chat.Modifier._Size.ValueType # 1 + big: Chat.Modifier._Size.ValueType # 2 + + class Size(_Size, metaclass=_SizeEnumTypeWrapper): ... + medium: Chat.Modifier.Size.ValueType # 0 + small: Chat.Modifier.Size.ValueType # 1 + big: Chat.Modifier.Size.ValueType # 2 + + class _ColorName: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _ColorNameEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat.Modifier._ColorName.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + white: Chat.Modifier._ColorName.ValueType # 0 + red: Chat.Modifier._ColorName.ValueType # 1 + pink: Chat.Modifier._ColorName.ValueType # 2 + orange: Chat.Modifier._ColorName.ValueType # 3 + yellow: Chat.Modifier._ColorName.ValueType # 4 + green: Chat.Modifier._ColorName.ValueType # 5 + cyan: Chat.Modifier._ColorName.ValueType # 6 + blue: Chat.Modifier._ColorName.ValueType # 7 + purple: Chat.Modifier._ColorName.ValueType # 8 + black: Chat.Modifier._ColorName.ValueType # 9 + white2: Chat.Modifier._ColorName.ValueType # 10 + red2: Chat.Modifier._ColorName.ValueType # 11 + pink2: Chat.Modifier._ColorName.ValueType # 12 + orange2: Chat.Modifier._ColorName.ValueType # 13 + yellow2: Chat.Modifier._ColorName.ValueType # 14 + green2: Chat.Modifier._ColorName.ValueType # 15 + cyan2: Chat.Modifier._ColorName.ValueType # 16 + blue2: Chat.Modifier._ColorName.ValueType # 17 + purple2: Chat.Modifier._ColorName.ValueType # 18 + black2: Chat.Modifier._ColorName.ValueType # 19 + + class ColorName(_ColorName, metaclass=_ColorNameEnumTypeWrapper): ... + white: Chat.Modifier.ColorName.ValueType # 0 + red: Chat.Modifier.ColorName.ValueType # 1 + pink: Chat.Modifier.ColorName.ValueType # 2 + orange: Chat.Modifier.ColorName.ValueType # 3 + yellow: Chat.Modifier.ColorName.ValueType # 4 + green: Chat.Modifier.ColorName.ValueType # 5 + cyan: Chat.Modifier.ColorName.ValueType # 6 + blue: Chat.Modifier.ColorName.ValueType # 7 + purple: Chat.Modifier.ColorName.ValueType # 8 + black: Chat.Modifier.ColorName.ValueType # 9 + white2: Chat.Modifier.ColorName.ValueType # 10 + red2: Chat.Modifier.ColorName.ValueType # 11 + pink2: Chat.Modifier.ColorName.ValueType # 12 + orange2: Chat.Modifier.ColorName.ValueType # 13 + yellow2: Chat.Modifier.ColorName.ValueType # 14 + green2: Chat.Modifier.ColorName.ValueType # 15 + cyan2: Chat.Modifier.ColorName.ValueType # 16 + blue2: Chat.Modifier.ColorName.ValueType # 17 + purple2: Chat.Modifier.ColorName.ValueType # 18 + black2: Chat.Modifier.ColorName.ValueType # 19 + + class _Font: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _FontEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat.Modifier._Font.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + defont: Chat.Modifier._Font.ValueType # 0 + mincho: Chat.Modifier._Font.ValueType # 1 + gothic: Chat.Modifier._Font.ValueType # 2 + + class Font(_Font, metaclass=_FontEnumTypeWrapper): ... + defont: Chat.Modifier.Font.ValueType # 0 + mincho: Chat.Modifier.Font.ValueType # 1 + gothic: Chat.Modifier.Font.ValueType # 2 + + class _Opacity: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _OpacityEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Chat.Modifier._Opacity.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Normal: Chat.Modifier._Opacity.ValueType # 0 + Translucent: Chat.Modifier._Opacity.ValueType # 1 + + class Opacity(_Opacity, metaclass=_OpacityEnumTypeWrapper): ... + Normal: Chat.Modifier.Opacity.ValueType # 0 + Translucent: Chat.Modifier.Opacity.ValueType # 1 + + @typing.final + class FullColor(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + R_FIELD_NUMBER: builtins.int + G_FIELD_NUMBER: builtins.int + B_FIELD_NUMBER: builtins.int + r: builtins.int + g: builtins.int + b: builtins.int + def __init__( + self, + *, + r: builtins.int = ..., + g: builtins.int = ..., + b: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["b", b"b", "g", b"g", "r", b"r"]) -> None: ... + + POSITION_FIELD_NUMBER: builtins.int + SIZE_FIELD_NUMBER: builtins.int + NAMED_COLOR_FIELD_NUMBER: builtins.int + FULL_COLOR_FIELD_NUMBER: builtins.int + FONT_FIELD_NUMBER: builtins.int + OPACITY_FIELD_NUMBER: builtins.int + position: global___Chat.Modifier.Pos.ValueType + size: global___Chat.Modifier.Size.ValueType + named_color: global___Chat.Modifier.ColorName.ValueType + font: global___Chat.Modifier.Font.ValueType + opacity: global___Chat.Modifier.Opacity.ValueType + @property + def full_color(self) -> global___Chat.Modifier.FullColor: ... + def __init__( + self, + *, + position: global___Chat.Modifier.Pos.ValueType = ..., + size: global___Chat.Modifier.Size.ValueType = ..., + named_color: global___Chat.Modifier.ColorName.ValueType = ..., + full_color: global___Chat.Modifier.FullColor | None = ..., + font: global___Chat.Modifier.Font.ValueType = ..., + opacity: global___Chat.Modifier.Opacity.ValueType = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["color", b"color", "full_color", b"full_color", "named_color", b"named_color"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["color", b"color", "font", b"font", "full_color", b"full_color", "named_color", b"named_color", "opacity", b"opacity", "position", b"position", "size", b"size"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["color", b"color"]) -> typing.Literal["named_color", "full_color"] | None: ... + + CONTENT_FIELD_NUMBER: builtins.int + VPOS_FIELD_NUMBER: builtins.int + ACCOUNT_STATUS_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + RAW_USER_ID_FIELD_NUMBER: builtins.int + HASHED_USER_ID_FIELD_NUMBER: builtins.int + MODIFIER_FIELD_NUMBER: builtins.int + NO_FIELD_NUMBER: builtins.int + content: builtins.str + vpos: builtins.int + account_status: global___Chat.AccountStatus.ValueType + name: builtins.str + raw_user_id: builtins.int + hashed_user_id: builtins.str + no: builtins.int + @property + def modifier(self) -> global___Chat.Modifier: ... + def __init__( + self, + *, + content: builtins.str = ..., + vpos: builtins.int = ..., + account_status: global___Chat.AccountStatus.ValueType = ..., + name: builtins.str | None = ..., + raw_user_id: builtins.int | None = ..., + hashed_user_id: builtins.str | None = ..., + modifier: global___Chat.Modifier | None = ..., + no: builtins.int = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_hashed_user_id", b"_hashed_user_id", "_name", b"_name", "_raw_user_id", b"_raw_user_id", "hashed_user_id", b"hashed_user_id", "modifier", b"modifier", "name", b"name", "raw_user_id", b"raw_user_id"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_hashed_user_id", b"_hashed_user_id", "_name", b"_name", "_raw_user_id", b"_raw_user_id", "account_status", b"account_status", "content", b"content", "hashed_user_id", b"hashed_user_id", "modifier", b"modifier", "name", b"name", "no", b"no", "raw_user_id", b"raw_user_id", "vpos", b"vpos"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_hashed_user_id", b"_hashed_user_id"]) -> typing.Literal["hashed_user_id"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_name", b"_name"]) -> typing.Literal["name"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_raw_user_id", b"_raw_user_id"]) -> typing.Literal["raw_user_id"] | None: ... + +global___Chat = Chat + +@typing.final +class OperatorComment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CONTENT_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + MODIFIER_FIELD_NUMBER: builtins.int + LINK_FIELD_NUMBER: builtins.int + content: builtins.str + name: builtins.str + link: builtins.str + @property + def modifier(self) -> global___Chat.Modifier: ... + def __init__( + self, + *, + content: builtins.str = ..., + name: builtins.str | None = ..., + modifier: global___Chat.Modifier | None = ..., + link: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_link", b"_link", "_name", b"_name", "link", b"link", "modifier", b"modifier", "name", b"name"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_link", b"_link", "_name", b"_name", "content", b"content", "link", b"link", "modifier", b"modifier", "name", b"name"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_link", b"_link"]) -> typing.Literal["link"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_name", b"_name"]) -> typing.Literal["name"] | None: ... + +global___OperatorComment = OperatorComment + +@typing.final +class Jump(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CONTENT_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + WAIT_FIELD_NUMBER: builtins.int + content: builtins.str + message: builtins.str + @property + def wait(self) -> google.protobuf.duration_pb2.Duration: ... + def __init__( + self, + *, + content: builtins.str = ..., + message: builtins.str = ..., + wait: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["wait", b"wait"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["content", b"content", "message", b"message", "wait", b"wait"]) -> None: ... + +global___Jump = Jump + +@typing.final +class Redirect(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + URI_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + WAIT_FIELD_NUMBER: builtins.int + uri: builtins.str + message: builtins.str + @property + def wait(self) -> google.protobuf.duration_pb2.Duration: ... + def __init__( + self, + *, + uri: builtins.str = ..., + message: builtins.str = ..., + wait: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["wait", b"wait"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["message", b"message", "uri", b"uri", "wait", b"wait"]) -> None: ... + +global___Redirect = Redirect + +@typing.final +class SimpleNotification(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ICHIBA_FIELD_NUMBER: builtins.int + QUOTE_FIELD_NUMBER: builtins.int + EMOTION_FIELD_NUMBER: builtins.int + CRUISE_FIELD_NUMBER: builtins.int + PROGRAM_EXTENDED_FIELD_NUMBER: builtins.int + RANKING_IN_FIELD_NUMBER: builtins.int + RANKING_UPDATED_FIELD_NUMBER: builtins.int + VISITED_FIELD_NUMBER: builtins.int + ichiba: builtins.str + quote: builtins.str + emotion: builtins.str + cruise: builtins.str + program_extended: builtins.str + ranking_in: builtins.str + ranking_updated: builtins.str + visited: builtins.str + def __init__( + self, + *, + ichiba: builtins.str = ..., + quote: builtins.str = ..., + emotion: builtins.str = ..., + cruise: builtins.str = ..., + program_extended: builtins.str = ..., + ranking_in: builtins.str = ..., + ranking_updated: builtins.str = ..., + visited: builtins.str = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["cruise", b"cruise", "emotion", b"emotion", "ichiba", b"ichiba", "message", b"message", "program_extended", b"program_extended", "quote", b"quote", "ranking_in", b"ranking_in", "ranking_updated", b"ranking_updated", "visited", b"visited"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["cruise", b"cruise", "emotion", b"emotion", "ichiba", b"ichiba", "message", b"message", "program_extended", b"program_extended", "quote", b"quote", "ranking_in", b"ranking_in", "ranking_updated", b"ranking_updated", "visited", b"visited"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["ichiba", "quote", "emotion", "cruise", "program_extended", "ranking_in", "ranking_updated", "visited"] | None: ... + +global___SimpleNotification = SimpleNotification + +@typing.final +class Gift(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ITEM_ID_FIELD_NUMBER: builtins.int + ADVERTISER_USER_ID_FIELD_NUMBER: builtins.int + ADVERTISER_NAME_FIELD_NUMBER: builtins.int + POINT_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + ITEM_NAME_FIELD_NUMBER: builtins.int + CONTRIBUTION_RANK_FIELD_NUMBER: builtins.int + item_id: builtins.str + advertiser_user_id: builtins.int + advertiser_name: builtins.str + point: builtins.int + message: builtins.str + item_name: builtins.str + contribution_rank: builtins.int + def __init__( + self, + *, + item_id: builtins.str = ..., + advertiser_user_id: builtins.int | None = ..., + advertiser_name: builtins.str = ..., + point: builtins.int = ..., + message: builtins.str = ..., + item_name: builtins.str = ..., + contribution_rank: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_advertiser_user_id", b"_advertiser_user_id", "_contribution_rank", b"_contribution_rank", "advertiser_user_id", b"advertiser_user_id", "contribution_rank", b"contribution_rank"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_advertiser_user_id", b"_advertiser_user_id", "_contribution_rank", b"_contribution_rank", "advertiser_name", b"advertiser_name", "advertiser_user_id", b"advertiser_user_id", "contribution_rank", b"contribution_rank", "item_id", b"item_id", "item_name", b"item_name", "message", b"message", "point", b"point"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_advertiser_user_id", b"_advertiser_user_id"]) -> typing.Literal["advertiser_user_id"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_contribution_rank", b"_contribution_rank"]) -> typing.Literal["contribution_rank"] | None: ... + +global___Gift = Gift + +@typing.final +class Nicoad(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class V0(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class Latest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ADVERTISER_FIELD_NUMBER: builtins.int + POINT_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + advertiser: builtins.str + point: builtins.int + message: builtins.str + def __init__( + self, + *, + advertiser: builtins.str = ..., + point: builtins.int = ..., + message: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_message", b"_message", "message", b"message"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_message", b"_message", "advertiser", b"advertiser", "message", b"message", "point", b"point"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_message", b"_message"]) -> typing.Literal["message"] | None: ... + + @typing.final + class Ranking(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ADVERTISER_FIELD_NUMBER: builtins.int + RANK_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + USER_RANK_FIELD_NUMBER: builtins.int + advertiser: builtins.str + rank: builtins.int + message: builtins.str + user_rank: builtins.int + def __init__( + self, + *, + advertiser: builtins.str = ..., + rank: builtins.int = ..., + message: builtins.str | None = ..., + user_rank: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_message", b"_message", "_user_rank", b"_user_rank", "message", b"message", "user_rank", b"user_rank"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_message", b"_message", "_user_rank", b"_user_rank", "advertiser", b"advertiser", "message", b"message", "rank", b"rank", "user_rank", b"user_rank"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_message", b"_message"]) -> typing.Literal["message"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_user_rank", b"_user_rank"]) -> typing.Literal["user_rank"] | None: ... + + LATEST_FIELD_NUMBER: builtins.int + RANKING_FIELD_NUMBER: builtins.int + TOTAL_POINT_FIELD_NUMBER: builtins.int + total_point: builtins.int + @property + def latest(self) -> global___Nicoad.V0.Latest: ... + @property + def ranking(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Nicoad.V0.Ranking]: ... + def __init__( + self, + *, + latest: global___Nicoad.V0.Latest | None = ..., + ranking: collections.abc.Iterable[global___Nicoad.V0.Ranking] | None = ..., + total_point: builtins.int = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["latest", b"latest"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["latest", b"latest", "ranking", b"ranking", "total_point", b"total_point"]) -> None: ... + + @typing.final + class V1(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TOTAL_AD_POINT_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + total_ad_point: builtins.int + message: builtins.str + def __init__( + self, + *, + total_ad_point: builtins.int = ..., + message: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["message", b"message", "total_ad_point", b"total_ad_point"]) -> None: ... + + V0_FIELD_NUMBER: builtins.int + V1_FIELD_NUMBER: builtins.int + @property + def v0(self) -> global___Nicoad.V0: ... + @property + def v1(self) -> global___Nicoad.V1: ... + def __init__( + self, + *, + v0: global___Nicoad.V0 | None = ..., + v1: global___Nicoad.V1 | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["v0", b"v0", "v1", b"v1", "versions", b"versions"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["v0", b"v0", "v1", b"v1", "versions", b"versions"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["versions", b"versions"]) -> typing.Literal["v0", "v1"] | None: ... + +global___Nicoad = Nicoad + +@typing.final +class CommentLock(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Status: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _StatusEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[CommentLock._Status.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Unrestricted: CommentLock._Status.ValueType # 0 + Locked: CommentLock._Status.ValueType # 1 + + class Status(_Status, metaclass=_StatusEnumTypeWrapper): ... + Unrestricted: CommentLock.Status.ValueType # 0 + Locked: CommentLock.Status.ValueType # 1 + + STATUS_FIELD_NUMBER: builtins.int + status: global___CommentLock.Status.ValueType + def __init__( + self, + *, + status: global___CommentLock.Status.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["status", b"status"]) -> None: ... + +global___CommentLock = CommentLock + +@typing.final +class CommentMode(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Layout: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _LayoutEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[CommentMode._Layout.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Normal: CommentMode._Layout.ValueType # 0 + SplitTop: CommentMode._Layout.ValueType # 1 + Background: CommentMode._Layout.ValueType # 2 + + class Layout(_Layout, metaclass=_LayoutEnumTypeWrapper): ... + Normal: CommentMode.Layout.ValueType # 0 + SplitTop: CommentMode.Layout.ValueType # 1 + Background: CommentMode.Layout.ValueType # 2 + + LAYOUT_FIELD_NUMBER: builtins.int + layout: global___CommentMode.Layout.ValueType + def __init__( + self, + *, + layout: global___CommentMode.Layout.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["layout", b"layout"]) -> None: ... + +global___CommentMode = CommentMode + +@typing.final +class GameUpdate(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___GameUpdate = GameUpdate + +@typing.final +class TrialPanel(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Panel: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _PanelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TrialPanel._Panel.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Hidden: TrialPanel._Panel.ValueType # 0 + Display: TrialPanel._Panel.ValueType # 1 + + class Panel(_Panel, metaclass=_PanelEnumTypeWrapper): ... + Hidden: TrialPanel.Panel.ValueType # 0 + Display: TrialPanel.Panel.ValueType # 1 + + class _Mode: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _ModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TrialPanel._Mode.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Allowed: TrialPanel._Mode.ValueType # 0 + Restricted: TrialPanel._Mode.ValueType # 1 + Forbidden: TrialPanel._Mode.ValueType # 2 + + class Mode(_Mode, metaclass=_ModeEnumTypeWrapper): ... + Allowed: TrialPanel.Mode.ValueType # 0 + Restricted: TrialPanel.Mode.ValueType # 1 + Forbidden: TrialPanel.Mode.ValueType # 2 + + PANEL_FIELD_NUMBER: builtins.int + UNQUALIFIED_USER_FIELD_NUMBER: builtins.int + panel: global___TrialPanel.Panel.ValueType + unqualified_user: global___TrialPanel.Mode.ValueType + def __init__( + self, + *, + panel: global___TrialPanel.Panel.ValueType = ..., + unqualified_user: global___TrialPanel.Mode.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["panel", b"panel", "unqualified_user", b"unqualified_user"]) -> None: ... + +global___TrialPanel = TrialPanel + +@typing.final +class ProgramStatus(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _State: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _StateEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ProgramStatus._State.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Unknown: ProgramStatus._State.ValueType # 0 + Ended: ProgramStatus._State.ValueType # 1 + + class State(_State, metaclass=_StateEnumTypeWrapper): ... + Unknown: ProgramStatus.State.ValueType # 0 + Ended: ProgramStatus.State.ValueType # 1 + + STATE_FIELD_NUMBER: builtins.int + state: global___ProgramStatus.State.ValueType + def __init__( + self, + *, + state: global___ProgramStatus.State.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["state", b"state"]) -> None: ... + +global___ProgramStatus = ProgramStatus + +@typing.final +class TagUpdated(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class Tag(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TEXT_FIELD_NUMBER: builtins.int + LOCKED_FIELD_NUMBER: builtins.int + RESERVED_FIELD_NUMBER: builtins.int + NICOPEDIA_URI_FIELD_NUMBER: builtins.int + text: builtins.str + locked: builtins.bool + reserved: builtins.bool + nicopedia_uri: builtins.str + def __init__( + self, + *, + text: builtins.str = ..., + locked: builtins.bool = ..., + reserved: builtins.bool = ..., + nicopedia_uri: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["locked", b"locked", "nicopedia_uri", b"nicopedia_uri", "reserved", b"reserved", "text", b"text"]) -> None: ... + + TAGS_FIELD_NUMBER: builtins.int + OWNER_LOCKED_FIELD_NUMBER: builtins.int + owner_locked: builtins.bool + @property + def tags(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___TagUpdated.Tag]: ... + def __init__( + self, + *, + tags: collections.abc.Iterable[global___TagUpdated.Tag] | None = ..., + owner_locked: builtins.bool = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["owner_locked", b"owner_locked", "tags", b"tags"]) -> None: ... + +global___TagUpdated = TagUpdated + +@typing.final +class Statistics(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VIEWERS_FIELD_NUMBER: builtins.int + COMMENTS_FIELD_NUMBER: builtins.int + AD_POINTS_FIELD_NUMBER: builtins.int + GIFT_POINTS_FIELD_NUMBER: builtins.int + viewers: builtins.int + comments: builtins.int + ad_points: builtins.int + gift_points: builtins.int + def __init__( + self, + *, + viewers: builtins.int | None = ..., + comments: builtins.int | None = ..., + ad_points: builtins.int | None = ..., + gift_points: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_ad_points", b"_ad_points", "_comments", b"_comments", "_gift_points", b"_gift_points", "_viewers", b"_viewers", "ad_points", b"ad_points", "comments", b"comments", "gift_points", b"gift_points", "viewers", b"viewers"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_ad_points", b"_ad_points", "_comments", b"_comments", "_gift_points", b"_gift_points", "_viewers", b"_viewers", "ad_points", b"ad_points", "comments", b"comments", "gift_points", b"gift_points", "viewers", b"viewers"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_ad_points", b"_ad_points"]) -> typing.Literal["ad_points"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_comments", b"_comments"]) -> typing.Literal["comments"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_gift_points", b"_gift_points"]) -> typing.Literal["gift_points"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_viewers", b"_viewers"]) -> typing.Literal["viewers"] | None: ... + +global___Statistics = Statistics + +@typing.final +class Marquee(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class Display(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + OPERATOR_COMMENT_FIELD_NUMBER: builtins.int + DURATION_FIELD_NUMBER: builtins.int + @property + def operator_comment(self) -> global___OperatorComment: ... + @property + def duration(self) -> google.protobuf.duration_pb2.Duration: ... + def __init__( + self, + *, + operator_comment: global___OperatorComment | None = ..., + duration: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_duration", b"_duration", "duration", b"duration", "operator_comment", b"operator_comment"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_duration", b"_duration", "duration", b"duration", "operator_comment", b"operator_comment"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_duration", b"_duration"]) -> typing.Literal["duration"] | None: ... + + DISPLAY_FIELD_NUMBER: builtins.int + @property + def display(self) -> global___Marquee.Display: ... + def __init__( + self, + *, + display: global___Marquee.Display | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_display", b"_display", "display", b"display"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_display", b"_display", "display", b"display"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_display", b"_display"]) -> typing.Literal["display"] | None: ... + +global___Marquee = Marquee + +@typing.final +class Enquete(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Status: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _StatusEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Enquete._Status.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Closed: Enquete._Status.ValueType # 0 + Poll: Enquete._Status.ValueType # 1 + Result: Enquete._Status.ValueType # 2 + + class Status(_Status, metaclass=_StatusEnumTypeWrapper): ... + Closed: Enquete.Status.ValueType # 0 + Poll: Enquete.Status.ValueType # 1 + Result: Enquete.Status.ValueType # 2 + + @typing.final + class Choice(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + DESCRIPTION_FIELD_NUMBER: builtins.int + PER_MILLE_FIELD_NUMBER: builtins.int + description: builtins.str + per_mille: builtins.int + def __init__( + self, + *, + description: builtins.str = ..., + per_mille: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_per_mille", b"_per_mille", "per_mille", b"per_mille"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_per_mille", b"_per_mille", "description", b"description", "per_mille", b"per_mille"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_per_mille", b"_per_mille"]) -> typing.Literal["per_mille"] | None: ... + + QUESTION_FIELD_NUMBER: builtins.int + CHOICES_FIELD_NUMBER: builtins.int + STATUS_FIELD_NUMBER: builtins.int + question: builtins.str + status: global___Enquete.Status.ValueType + @property + def choices(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Enquete.Choice]: ... + def __init__( + self, + *, + question: builtins.str = ..., + choices: collections.abc.Iterable[global___Enquete.Choice] | None = ..., + status: global___Enquete.Status.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["choices", b"choices", "question", b"question", "status", b"status"]) -> None: ... + +global___Enquete = Enquete + +@typing.final +class MoveOrder(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + JUMP_FIELD_NUMBER: builtins.int + REDIRECT_FIELD_NUMBER: builtins.int + @property + def jump(self) -> global___Jump: ... + @property + def redirect(self) -> global___Redirect: ... + def __init__( + self, + *, + jump: global___Jump | None = ..., + redirect: global___Redirect | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["jump", b"jump", "redirect", b"redirect", "to", b"to"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["jump", b"jump", "redirect", b"redirect", "to", b"to"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["to", b"to"]) -> typing.Literal["jump", "redirect"] | None: ... + +global___MoveOrder = MoveOrder diff --git a/proto/dwango/nicolive/chat/data/message_pb2.py b/proto/dwango/nicolive/chat/data/message_pb2.py new file mode 100644 index 0000000..296ad00 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/message_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/message.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/message.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from ndgr_client.proto.dwango.nicolive.chat.data import atoms_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_atoms__pb2 +from ndgr_client.proto.dwango.nicolive.chat.data.atoms import moderator_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_atoms_dot_moderator__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'dwango/nicolive/chat/data/message.proto\x12\x19\x64wango.nicolive.chat.data\x1a%dwango/nicolive/chat/data/atoms.proto\x1a/dwango/nicolive/chat/data/atoms/moderator.proto\"\xde\x04\n\x0fNicoliveMessage\x12/\n\x04\x63hat\x18\x01 \x01(\x0b\x32\x1f.dwango.nicolive.chat.data.ChatH\x00\x12L\n\x13simple_notification\x18\x07 \x01(\x0b\x32-.dwango.nicolive.chat.data.SimpleNotificationH\x00\x12/\n\x04gift\x18\x08 \x01(\x0b\x32\x1f.dwango.nicolive.chat.data.GiftH\x00\x12\x33\n\x06nicoad\x18\t \x01(\x0b\x32!.dwango.nicolive.chat.data.NicoadH\x00\x12<\n\x0bgame_update\x18\r \x01(\x0b\x32%.dwango.nicolive.chat.data.GameUpdateH\x00\x12<\n\x0btag_updated\x18\x11 \x01(\x0b\x32%.dwango.nicolive.chat.data.TagUpdatedH\x00\x12N\n\x11moderator_updated\x18\x12 \x01(\x0b\x32\x31.dwango.nicolive.chat.data.atoms.ModeratorUpdatedH\x00\x12\x44\n\x0cssng_updated\x18\x13 \x01(\x0b\x32,.dwango.nicolive.chat.data.atoms.SSNGUpdatedH\x00\x12:\n\x0foverflowed_chat\x18\x14 \x01(\x0b\x32\x1f.dwango.nicolive.chat.data.ChatH\x00\x42\x06\n\x04\x64\x61taJ\x04\x08\x02\x10\x07J\x04\x08\n\x10\rJ\x04\x08\x0e\x10\x11\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.message_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_NICOLIVEMESSAGE']._serialized_start=159 + _globals['_NICOLIVEMESSAGE']._serialized_end=765 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/message_pb2.pyi b/proto/dwango/nicolive/chat/data/message_pb2.pyi new file mode 100644 index 0000000..c9e629c --- /dev/null +++ b/proto/dwango/nicolive/chat/data/message_pb2.pyi @@ -0,0 +1,63 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2 +import ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2 +import google.protobuf.descriptor +import google.protobuf.message +import typing + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class NicoliveMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CHAT_FIELD_NUMBER: builtins.int + SIMPLE_NOTIFICATION_FIELD_NUMBER: builtins.int + GIFT_FIELD_NUMBER: builtins.int + NICOAD_FIELD_NUMBER: builtins.int + GAME_UPDATE_FIELD_NUMBER: builtins.int + TAG_UPDATED_FIELD_NUMBER: builtins.int + MODERATOR_UPDATED_FIELD_NUMBER: builtins.int + SSNG_UPDATED_FIELD_NUMBER: builtins.int + OVERFLOWED_CHAT_FIELD_NUMBER: builtins.int + @property + def chat(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Chat: ... + @property + def simple_notification(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.SimpleNotification: ... + @property + def gift(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Gift: ... + @property + def nicoad(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Nicoad: ... + @property + def game_update(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.GameUpdate: ... + @property + def tag_updated(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.TagUpdated: ... + @property + def moderator_updated(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.ModeratorUpdated: ... + @property + def ssng_updated(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.SSNGUpdated: ... + @property + def overflowed_chat(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Chat: ... + def __init__( + self, + *, + chat: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Chat | None = ..., + simple_notification: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.SimpleNotification | None = ..., + gift: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Gift | None = ..., + nicoad: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Nicoad | None = ..., + game_update: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.GameUpdate | None = ..., + tag_updated: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.TagUpdated | None = ..., + moderator_updated: ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.ModeratorUpdated | None = ..., + ssng_updated: ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.SSNGUpdated | None = ..., + overflowed_chat: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Chat | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["chat", b"chat", "data", b"data", "game_update", b"game_update", "gift", b"gift", "moderator_updated", b"moderator_updated", "nicoad", b"nicoad", "overflowed_chat", b"overflowed_chat", "simple_notification", b"simple_notification", "ssng_updated", b"ssng_updated", "tag_updated", b"tag_updated"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["chat", b"chat", "data", b"data", "game_update", b"game_update", "gift", b"gift", "moderator_updated", b"moderator_updated", "nicoad", b"nicoad", "overflowed_chat", b"overflowed_chat", "simple_notification", b"simple_notification", "ssng_updated", b"ssng_updated", "tag_updated", b"tag_updated"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["chat", "simple_notification", "gift", "nicoad", "game_update", "tag_updated", "moderator_updated", "ssng_updated", "overflowed_chat"] | None: ... + +global___NicoliveMessage = NicoliveMessage diff --git a/proto/dwango/nicolive/chat/data/origin_pb2.py b/proto/dwango/nicolive/chat/data/origin_pb2.py new file mode 100644 index 0000000..0648a92 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/origin_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/origin.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/origin.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&dwango/nicolive/chat/data/origin.proto\x12\x19\x64wango.nicolive.chat.data\"s\n\x0eNicoliveOrigin\x12>\n\x04\x63hat\x18\x01 \x01(\x0b\x32..dwango.nicolive.chat.data.NicoliveOrigin.ChatH\x00\x1a\x17\n\x04\x43hat\x12\x0f\n\x07live_id\x18\x01 \x01(\x03\x42\x08\n\x06originb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.origin_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_NICOLIVEORIGIN']._serialized_start=69 + _globals['_NICOLIVEORIGIN']._serialized_end=184 + _globals['_NICOLIVEORIGIN_CHAT']._serialized_start=151 + _globals['_NICOLIVEORIGIN_CHAT']._serialized_end=174 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/origin_pb2.pyi b/proto/dwango/nicolive/chat/data/origin_pb2.pyi new file mode 100644 index 0000000..3c53eff --- /dev/null +++ b/proto/dwango/nicolive/chat/data/origin_pb2.pyi @@ -0,0 +1,42 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import typing + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class NicoliveOrigin(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class Chat(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + LIVE_ID_FIELD_NUMBER: builtins.int + live_id: builtins.int + def __init__( + self, + *, + live_id: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["live_id", b"live_id"]) -> None: ... + + CHAT_FIELD_NUMBER: builtins.int + @property + def chat(self) -> global___NicoliveOrigin.Chat: ... + def __init__( + self, + *, + chat: global___NicoliveOrigin.Chat | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["chat", b"chat", "origin", b"origin"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["chat", b"chat", "origin", b"origin"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["origin", b"origin"]) -> typing.Literal["chat"] | None: ... + +global___NicoliveOrigin = NicoliveOrigin diff --git a/proto/dwango/nicolive/chat/data/state_pb2.py b/proto/dwango/nicolive/chat/data/state_pb2.py new file mode 100644 index 0000000..f29d399 --- /dev/null +++ b/proto/dwango/nicolive/chat/data/state_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/data/state.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/data/state.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from ndgr_client.proto.dwango.nicolive.chat.data import atoms_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_atoms__pb2 +from ndgr_client.proto.dwango.nicolive.chat.data.atoms import moderator_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_atoms_dot_moderator__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%dwango/nicolive/chat/data/state.proto\x12\x19\x64wango.nicolive.chat.data\x1a%dwango/nicolive/chat/data/atoms.proto\x1a/dwango/nicolive/chat/data/atoms/moderator.proto\"\x86\x06\n\rNicoliveState\x12>\n\nstatistics\x18\x01 \x01(\x0b\x32%.dwango.nicolive.chat.data.StatisticsH\x00\x88\x01\x01\x12\x38\n\x07\x65nquete\x18\x02 \x01(\x0b\x32\".dwango.nicolive.chat.data.EnqueteH\x01\x88\x01\x01\x12=\n\nmove_order\x18\x03 \x01(\x0b\x32$.dwango.nicolive.chat.data.MoveOrderH\x02\x88\x01\x01\x12\x38\n\x07marquee\x18\x04 \x01(\x0b\x32\".dwango.nicolive.chat.data.MarqueeH\x03\x88\x01\x01\x12\x41\n\x0c\x63omment_lock\x18\x05 \x01(\x0b\x32&.dwango.nicolive.chat.data.CommentLockH\x04\x88\x01\x01\x12\x41\n\x0c\x63omment_mode\x18\x06 \x01(\x0b\x32&.dwango.nicolive.chat.data.CommentModeH\x05\x88\x01\x01\x12?\n\x0btrial_panel\x18\x07 \x01(\x0b\x32%.dwango.nicolive.chat.data.TrialPanelH\x06\x88\x01\x01\x12\x45\n\x0eprogram_status\x18\t \x01(\x0b\x32(.dwango.nicolive.chat.data.ProgramStatusH\x07\x88\x01\x01\x12]\n\x17moderation_announcement\x18\n \x01(\x0b\x32\x37.dwango.nicolive.chat.data.atoms.ModerationAnnouncementH\x08\x88\x01\x01\x42\r\n\x0b_statisticsB\n\n\x08_enqueteB\r\n\x0b_move_orderB\n\n\x08_marqueeB\x0f\n\r_comment_lockB\x0f\n\r_comment_modeB\x0e\n\x0c_trial_panelB\x11\n\x0f_program_statusB\x1a\n\x18_moderation_announcementb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.data.state_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_NICOLIVESTATE']._serialized_start=157 + _globals['_NICOLIVESTATE']._serialized_end=931 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/data/state_pb2.pyi b/proto/dwango/nicolive/chat/data/state_pb2.pyi new file mode 100644 index 0000000..9f225eb --- /dev/null +++ b/proto/dwango/nicolive/chat/data/state_pb2.pyi @@ -0,0 +1,80 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2 +import ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2 +import google.protobuf.descriptor +import google.protobuf.message +import typing + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class NicoliveState(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + STATISTICS_FIELD_NUMBER: builtins.int + ENQUETE_FIELD_NUMBER: builtins.int + MOVE_ORDER_FIELD_NUMBER: builtins.int + MARQUEE_FIELD_NUMBER: builtins.int + COMMENT_LOCK_FIELD_NUMBER: builtins.int + COMMENT_MODE_FIELD_NUMBER: builtins.int + TRIAL_PANEL_FIELD_NUMBER: builtins.int + PROGRAM_STATUS_FIELD_NUMBER: builtins.int + MODERATION_ANNOUNCEMENT_FIELD_NUMBER: builtins.int + @property + def statistics(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Statistics: ... + @property + def enquete(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Enquete: ... + @property + def move_order(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.MoveOrder: ... + @property + def marquee(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Marquee: ... + @property + def comment_lock(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.CommentLock: ... + @property + def comment_mode(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.CommentMode: ... + @property + def trial_panel(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.TrialPanel: ... + @property + def program_status(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.ProgramStatus: ... + @property + def moderation_announcement(self) -> ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.ModerationAnnouncement: ... + def __init__( + self, + *, + statistics: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Statistics | None = ..., + enquete: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Enquete | None = ..., + move_order: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.MoveOrder | None = ..., + marquee: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.Marquee | None = ..., + comment_lock: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.CommentLock | None = ..., + comment_mode: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.CommentMode | None = ..., + trial_panel: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.TrialPanel | None = ..., + program_status: ndgr_client.proto.dwango.nicolive.chat.data.atoms_pb2.ProgramStatus | None = ..., + moderation_announcement: ndgr_client.proto.dwango.nicolive.chat.data.atoms.moderator_pb2.ModerationAnnouncement | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["_comment_lock", b"_comment_lock", "_comment_mode", b"_comment_mode", "_enquete", b"_enquete", "_marquee", b"_marquee", "_moderation_announcement", b"_moderation_announcement", "_move_order", b"_move_order", "_program_status", b"_program_status", "_statistics", b"_statistics", "_trial_panel", b"_trial_panel", "comment_lock", b"comment_lock", "comment_mode", b"comment_mode", "enquete", b"enquete", "marquee", b"marquee", "moderation_announcement", b"moderation_announcement", "move_order", b"move_order", "program_status", b"program_status", "statistics", b"statistics", "trial_panel", b"trial_panel"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_comment_lock", b"_comment_lock", "_comment_mode", b"_comment_mode", "_enquete", b"_enquete", "_marquee", b"_marquee", "_moderation_announcement", b"_moderation_announcement", "_move_order", b"_move_order", "_program_status", b"_program_status", "_statistics", b"_statistics", "_trial_panel", b"_trial_panel", "comment_lock", b"comment_lock", "comment_mode", b"comment_mode", "enquete", b"enquete", "marquee", b"marquee", "moderation_announcement", b"moderation_announcement", "move_order", b"move_order", "program_status", b"program_status", "statistics", b"statistics", "trial_panel", b"trial_panel"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_comment_lock", b"_comment_lock"]) -> typing.Literal["comment_lock"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_comment_mode", b"_comment_mode"]) -> typing.Literal["comment_mode"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_enquete", b"_enquete"]) -> typing.Literal["enquete"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_marquee", b"_marquee"]) -> typing.Literal["marquee"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_moderation_announcement", b"_moderation_announcement"]) -> typing.Literal["moderation_announcement"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_move_order", b"_move_order"]) -> typing.Literal["move_order"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_program_status", b"_program_status"]) -> typing.Literal["program_status"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_statistics", b"_statistics"]) -> typing.Literal["statistics"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_trial_panel", b"_trial_panel"]) -> typing.Literal["trial_panel"] | None: ... + +global___NicoliveState = NicoliveState diff --git a/proto/dwango/nicolive/chat/service/edge/payload_pb2.py b/proto/dwango/nicolive/chat/service/edge/payload_pb2.py new file mode 100644 index 0000000..ca4096c --- /dev/null +++ b/proto/dwango/nicolive/chat/service/edge/payload_pb2.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dwango/nicolive/chat/service/edge/payload.proto +# Protobuf Python Version: 5.27.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 27, + 0, + '', + 'dwango/nicolive/chat/service/edge/payload.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from ndgr_client.proto.dwango.nicolive.chat.data import message_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_message__pb2 +from ndgr_client.proto.dwango.nicolive.chat.data import state_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_state__pb2 +from ndgr_client.proto.dwango.nicolive.chat.data import origin_pb2 as dwango_dot_nicolive_dot_chat_dot_data_dot_origin__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/dwango/nicolive/chat/service/edge/payload.proto\x12!dwango.nicolive.chat.service.edge\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\'dwango/nicolive/chat/data/message.proto\x1a%dwango/nicolive/chat/data/state.proto\x1a&dwango/nicolive/chat/data/origin.proto\"\xb5\x03\n\x0e\x43hunkedMessage\x12\x44\n\x04meta\x18\x01 \x01(\x0b\x32\x36.dwango.nicolive.chat.service.edge.ChunkedMessage.Meta\x12=\n\x07message\x18\x02 \x01(\x0b\x32*.dwango.nicolive.chat.data.NicoliveMessageH\x00\x12\x39\n\x05state\x18\x04 \x01(\x0b\x32(.dwango.nicolive.chat.data.NicoliveStateH\x00\x12J\n\x06signal\x18\x05 \x01(\x0e\x32\x38.dwango.nicolive.chat.service.edge.ChunkedMessage.SignalH\x00\x1au\n\x04Meta\x12\n\n\x02id\x18\x01 \x01(\t\x12&\n\x02\x61t\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x06origin\x18\x03 \x01(\x0b\x32).dwango.nicolive.chat.data.NicoliveOrigin\"\x15\n\x06Signal\x12\x0b\n\x07\x46lushed\x10\x00\x42\t\n\x07payload\"\x9e\x02\n\rPackedSegment\x12\x43\n\x08messages\x18\x01 \x03(\x0b\x32\x31.dwango.nicolive.chat.service.edge.ChunkedMessage\x12\x43\n\x04next\x18\x02 \x01(\x0b\x32\x35.dwango.nicolive.chat.service.edge.PackedSegment.Next\x12P\n\x08snapshot\x18\x03 \x01(\x0b\x32>.dwango.nicolive.chat.service.edge.PackedSegment.StateSnapshot\x1a\x13\n\x04Next\x12\x0b\n\x03uri\x18\x01 \x01(\t\x1a\x1c\n\rStateSnapshot\x12\x0b\n\x03uri\x18\x01 \x01(\t\"\xd6\x02\n\x0c\x43hunkedEntry\x12\x46\n\x08\x62\x61\x63kward\x18\x02 \x01(\x0b\x32\x32.dwango.nicolive.chat.service.edge.BackwardSegmentH\x00\x12\x45\n\x08previous\x18\x03 \x01(\x0b\x32\x31.dwango.nicolive.chat.service.edge.MessageSegmentH\x00\x12\x44\n\x07segment\x18\x01 \x01(\x0b\x32\x31.dwango.nicolive.chat.service.edge.MessageSegmentH\x00\x12L\n\x04next\x18\x04 \x01(\x0b\x32<.dwango.nicolive.chat.service.edge.ChunkedEntry.ReadyForNextH\x00\x1a\x1a\n\x0cReadyForNext\x12\n\n\x02\x61t\x18\x01 \x01(\x03\x42\x07\n\x05\x65ntry\"s\n\x0eMessageSegment\x12)\n\x05\x66rom_\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12)\n\x05until\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0b\n\x03uri\x18\x03 \x01(\t\"\xd6\x01\n\x0f\x42\x61\x63kwardSegment\x12)\n\x05until\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x46\n\x07segment\x18\x02 \x01(\x0b\x32\x35.dwango.nicolive.chat.service.edge.PackedSegment.Next\x12P\n\x08snapshot\x18\x03 \x01(\x0b\x32>.dwango.nicolive.chat.service.edge.PackedSegment.StateSnapshotb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dwango.nicolive.chat.service.edge.payload_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CHUNKEDMESSAGE']._serialized_start=240 + _globals['_CHUNKEDMESSAGE']._serialized_end=677 + _globals['_CHUNKEDMESSAGE_META']._serialized_start=526 + _globals['_CHUNKEDMESSAGE_META']._serialized_end=643 + _globals['_CHUNKEDMESSAGE_SIGNAL']._serialized_start=645 + _globals['_CHUNKEDMESSAGE_SIGNAL']._serialized_end=666 + _globals['_PACKEDSEGMENT']._serialized_start=680 + _globals['_PACKEDSEGMENT']._serialized_end=966 + _globals['_PACKEDSEGMENT_NEXT']._serialized_start=917 + _globals['_PACKEDSEGMENT_NEXT']._serialized_end=936 + _globals['_PACKEDSEGMENT_STATESNAPSHOT']._serialized_start=938 + _globals['_PACKEDSEGMENT_STATESNAPSHOT']._serialized_end=966 + _globals['_CHUNKEDENTRY']._serialized_start=969 + _globals['_CHUNKEDENTRY']._serialized_end=1311 + _globals['_CHUNKEDENTRY_READYFORNEXT']._serialized_start=1276 + _globals['_CHUNKEDENTRY_READYFORNEXT']._serialized_end=1302 + _globals['_MESSAGESEGMENT']._serialized_start=1313 + _globals['_MESSAGESEGMENT']._serialized_end=1428 + _globals['_BACKWARDSEGMENT']._serialized_start=1431 + _globals['_BACKWARDSEGMENT']._serialized_end=1645 +# @@protoc_insertion_point(module_scope) diff --git a/proto/dwango/nicolive/chat/service/edge/payload_pb2.pyi b/proto/dwango/nicolive/chat/service/edge/payload_pb2.pyi new file mode 100644 index 0000000..e675e34 --- /dev/null +++ b/proto/dwango/nicolive/chat/service/edge/payload_pb2.pyi @@ -0,0 +1,231 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import ndgr_client.proto.dwango.nicolive.chat.data.message_pb2 +import ndgr_client.proto.dwango.nicolive.chat.data.origin_pb2 +import ndgr_client.proto.dwango.nicolive.chat.data.state_pb2 +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import google.protobuf.timestamp_pb2 +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class ChunkedMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Signal: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _SignalEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ChunkedMessage._Signal.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + Flushed: ChunkedMessage._Signal.ValueType # 0 + + class Signal(_Signal, metaclass=_SignalEnumTypeWrapper): ... + Flushed: ChunkedMessage.Signal.ValueType # 0 + + @typing.final + class Meta(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + AT_FIELD_NUMBER: builtins.int + ORIGIN_FIELD_NUMBER: builtins.int + id: builtins.str + @property + def at(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + @property + def origin(self) -> ndgr_client.proto.dwango.nicolive.chat.data.origin_pb2.NicoliveOrigin: ... + def __init__( + self, + *, + id: builtins.str = ..., + at: google.protobuf.timestamp_pb2.Timestamp | None = ..., + origin: ndgr_client.proto.dwango.nicolive.chat.data.origin_pb2.NicoliveOrigin | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["at", b"at", "origin", b"origin"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["at", b"at", "id", b"id", "origin", b"origin"]) -> None: ... + + META_FIELD_NUMBER: builtins.int + MESSAGE_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + SIGNAL_FIELD_NUMBER: builtins.int + signal: global___ChunkedMessage.Signal.ValueType + @property + def meta(self) -> global___ChunkedMessage.Meta: ... + @property + def message(self) -> ndgr_client.proto.dwango.nicolive.chat.data.message_pb2.NicoliveMessage: ... + @property + def state(self) -> ndgr_client.proto.dwango.nicolive.chat.data.state_pb2.NicoliveState: ... + def __init__( + self, + *, + meta: global___ChunkedMessage.Meta | None = ..., + message: ndgr_client.proto.dwango.nicolive.chat.data.message_pb2.NicoliveMessage | None = ..., + state: ndgr_client.proto.dwango.nicolive.chat.data.state_pb2.NicoliveState | None = ..., + signal: global___ChunkedMessage.Signal.ValueType = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["message", b"message", "meta", b"meta", "payload", b"payload", "signal", b"signal", "state", b"state"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["message", b"message", "meta", b"meta", "payload", b"payload", "signal", b"signal", "state", b"state"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["payload", b"payload"]) -> typing.Literal["message", "state", "signal"] | None: ... + +global___ChunkedMessage = ChunkedMessage + +@typing.final +class PackedSegment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class Next(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + URI_FIELD_NUMBER: builtins.int + uri: builtins.str + def __init__( + self, + *, + uri: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["uri", b"uri"]) -> None: ... + + @typing.final + class StateSnapshot(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + URI_FIELD_NUMBER: builtins.int + uri: builtins.str + def __init__( + self, + *, + uri: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["uri", b"uri"]) -> None: ... + + MESSAGES_FIELD_NUMBER: builtins.int + NEXT_FIELD_NUMBER: builtins.int + SNAPSHOT_FIELD_NUMBER: builtins.int + @property + def messages(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ChunkedMessage]: ... + @property + def next(self) -> global___PackedSegment.Next: ... + @property + def snapshot(self) -> global___PackedSegment.StateSnapshot: ... + def __init__( + self, + *, + messages: collections.abc.Iterable[global___ChunkedMessage] | None = ..., + next: global___PackedSegment.Next | None = ..., + snapshot: global___PackedSegment.StateSnapshot | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["next", b"next", "snapshot", b"snapshot"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["messages", b"messages", "next", b"next", "snapshot", b"snapshot"]) -> None: ... + +global___PackedSegment = PackedSegment + +@typing.final +class ChunkedEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing.final + class ReadyForNext(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + AT_FIELD_NUMBER: builtins.int + at: builtins.int + def __init__( + self, + *, + at: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["at", b"at"]) -> None: ... + + BACKWARD_FIELD_NUMBER: builtins.int + PREVIOUS_FIELD_NUMBER: builtins.int + SEGMENT_FIELD_NUMBER: builtins.int + NEXT_FIELD_NUMBER: builtins.int + @property + def backward(self) -> global___BackwardSegment: ... + @property + def previous(self) -> global___MessageSegment: ... + @property + def segment(self) -> global___MessageSegment: ... + @property + def next(self) -> global___ChunkedEntry.ReadyForNext: ... + def __init__( + self, + *, + backward: global___BackwardSegment | None = ..., + previous: global___MessageSegment | None = ..., + segment: global___MessageSegment | None = ..., + next: global___ChunkedEntry.ReadyForNext | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["backward", b"backward", "entry", b"entry", "next", b"next", "previous", b"previous", "segment", b"segment"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["backward", b"backward", "entry", b"entry", "next", b"next", "previous", b"previous", "segment", b"segment"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["entry", b"entry"]) -> typing.Literal["backward", "previous", "segment", "next"] | None: ... + +global___ChunkedEntry = ChunkedEntry + +@typing.final +class MessageSegment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FROM__FIELD_NUMBER: builtins.int + UNTIL_FIELD_NUMBER: builtins.int + URI_FIELD_NUMBER: builtins.int + uri: builtins.str + @property + def from_(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Python では from が予約されているため from_ として命名している""" + + @property + def until(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def __init__( + self, + *, + from_: google.protobuf.timestamp_pb2.Timestamp | None = ..., + until: google.protobuf.timestamp_pb2.Timestamp | None = ..., + uri: builtins.str = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["from_", b"from_", "until", b"until"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["from_", b"from_", "until", b"until", "uri", b"uri"]) -> None: ... + +global___MessageSegment = MessageSegment + +@typing.final +class BackwardSegment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + UNTIL_FIELD_NUMBER: builtins.int + SEGMENT_FIELD_NUMBER: builtins.int + SNAPSHOT_FIELD_NUMBER: builtins.int + @property + def until(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + @property + def segment(self) -> global___PackedSegment.Next: ... + @property + def snapshot(self) -> global___PackedSegment.StateSnapshot: ... + def __init__( + self, + *, + until: google.protobuf.timestamp_pb2.Timestamp | None = ..., + segment: global___PackedSegment.Next | None = ..., + snapshot: global___PackedSegment.StateSnapshot | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["segment", b"segment", "snapshot", b"snapshot", "until", b"until"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["segment", b"segment", "snapshot", b"snapshot", "until", b"until"]) -> None: ... + +global___BackwardSegment = BackwardSegment From 7472726146a7fc1546f9c94a126780b5377506c5 Mon Sep 17 00:00:00 2001 From: fireattack Date: Wed, 16 Oct 2024 10:31:12 +0800 Subject: [PATCH 07/39] minor fix --- nico.py | 5 +++-- util.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/nico.py b/nico.py index 3b58976..0a077bb 100644 --- a/nico.py +++ b/nico.py @@ -289,11 +289,13 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='no', ve if comments in ['yes', 'only']: print('Downloading comments...') danmaku_output = self.save_dir / f'{filename}.json' + return_value['danmaku'] = danmaku_output ex.submit(self.download_comments_native, message_server_info, end_time_dt, danmaku_output) + else: + return_value['danmaku'] = None if comments == 'only': ex.shutdown(wait=True) - return_value['danmaku'] = danmaku_output return return_value master_m3u8_url = stream_info['data']['uri'] @@ -330,7 +332,6 @@ def download_timeshift(self, url_or_video_id, info_only=False, comments='no', ve 'master_m3u8_url': master_m3u8_url, 'playlist_m3u8_url': playlist_url, 'output': output, - 'danmaku': danmaku_output if comments in ['yes', 'only'] else None }) return return_value diff --git a/util.py b/util.py index 44dd300..8831b7e 100644 --- a/util.py +++ b/util.py @@ -30,7 +30,7 @@ # ==================== data structure manipulation & misc. ==================== def to_list(a): - return a if not a or isinstance(a, list) else [a] + return a if isinstance(a, list) or a is None else [a] def flatten(x): from collections.abc import Iterable From 29bcf132b4dc22e111756a5a15eec3fc6ad4c65a Mon Sep 17 00:00:00 2001 From: fireattack Date: Mon, 6 Jan 2025 15:27:58 +0800 Subject: [PATCH 08/39] Fix proxy --- nico.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/nico.py b/nico.py index 0a077bb..c794ee4 100644 --- a/nico.py +++ b/nico.py @@ -66,20 +66,29 @@ def validate_cookie(cookies): self.session.headers.update(self.HEADERS) # proxy settings - if proxy is None or proxy.lower() == 'none': - proxy = None + if not proxy or proxy.lower() == 'none': + # it's recommended to set proxy to '' instead of None, otherwise + # some redirected requests may not actually use the proxy settings. + # see https://github.com/psf/requests/issues/6153 + + proxy = '' elif proxy == 'auto': - proxies = getproxies() - if proxy := proxies.get('http'): + sys_proxies = getproxies() + if proxy := sys_proxies.get('http'): print(f'INFO: Automatically use system proxy {proxy}') - # I don't think system proxy would be missing scheme, but just in case + # I don't think system proxy would be missing scheme ever, but just in case if proxy and '://' not in proxy: print('WARN: Proxy is missing scheme. Assuming http://') proxy = f'http://{proxy}' - + # setting self.session.proxies alone isn't enough; because requests will + # prioritize system proxy over session.proxies. + # you have to set proxy at request level to override system proxy. + # see https://github.com/psf/requests/issues/2018 + # so, we have to disable system proxy by setting trust_env to False first. + self.session.trust_env = False self.session.proxies = {'http': proxy, 'https': proxy} + # this is for websocket connection/minyami download self.proxy = proxy - self.save_dir = Path(save_dir) if save_dir else Path.cwd() def _parse_url_or_video_id(self, url_or_video_id): From a35e47fe7768dbbac24610d970ccf78cf885ff20 Mon Sep 17 00:00:00 2001 From: fireattack Date: Fri, 17 Jan 2025 11:22:52 +0800 Subject: [PATCH 09/39] util: fix instagram fiename pattern --- util.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util.py b/util.py index 8831b7e..febb98e 100644 --- a/util.py +++ b/util.py @@ -27,6 +27,10 @@ TWITTER_FILENAME_RE = re.compile(r'^(?P\w+)-(?P\d+)-(?P\d{8})_(?P