Merge branch 'hotfix/membership_renderer'
This commit is contained in:
@@ -4,10 +4,12 @@ from .renderer.textmessage import LiveChatTextMessageRenderer
|
|||||||
from .renderer.paidmessage import LiveChatPaidMessageRenderer
|
from .renderer.paidmessage import LiveChatPaidMessageRenderer
|
||||||
from .renderer.paidsticker import LiveChatPaidStickerRenderer
|
from .renderer.paidsticker import LiveChatPaidStickerRenderer
|
||||||
from .renderer.legacypaid import LiveChatLegacyPaidMessageRenderer
|
from .renderer.legacypaid import LiveChatLegacyPaidMessageRenderer
|
||||||
|
from .renderer.membership import LiveChatMembershipItemRenderer
|
||||||
from .. chat_processor import ChatProcessor
|
from .. chat_processor import ChatProcessor
|
||||||
from ... import config
|
from ... import config
|
||||||
logger = config.logger(__name__)
|
logger = config.logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CompatibleProcessor(ChatProcessor):
|
class CompatibleProcessor(ChatProcessor):
|
||||||
|
|
||||||
def process(self, chat_components: list):
|
def process(self, chat_components: list):
|
||||||
@@ -24,11 +26,15 @@ class CompatibleProcessor(ChatProcessor):
|
|||||||
timeout += chat_component.get('timeout', 0)
|
timeout += chat_component.get('timeout', 0)
|
||||||
chatdata = chat_component.get('chatdata')
|
chatdata = chat_component.get('chatdata')
|
||||||
|
|
||||||
if chatdata is None: break
|
if chatdata is None:
|
||||||
|
break
|
||||||
for action in chatdata:
|
for action in chatdata:
|
||||||
if action is None: continue
|
if action is None:
|
||||||
if action.get('addChatItemAction') is None: continue
|
continue
|
||||||
if action['addChatItemAction'].get('item') is None: continue
|
if action.get('addChatItemAction') is None:
|
||||||
|
continue
|
||||||
|
if action['addChatItemAction'].get('item') is None:
|
||||||
|
continue
|
||||||
|
|
||||||
chat = self.parse(action)
|
chat = self.parse(action)
|
||||||
if chat:
|
if chat:
|
||||||
@@ -47,7 +53,8 @@ class CompatibleProcessor(ChatProcessor):
|
|||||||
action = sitem.get("addChatItemAction")
|
action = sitem.get("addChatItemAction")
|
||||||
if action:
|
if action:
|
||||||
item = action.get("item")
|
item = action.get("item")
|
||||||
if item is None: return None
|
if item is None:
|
||||||
|
return None
|
||||||
rd = {}
|
rd = {}
|
||||||
try:
|
try:
|
||||||
renderer = self.get_renderer(item)
|
renderer = self.get_renderer(item)
|
||||||
@@ -75,7 +82,8 @@ class CompatibleProcessor(ChatProcessor):
|
|||||||
renderer = LiveChatPaidStickerRenderer(item)
|
renderer = LiveChatPaidStickerRenderer(item)
|
||||||
elif item.get("liveChatLegacyPaidMessageRenderer"):
|
elif item.get("liveChatLegacyPaidMessageRenderer"):
|
||||||
renderer = LiveChatLegacyPaidMessageRenderer(item)
|
renderer = LiveChatLegacyPaidMessageRenderer(item)
|
||||||
|
elif item.get("liveChatMembershipItemRenderer"):
|
||||||
|
renderer = LiveChatMembershipItemRenderer(item)
|
||||||
else:
|
else:
|
||||||
renderer = None
|
renderer = None
|
||||||
return renderer
|
return renderer
|
||||||
|
|
||||||
|
|||||||
40
pytchat/processors/compatible/renderer/membership.py
Normal file
40
pytchat/processors/compatible/renderer/membership.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from .base import BaseRenderer
|
||||||
|
|
||||||
|
|
||||||
|
class LiveChatMembershipItemRenderer(BaseRenderer):
|
||||||
|
def __init__(self, item):
|
||||||
|
super().__init__(item, "newSponsorEvent")
|
||||||
|
|
||||||
|
def get_snippet(self):
|
||||||
|
message = self.get_message(self.renderer)
|
||||||
|
return {
|
||||||
|
"type": self.chattype,
|
||||||
|
"liveChatId": "",
|
||||||
|
"authorChannelId": self.renderer.get("authorExternalChannelId"),
|
||||||
|
"publishedAt": self.get_publishedat(self.renderer.get("timestampUsec", 0)),
|
||||||
|
"hasDisplayContent": True,
|
||||||
|
"displayMessage": message,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_authordetails(self):
|
||||||
|
authorExternalChannelId = self.renderer.get("authorExternalChannelId")
|
||||||
|
# parse subscriber type
|
||||||
|
isVerified, isChatOwner, _, isChatModerator = (
|
||||||
|
self.get_badges(self.renderer)
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"channelId": authorExternalChannelId,
|
||||||
|
"channelUrl": "http://www.youtube.com/channel/"+authorExternalChannelId,
|
||||||
|
"displayName": self.renderer["authorName"]["simpleText"],
|
||||||
|
"profileImageUrl": self.renderer["authorPhoto"]["thumbnails"][1]["url"],
|
||||||
|
"isVerified": isVerified,
|
||||||
|
"isChatOwner": isChatOwner,
|
||||||
|
"isChatSponsor": True,
|
||||||
|
"isChatModerator": isChatModerator
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_message(self, renderer):
|
||||||
|
message = (renderer["headerSubtext"]["runs"][0]["text"]
|
||||||
|
)+' / '+(renderer["authorName"]["simpleText"])
|
||||||
|
return message
|
||||||
@@ -4,10 +4,13 @@ from .renderer.textmessage import LiveChatTextMessageRenderer
|
|||||||
from .renderer.paidmessage import LiveChatPaidMessageRenderer
|
from .renderer.paidmessage import LiveChatPaidMessageRenderer
|
||||||
from .renderer.paidsticker import LiveChatPaidStickerRenderer
|
from .renderer.paidsticker import LiveChatPaidStickerRenderer
|
||||||
from .renderer.legacypaid import LiveChatLegacyPaidMessageRenderer
|
from .renderer.legacypaid import LiveChatLegacyPaidMessageRenderer
|
||||||
|
from .renderer.membership import LiveChatMembershipItemRenderer
|
||||||
from .. chat_processor import ChatProcessor
|
from .. chat_processor import ChatProcessor
|
||||||
from ... import config
|
from ... import config
|
||||||
|
|
||||||
logger = config.logger(__name__)
|
logger = config.logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Chatdata:
|
class Chatdata:
|
||||||
def __init__(self, chatlist: list, timeout: float):
|
def __init__(self, chatlist: list, timeout: float):
|
||||||
self.items = chatlist
|
self.items = chatlist
|
||||||
@@ -25,6 +28,7 @@ class Chatdata:
|
|||||||
return
|
return
|
||||||
await asyncio.sleep(self.interval/len(self.items))
|
await asyncio.sleep(self.interval/len(self.items))
|
||||||
|
|
||||||
|
|
||||||
class DefaultProcessor(ChatProcessor):
|
class DefaultProcessor(ChatProcessor):
|
||||||
def process(self, chat_components: list):
|
def process(self, chat_components: list):
|
||||||
|
|
||||||
@@ -35,24 +39,27 @@ class DefaultProcessor(ChatProcessor):
|
|||||||
for component in chat_components:
|
for component in chat_components:
|
||||||
timeout += component.get('timeout', 0)
|
timeout += component.get('timeout', 0)
|
||||||
chatdata = component.get('chatdata')
|
chatdata = component.get('chatdata')
|
||||||
if chatdata is None: continue
|
if chatdata is None:
|
||||||
|
continue
|
||||||
for action in chatdata:
|
for action in chatdata:
|
||||||
if action is None: continue
|
if action is None:
|
||||||
if action.get('addChatItemAction') is None: continue
|
continue
|
||||||
if action['addChatItemAction'].get('item') is None: continue
|
if action.get('addChatItemAction') is None:
|
||||||
|
continue
|
||||||
|
if action['addChatItemAction'].get('item') is None:
|
||||||
|
continue
|
||||||
|
|
||||||
chat = self._parse(action)
|
chat = self._parse(action)
|
||||||
if chat:
|
if chat:
|
||||||
chatlist.append(chat)
|
chatlist.append(chat)
|
||||||
return Chatdata(chatlist, float(timeout))
|
return Chatdata(chatlist, float(timeout))
|
||||||
|
|
||||||
|
|
||||||
def _parse(self, sitem):
|
def _parse(self, sitem):
|
||||||
|
|
||||||
action = sitem.get("addChatItemAction")
|
action = sitem.get("addChatItemAction")
|
||||||
if action:
|
if action:
|
||||||
item = action.get("item")
|
item = action.get("item")
|
||||||
if item is None: return None
|
if item is None:
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
renderer = self._get_renderer(item)
|
renderer = self._get_renderer(item)
|
||||||
if renderer == None:
|
if renderer == None:
|
||||||
@@ -74,6 +81,8 @@ class DefaultProcessor(ChatProcessor):
|
|||||||
renderer = LiveChatPaidStickerRenderer(item)
|
renderer = LiveChatPaidStickerRenderer(item)
|
||||||
elif item.get("liveChatLegacyPaidMessageRenderer"):
|
elif item.get("liveChatLegacyPaidMessageRenderer"):
|
||||||
renderer = LiveChatLegacyPaidMessageRenderer(item)
|
renderer = LiveChatLegacyPaidMessageRenderer(item)
|
||||||
|
elif item.get("liveChatMembershipItemRenderer"):
|
||||||
|
renderer = LiveChatMembershipItemRenderer(item)
|
||||||
else:
|
else:
|
||||||
renderer = None
|
renderer = None
|
||||||
return renderer
|
return renderer
|
||||||
15
pytchat/processors/default/renderer/membership.py
Normal file
15
pytchat/processors/default/renderer/membership.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from .base import BaseRenderer
|
||||||
|
|
||||||
|
|
||||||
|
class LiveChatMembershipItemRenderer(BaseRenderer):
|
||||||
|
def __init__(self, item):
|
||||||
|
super().__init__(item, "newSponsor")
|
||||||
|
|
||||||
|
def get_authordetails(self):
|
||||||
|
super().get_authordetails()
|
||||||
|
self.author.isChatSponsor = True
|
||||||
|
|
||||||
|
def get_message(self, renderer):
|
||||||
|
message = (renderer["headerSubtext"]["runs"][0]["text"]
|
||||||
|
)+' / '+(renderer["authorName"]["simpleText"])
|
||||||
|
return message
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import pytest
|
import pytest
|
||||||
import asyncio,aiohttp
|
import asyncio
|
||||||
|
import aiohttp
|
||||||
from pytchat.parser.live import Parser
|
from pytchat.parser.live import Parser
|
||||||
from pytchat.processors.compatible.processor import CompatibleProcessor
|
from pytchat.processors.compatible.processor import CompatibleProcessor
|
||||||
from pytchat.exceptions import (
|
from pytchat.exceptions import (
|
||||||
@@ -14,6 +15,7 @@ from pytchat.processors.compatible.renderer.legacypaid import LiveChatLegacyPaid
|
|||||||
|
|
||||||
parser = Parser(is_replay=False)
|
parser = Parser(is_replay=False)
|
||||||
|
|
||||||
|
|
||||||
def test_textmessage(mocker):
|
def test_textmessage(mocker):
|
||||||
'''api互換processorのテスト:通常テキストメッセージ'''
|
'''api互換processorのテスト:通常テキストメッセージ'''
|
||||||
processor = CompatibleProcessor()
|
processor = CompatibleProcessor()
|
||||||
@@ -51,6 +53,7 @@ def test_textmessage(mocker):
|
|||||||
assert "LCC." in ret["items"][0]["id"]
|
assert "LCC." in ret["items"][0]["id"]
|
||||||
assert ret["items"][0]["snippet"]["type"] == "textMessageEvent"
|
assert ret["items"][0]["snippet"]["type"] == "textMessageEvent"
|
||||||
|
|
||||||
|
|
||||||
def test_newsponcer(mocker):
|
def test_newsponcer(mocker):
|
||||||
'''api互換processorのテスト:メンバ新規登録'''
|
'''api互換processorのテスト:メンバ新規登録'''
|
||||||
processor = CompatibleProcessor()
|
processor = CompatibleProcessor()
|
||||||
@@ -87,6 +90,42 @@ def test_newsponcer(mocker):
|
|||||||
assert ret["items"][0]["snippet"]["type"] == "newSponsorEvent"
|
assert ret["items"][0]["snippet"]["type"] == "newSponsorEvent"
|
||||||
|
|
||||||
|
|
||||||
|
def test_newsponcer_rev(mocker):
|
||||||
|
'''api互換processorのテスト:メンバ新規登録'''
|
||||||
|
processor = CompatibleProcessor()
|
||||||
|
|
||||||
|
_json = _open_file("tests/testdata/compatible/newSponsor_rev.json")
|
||||||
|
|
||||||
|
_, chatdata = parser.parse(parser.get_contents(json.loads(_json)))
|
||||||
|
data = {
|
||||||
|
"video_id": "",
|
||||||
|
"timeout": 7,
|
||||||
|
"chatdata": chatdata
|
||||||
|
}
|
||||||
|
ret = processor.process([data])
|
||||||
|
|
||||||
|
assert ret["kind"] == "youtube#liveChatMessageListResponse"
|
||||||
|
assert ret["pollingIntervalMillis"] == data["timeout"]*1000
|
||||||
|
assert ret.keys() == {
|
||||||
|
"kind", "etag", "pageInfo", "nextPageToken", "pollingIntervalMillis", "items"
|
||||||
|
}
|
||||||
|
assert ret["pageInfo"].keys() == {
|
||||||
|
"totalResults", "resultsPerPage"
|
||||||
|
}
|
||||||
|
assert ret["items"][0].keys() == {
|
||||||
|
"kind", "etag", "id", "snippet", "authorDetails"
|
||||||
|
}
|
||||||
|
assert ret["items"][0]["snippet"].keys() == {
|
||||||
|
'type', 'liveChatId', 'authorChannelId', 'publishedAt', 'hasDisplayContent', 'displayMessage'
|
||||||
|
|
||||||
|
}
|
||||||
|
assert ret["items"][0]["authorDetails"].keys() == {
|
||||||
|
'channelId', 'channelUrl', 'displayName', 'profileImageUrl', 'isVerified', 'isChatOwner', 'isChatSponsor', 'isChatModerator'
|
||||||
|
}
|
||||||
|
assert "LCC." in ret["items"][0]["id"]
|
||||||
|
assert ret["items"][0]["snippet"]["type"] == "newSponsorEvent"
|
||||||
|
|
||||||
|
|
||||||
def test_superchat(mocker):
|
def test_superchat(mocker):
|
||||||
'''api互換processorのテスト:スパチャ'''
|
'''api互換processorのテスト:スパチャ'''
|
||||||
processor = CompatibleProcessor()
|
processor = CompatibleProcessor()
|
||||||
@@ -124,6 +163,7 @@ def test_superchat(mocker):
|
|||||||
assert "LCC." in ret["items"][0]["id"]
|
assert "LCC." in ret["items"][0]["id"]
|
||||||
assert ret["items"][0]["snippet"]["type"] == "superChatEvent"
|
assert ret["items"][0]["snippet"]["type"] == "superChatEvent"
|
||||||
|
|
||||||
|
|
||||||
def test_unregistered_currency(mocker):
|
def test_unregistered_currency(mocker):
|
||||||
processor = CompatibleProcessor()
|
processor = CompatibleProcessor()
|
||||||
|
|
||||||
|
|||||||
1823
tests/testdata/compatible/newSponsor_rev.json
vendored
Normal file
1823
tests/testdata/compatible/newSponsor_rev.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user