From 3b27c81166c7bae7167d3cbf97f65c3b56b97f8b Mon Sep 17 00:00:00 2001 From: taizan-hokuto <55448286+taizan-hokuto@users.noreply.github.com> Date: Wed, 8 Jan 2020 00:44:50 +0900 Subject: [PATCH] Add tests --- tests/test_compatible_processor.py | 2 +- tests/test_livechat_2.py | 125 +++++++ tests/test_parser.py | 2 +- tests/test_speed_calculator.py | 2 +- tests/testdata/finished_live.json | 113 ++++++- tests/testdata/test_stream.json | 509 +++++++++++++++++++++++++++++ 6 files changed, 749 insertions(+), 4 deletions(-) create mode 100644 tests/test_livechat_2.py create mode 100644 tests/testdata/test_stream.json diff --git a/tests/test_compatible_processor.py b/tests/test_compatible_processor.py index efc81b9..39cf9fe 100644 --- a/tests/test_compatible_processor.py +++ b/tests/test_compatible_processor.py @@ -12,7 +12,7 @@ from pytchat.processors.compatible.renderer.paidmessage import LiveChatPaidMessa from pytchat.processors.compatible.renderer.paidsticker import LiveChatPaidStickerRenderer from pytchat.processors.compatible.renderer.legacypaid import LiveChatLegacyPaidMessageRenderer -parser = Parser() +parser = Parser(is_replay=False) def test_textmessage(mocker): '''api互換processorのテスト:通常テキストメッセージ''' diff --git a/tests/test_livechat_2.py b/tests/test_livechat_2.py new file mode 100644 index 0000000..f582ae0 --- /dev/null +++ b/tests/test_livechat_2.py @@ -0,0 +1,125 @@ +import asyncio, aiohttp +import json +import pytest +import re +import requests +import sys +import time +from aioresponses import aioresponses +from concurrent.futures import CancelledError +from unittest import TestCase +from pytchat.core_multithread.livechat import LiveChat +from pytchat.core_async.livechat import LiveChatAsync +from pytchat.exceptions import ( + NoLivechatRendererException,NoYtinitialdataException, + ResponseContextError,NoContentsException) +from pytchat.parser.live import Parser +from pytchat.processors.dummy_processor import DummyProcessor + +def _open_file(path): + with open(path,mode ='r',encoding = 'utf-8') as f: + return f.read() + +@aioresponses() +def test_async_live_stream(*mock): + + async def test_loop(*mock): + pattern = re.compile(r'^https://www.youtube.com/live_chat/get_live_chat\?continuation=.*$') + _text = _open_file('tests/testdata/test_stream.json') + mock[0].get(pattern, status=200, body=_text) + chat = LiveChatAsync(video_id='', processor = DummyProcessor()) + chats = await chat.get() + rawdata = chats[0]["chatdata"] + #assert fetching livachat data + assert list(rawdata[0]["addChatItemAction"]["item"].keys())[0] == "liveChatTextMessageRenderer" + assert list(rawdata[1]["addChatItemAction"]["item"].keys())[0] == "liveChatTextMessageRenderer" + assert list(rawdata[2]["addChatItemAction"]["item"].keys())[0] == "liveChatPlaceholderItemRenderer" + assert list(rawdata[3]["addLiveChatTickerItemAction"]["item"].keys())[0] == "liveChatTickerPaidMessageItemRenderer" + assert list(rawdata[4]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidMessageRenderer" + assert list(rawdata[5]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidStickerRenderer" + assert list(rawdata[6]["addLiveChatTickerItemAction"]["item"].keys())[0] == "liveChatTickerSponsorItemRenderer" + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(test_loop(*mock)) + except CancelledError: + assert True + +@aioresponses() +def test_async_replay_stream(*mock): + + async def test_loop(*mock): + pattern_live = re.compile(r'^https://www.youtube.com/live_chat/get_live_chat\?continuation=.*$') + pattern_replay = re.compile(r'^https://www.youtube.com/live_chat_replay/get_live_chat_replay\?continuation=.*$') + #empty livechat -> switch to fetch replaychat + _text_live = _open_file('tests/testdata/finished_live.json') + _text_replay = _open_file('tests/testdata/chatreplay.json') + mock[0].get(pattern_live, status=200, body=_text_live) + mock[0].get(pattern_replay, status=200, body=_text_replay) + + chat = LiveChatAsync(video_id='', processor = DummyProcessor()) + chats = await chat.get() + rawdata = chats[0]["chatdata"] + #assert fetching replaychat data + assert list(rawdata[0]["addChatItemAction"]["item"].keys())[0] == "liveChatTextMessageRenderer" + assert list(rawdata[14]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidMessageRenderer" + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(test_loop(*mock)) + except CancelledError: + assert True + +@aioresponses() +def test_async_force_replay(*mock): + + async def test_loop(*mock): + pattern_live = re.compile(r'^https://www.youtube.com/live_chat/get_live_chat\?continuation=.*$') + pattern_replay = re.compile(r'^https://www.youtube.com/live_chat_replay/get_live_chat_replay\?continuation=.*$') + #valid live data, but force_replay = True + _text_live = _open_file('tests/testdata/test_stream.json') + #valid replay data + _text_replay = _open_file('tests/testdata/chatreplay.json') + + mock[0].get(pattern_live, status=200, body=_text_live) + mock[0].get(pattern_replay, status=200, body=_text_replay) + #force replay + chat = LiveChatAsync(video_id='', processor = DummyProcessor(), force_replay = True) + chats = await chat.get() + rawdata = chats[0]["chatdata"] + # assert fetching replaychat data + assert list(rawdata[14]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidMessageRenderer" + # assert not mix livechat data + assert list(rawdata[2]["addChatItemAction"]["item"].keys())[0] != "liveChatPlaceholderItemRenderer" + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(test_loop(*mock)) + except CancelledError: + assert True + +def test_multithread_live_stream(mocker): + + _text = _open_file('tests/testdata/test_stream.json') + responseMock = mocker.Mock() + responseMock.status_code = 200 + responseMock.text = _text + mocker.patch('requests.Session.get').return_value.__enter__.return_value = responseMock + + chat = LiveChat(video_id='test_id', processor = DummyProcessor()) + chats = chat.get() + rawdata = chats[0]["chatdata"] + #assert fetching livachat data + assert list(rawdata[0]["addChatItemAction"]["item"].keys())[0] == "liveChatTextMessageRenderer" + assert list(rawdata[1]["addChatItemAction"]["item"].keys())[0] == "liveChatTextMessageRenderer" + assert list(rawdata[2]["addChatItemAction"]["item"].keys())[0] == "liveChatPlaceholderItemRenderer" + assert list(rawdata[3]["addLiveChatTickerItemAction"]["item"].keys())[0] == "liveChatTickerPaidMessageItemRenderer" + assert list(rawdata[4]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidMessageRenderer" + assert list(rawdata[5]["addChatItemAction"]["item"].keys())[0] == "liveChatPaidStickerRenderer" + assert list(rawdata[6]["addLiveChatTickerItemAction"]["item"].keys())[0] == "liveChatTickerSponsorItemRenderer" + chat.terminate() + + + + + diff --git a/tests/test_parser.py b/tests/test_parser.py index b40bee8..9832f7a 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -11,7 +11,7 @@ from pytchat.exceptions import ( def _open_file(path): with open(path,mode ='r',encoding = 'utf-8') as f: return f.read() -parser = Parser() +parser = Parser(is_replay = False) @aioresponses() def test_finishedlive(*mock): diff --git a/tests/test_speed_calculator.py b/tests/test_speed_calculator.py index f137c52..96c6761 100644 --- a/tests/test_speed_calculator.py +++ b/tests/test_speed_calculator.py @@ -9,7 +9,7 @@ from pytchat.exceptions import ( from pytchat.processors.speed_calculator import SpeedCalculator -parser = Parser() +parser = Parser(is_replay =False) def test_speed_1(mocker): '''test speed calculation with normal json. diff --git a/tests/testdata/finished_live.json b/tests/testdata/finished_live.json index 0300acc..39a897a 100644 --- a/tests/testdata/finished_live.json +++ b/tests/testdata/finished_live.json @@ -1 +1,112 @@ -{"csn":"zeiIXfXHJYOA1d8Pyuaw4A4","response":{"responseContext":{"serviceTrackingParams":[{"service":"CSI","params":[{"key":"GetLiveChat_rid","value":"0x96761cd683987638"},{"key":"c","value":"WEB"},{"key":"cver","value":"2.20190920.05.01"},{"key":"yt_li","value":"0"}]},{"service":"GFEEDBACK","params":[{"key":"e","value":"23744176,23757412,23788838,23788875,23793834,23804281,23808952,23818920,23828084,23828243,23829335,23832543,23835014,23836965,23837741,23837772,23837957,23837993,23838272,23838302,23838823,23838823,23839284,23839362,23840216,23840243,23841118,23842662,23842986,23843283,23843289,23843534,23844042,24630096,9449243,9471235"},{"key":"logged_in","value":"0"}]},{"service":"GUIDED_HELP","params":[{"key":"logged_in","value":"0"}]},{"service":"ECATCHER","params":[{"key":"client.name","value":"WEB"},{"key":"client.version","value":"2.20190920"},{"key":"innertube.build.changelist","value":"270293990"},{"key":"innertube.build.experiments.source_version","value":"270377311"},{"key":"innertube.build.label","value":"youtube.ytfe.innertube_20190920_5_RC0"},{"key":"innertube.build.timestamp","value":"1568999515"},{"key":"innertube.build.variants.checksum","value":"669625af1d321c1e95dffac8db989afa"},{"key":"innertube.run.job","value":"ytfe-innertube-replica-only.ytfe"}]}],"webResponseContextExtensionData":{"ytConfigData":{"csn":"zeiIXfXHJYOA1d8Pyuaw4A4","visitorData":"CgtLWW1kYjAxZTBaRSjN0aPsBQ%3D%3D"}}}},"xsrf_token":"QUFFLUhqbnhXaGhpblNhWmEzdjJJR2JNeW02M01PQ0p6Z3xBQ3Jtc0ttekpfU1dhZlA4ZWJhSGNrOFN5ZGFFSmNSMjBWRERWYUtOSS03RG5sbDRaa01KWmZFd2pPZzNEdW10WThmUXRiQjRKQ1ZPUkd1b09nT0k5dEZJTGdFYWxEVGNOWkUzcGNEQjdTNnN2OTRjN1Qtc0haZlpSWGlxd1k4LUdnVEhVb1FtMW8yZHJfankzN1JhUFo3aFZvS0s4NkIzTGc=","url":"\/live_chat\/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D","endpoint":{"commandMetadata":{"webCommandMetadata":{"url":"/live_chat/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D"}},"urlEndpoint":{"url":"/live_chat/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D"}},"timing":{"info":{"st":64}}} \ No newline at end of file +{ + "csn": "zeiIXfXHJYOA1d8Pyuaw4A4", + "response": { + "responseContext": { + "serviceTrackingParams": [ + { + "service": "CSI", + "params": [ + { + "key": "GetLiveChat_rid", + "value": "0x96761cd683987638" + }, + { + "key": "c", + "value": "WEB" + }, + { + "key": "cver", + "value": "2.20190920.05.01" + }, + { + "key": "yt_li", + "value": "0" + } + ] + }, + { + "service": "GFEEDBACK", + "params": [ + { + "key": "e", + "value": "23744176,23757412,23788838,23788875,23793834,23804281,23808952,23818920,23828084,23828243,23829335,23832543,23835014,23836965,23837741,23837772,23837957,23837993,23838272,23838302,23838823,23838823,23839284,23839362,23840216,23840243,23841118,23842662,23842986,23843283,23843289,23843534,23844042,24630096,9449243,9471235" + }, + { + "key": "logged_in", + "value": "0" + } + ] + }, + { + "service": "GUIDED_HELP", + "params": [ + { + "key": "logged_in", + "value": "0" + } + ] + }, + { + "service": "ECATCHER", + "params": [ + { + "key": "client.name", + "value": "WEB" + }, + { + "key": "client.version", + "value": "2.20190920" + }, + { + "key": "innertube.build.changelist", + "value": "270293990" + }, + { + "key": "innertube.build.experiments.source_version", + "value": "270377311" + }, + { + "key": "innertube.build.label", + "value": "youtube.ytfe.innertube_20190920_5_RC0" + }, + { + "key": "innertube.build.timestamp", + "value": "1568999515" + }, + { + "key": "innertube.build.variants.checksum", + "value": "669625af1d321c1e95dffac8db989afa" + }, + { + "key": "innertube.run.job", + "value": "ytfe-innertube-replica-only.ytfe" + } + ] + } + ], + "webResponseContextExtensionData": { + "ytConfigData": { + "csn": "zeiIXfXHJYOA1d8Pyuaw4A4", + "visitorData": "CgtLWW1kYjAxZTBaRSjN0aPsBQ%3D%3D" + } + } + } + }, + "xsrf_token": "QUFFLUhqbnhXaGhpblNhWmEzdjJJR2JNeW02M01PQ0p6Z3xBQ3Jtc0ttekpfU1dhZlA4ZWJhSGNrOFN5ZGFFSmNSMjBWRERWYUtOSS03RG5sbDRaa01KWmZFd2pPZzNEdW10WThmUXRiQjRKQ1ZPUkd1b09nT0k5dEZJTGdFYWxEVGNOWkUzcGNEQjdTNnN2OTRjN1Qtc0haZlpSWGlxd1k4LUdnVEhVb1FtMW8yZHJfankzN1JhUFo3aFZvS0s4NkIzTGc=", + "url": "\/live_chat\/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D", + "endpoint": { + "commandMetadata": { + "webCommandMetadata": { + "url": "/live_chat/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D" + } + }, + "urlEndpoint": { + "url": "/live_chat/get_live_chat?continuation=0ofMyAORAhqsAUNqZ0tEUW9MWjAwdGEwMWFaMmRxY2xrcUp3b1lWVU53VGtneVdtc3laM2N6U2tKcVYwRkxVM2xhWTFGUkVndG5UUzFyVFZwbloycHlXUnBEcXJuQnZRRTlDanRvZEhSd2N6b3ZMM2QzZHk1NWIzVjBkV0psTG1OdmJTOXNhWFpsWDJOb1lYUV9kajFuVFMxclRWcG5aMnB5V1NacGMxOXdiM0J2ZFhROU1TQUMo5-aA_KPn5AIwADgAQAJKKwgAEAAYACAAKg5zdGF0aWNjaGVja3N1bToAQABKAggBUMKMlt2k5-QCWANQ5KzA_KPn5AJYt7rZo9Tm5AJoAYIBAggBiAEAoAHorZb_pOfkAg%253D%253D" + } + }, + "timing": { + "info": { + "st": 64 + } + } +} \ No newline at end of file diff --git a/tests/testdata/test_stream.json b/tests/testdata/test_stream.json new file mode 100644 index 0000000..46f85d6 --- /dev/null +++ b/tests/testdata/test_stream.json @@ -0,0 +1,509 @@ +{ + "response": { + "responseContext": { + "webResponseContextExtensionData": "" + }, + "continuationContents": { + "liveChatContinuation": { + "continuations": [ + { + "invalidationContinuationData": { + "invalidationId": { + "objectSource": 1000, + "objectId": "___objectId___", + "topic": "chat~00000000000~0000000", + "subscribeToGcmTopics": true, + "protoCreationTimestampMs": "1577804400000" + }, + "timeoutMs": 5000, + "continuation": "___continuation___" + } + } + ], + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "This is normal message." + } + ] + }, + "authorName": { + "simpleText": "author_name" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "id": "dummy_id", + "timestampUsec": 0, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + } + } + }, + "clientId": "dummy_client_id" + } + }, + { + "addChatItemAction": { + "item": { + "liveChatTextMessageRenderer": { + "message": { + "runs": [ + { + "text": "This is members's message" + } + ] + }, + "authorName": { + "simpleText": "author_name" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "id": "dummy_id", + "timestampUsec": 0, + "authorBadges": [ + { + "liveChatAuthorBadgeRenderer": { + "customThumbnail": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/X=s32-c-k" + }, + { + "url": "https://yt3.ggpht.com/X=s32-c-k" + } + ] + }, + "tooltip": "メンバー(2 か月)", + "accessibility": { + "accessibilityData": { + "label": "メンバー(2 か月)" + } + } + } + } + ], + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + } + } + }, + "clientId": "dummy_client_id" + } + }, + { + "addChatItemAction": { + "item": { + "liveChatPlaceholderItemRenderer": { + "id": "dummy_id", + "timestampUsec": 0 + } + }, + "clientId": "dummy_client_id" + } + }, + { + "addLiveChatTickerItemAction": { + "item": { + "liveChatTickerPaidMessageItemRenderer": { + "id": "dummy_id", + "amount": { + "simpleText": "¥10,000" + }, + "amountTextColor": 4294967295, + "startBackgroundColor": 4293271831, + "endBackgroundColor": 4291821568, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "durationSec": 3600, + "showItemEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "showLiveChatItemEndpoint": { + "renderer": { + "liveChatPaidMessageRenderer": { + "id": "dummy_id", + "timestampUsec": 0, + "authorName": { + "simpleText": "author_name" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "purchaseAmountText": { + "simpleText": "¥10,000" + }, + "message": { + "runs": [ + { + "text": "This is superchat message." + } + ] + }, + "headerBackgroundColor": 4291821568, + "headerTextColor": 4294967295, + "bodyBackgroundColor": 4293271831, + "bodyTextColor": 4294967295, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "authorNameTextColor": 3019898879, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "timestampColor": 2164260863, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + } + } + } + } + }, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "fullDurationSec": 3600 + } + }, + "durationSec": "3600" + } + }, + { + "addChatItemAction": { + "item": { + "liveChatPaidMessageRenderer": { + "id": "dummy_id", + "timestampUsec": 0, + "authorName": { + "simpleText": "author_name" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "purchaseAmountText": { + "simpleText": "¥10,800" + }, + "message": { + "runs": [ + { + "text": "This is superchat message." + } + ] + }, + "headerBackgroundColor": 4291821568, + "headerTextColor": 4294967295, + "bodyBackgroundColor": 4293271831, + "bodyTextColor": 4294967295, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "authorNameTextColor": 3019898879, + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "timestampColor": 2164260863, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + } + } + } + } + }, + { + "addChatItemAction": { + "item": { + "liveChatPaidStickerRenderer": { + "id": "dummy_id", + "contextMenuEndpoint": { + "clickTrackingParams": "___clickTrackingParams___", + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + }, + "timestampUsec": 0, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "authorName": { + "simpleText": "author_name" + }, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "sticker": { + "thumbnails": [ + { + "url": "//lh3.googleusercontent.com/param_s=s40-rp", + "width": 40, + "height": 40 + }, + { + "url": "//lh3.googleusercontent.com/param_s=s80-rp", + "width": 80, + "height": 80 + } + ], + "accessibility": { + "accessibilityData": { + "label": "___sticker_label___" + } + } + }, + "moneyChipBackgroundColor": 4280191205, + "moneyChipTextColor": 4294967295, + "purchaseAmountText": { + "simpleText": "¥150" + }, + "stickerDisplayWidth": 40, + "stickerDisplayHeight": 40, + "backgroundColor": 4279592384, + "authorNameTextColor": 3019898879, + "trackingParams": "___trackingParams___" + } + } + } + }, + { + "addLiveChatTickerItemAction": { + "item": { + "liveChatTickerSponsorItemRenderer": { + "id": "dummy_id", + "detailText": { + "runs": [ + { + "text": "メンバー" + } + ] + }, + "detailTextColor": 4294967295, + "startBackgroundColor": 4279213400, + "endBackgroundColor": 4278943811, + "sponsorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "durationSec": 300, + "showItemEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "showLiveChatItemEndpoint": { + "renderer": { + "liveChatMembershipItemRenderer": { + "id": "dummy_id", + "timestampUsec": 0, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "headerSubtext": { + "runs": [ + { + "text": "メンバーシップ" + }, + { + "text": " へようこそ!" + } + ] + }, + "authorName": { + "simpleText": "author_name" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 32, + "height": 32 + }, + { + "url": "https://yt3.ggpht.com/------------/AAAAAAAAAAA/AAAAAAAAAAA/xxxxxxxxxxxx/s32-x-x-xx-xx-xx-c0xffffff/photo.jpg", + "width": 64, + "height": 64 + } + ] + }, + "authorBadges": [ + { + "liveChatAuthorBadgeRenderer": { + "customThumbnail": { + "thumbnails": [ + { + "url": "https://yt3.ggpht.com/X=s32-c-k" + }, + { + "url": "https://yt3.ggpht.com/X=s32-c-k" + } + ] + }, + "tooltip": "新規メンバー", + "accessibility": { + "accessibilityData": { + "label": "新規メンバー" + } + } + } + } + ], + "contextMenuEndpoint": { + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "___params___" + } + }, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "コメントの操作" + } + } + } + } + } + }, + "authorExternalChannelId": "http://www.youtube.com/channel/author_channel_url", + "fullDurationSec": 300 + } + }, + "durationSec": "300" + } + } + ] + } + } + } +} \ No newline at end of file