Compare commits
3 commits
main
...
plugin-bas
Author | SHA1 | Date | |
---|---|---|---|
|
220e5f8a25 | ||
|
65f4499bbd | ||
|
a6d1162665 |
9 changed files with 149 additions and 165 deletions
|
@ -1,79 +0,0 @@
|
||||||
import random
|
|
||||||
from enum import Enum, auto
|
|
||||||
|
|
||||||
from ovtk_audiencekit.chats import ChatProcess
|
|
||||||
from ovtk_audiencekit.events import Event, Message, SysMessage
|
|
||||||
from ovtk_audiencekit.events.Message import USER_TYPE
|
|
||||||
|
|
||||||
|
|
||||||
class STATES(Enum):
|
|
||||||
PAUSED = auto()
|
|
||||||
RUNNING = auto()
|
|
||||||
|
|
||||||
|
|
||||||
class StartStop(Event):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FakeChat(ChatProcess):
|
|
||||||
def __init__(self, *args, max_delay=10, max_messages_per_chunk=1, start_paused=True, max_monitization=None, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self._max_delay = max_delay
|
|
||||||
self._max_messages_per_chunk = max_messages_per_chunk
|
|
||||||
self._max_monitization = max_monitization
|
|
||||||
self.state = STATES.PAUSED if start_paused else STATES.RUNNING
|
|
||||||
|
|
||||||
def process_messages(self, event, next_state):
|
|
||||||
if isinstance(event, StartStop):
|
|
||||||
running = not self.state == STATES.RUNNING
|
|
||||||
text = 'Fake chat activated!' if running else 'Disabled fake chat'
|
|
||||||
|
|
||||||
sys_msg = SysMessage(self._name, text)
|
|
||||||
self.publish(sys_msg)
|
|
||||||
|
|
||||||
return STATES.RUNNING if running else STATES.PAUSED
|
|
||||||
|
|
||||||
def loop(self, next_state):
|
|
||||||
if self.state == STATES.PAUSED:
|
|
||||||
return None
|
|
||||||
|
|
||||||
while range(int(random.random() * (self._max_messages_per_chunk + 1))):
|
|
||||||
author_name, author_id, author_type = random.choice([
|
|
||||||
('Random user', '123123', USER_TYPE.PATRON),
|
|
||||||
('Some Guy', '723894', USER_TYPE.PATRON),
|
|
||||||
('xX_ButtSlayerMan1967_Xx', '324234', USER_TYPE.PATRON),
|
|
||||||
('My name is uncessisarily long why does yt allow this', '123786986', USER_TYPE.PATRON),
|
|
||||||
('Taco Bell official (i wish)', '8979823', USER_TYPE.PATRON),
|
|
||||||
('skeh', '1337', USER_TYPE.OWNER),
|
|
||||||
('rando_mod', '6969', USER_TYPE.MODERATOR),
|
|
||||||
])
|
|
||||||
text = random.choice([
|
|
||||||
'Some fake user saying some shid',
|
|
||||||
'Another fake message from a fake fan (lol)',
|
|
||||||
'Why play games when you could eat bean',
|
|
||||||
'pog more like log',
|
|
||||||
'playing the game :drake_dislike:\nspending hours getting the game to run well :drake_like:',
|
|
||||||
'now thats what i call epic',
|
|
||||||
'POG',
|
|
||||||
'cheese',
|
|
||||||
'oh yeah, thats one neat chat',
|
|
||||||
'lmao fake chat',
|
|
||||||
'nice chat you got there, be a shame if someone spammed it',
|
|
||||||
' i like m y whitespace ',
|
|
||||||
'no i \n\n\n like my\nwhite\nspace',
|
|
||||||
'this fake user is chatty and say a lot of various things, but its still a coherent sentance somehow',
|
|
||||||
'Thanks for coming to my ted talk. Tonight, I discuss what exactly it means to be your little pogchamp, and how "come here" is actually propoganda in disquise. I am very good at parties i swear, please come to my party p l ea se',
|
|
||||||
'USRE VERY EXCITE POGGGG POG POGGGGGGGGGGGGGGGGGGGGGGGG POGPOGPOGGGG',
|
|
||||||
'spaamamspmapmdpmaspmspsapmspmapsmpasmspmapmpasmspmapmspampsmpaspaspamapmspmapmspmapsmpamspamspmapsmpmaspmapmspamspmapsmpamspmpamspms',
|
|
||||||
])
|
|
||||||
if self._max_monitization and random.random() > 0.5:
|
|
||||||
amount = random.random() * self._max_monitization
|
|
||||||
monitization = (amount, amount)
|
|
||||||
else:
|
|
||||||
monitization = None
|
|
||||||
fake_message = Message(self._name, text,
|
|
||||||
author_name, author_id, author_type,
|
|
||||||
monitization=monitization)
|
|
||||||
self.publish(fake_message)
|
|
||||||
|
|
||||||
return random.random() * self._max_delay
|
|
|
@ -1 +0,0 @@
|
||||||
from .FakeChat import FakeChat as Process
|
|
|
@ -1 +0,0 @@
|
||||||
from .misskey import MisskeyProcess as Process
|
|
|
@ -1,80 +0,0 @@
|
||||||
import json
|
|
||||||
import random
|
|
||||||
import logging
|
|
||||||
from enum import Enum, auto
|
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from ovtk_audiencekit.chats import ChatProcess
|
|
||||||
from ovtk_audiencekit.utils import NonBlockingWebsocket
|
|
||||||
from ovtk_audiencekit.events.Message import Message, USER_TYPE
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class STATES(Enum):
|
|
||||||
CONNECTING = auto()
|
|
||||||
READING = auto()
|
|
||||||
|
|
||||||
|
|
||||||
class MisskeyProcess(ChatProcess):
|
|
||||||
def __init__(self, *args, instance=None, channel=None, token=None, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self._url = f'wss://{instance}/streaming'
|
|
||||||
if token:
|
|
||||||
self._url += f'?token={token}'
|
|
||||||
self.channelId = channel
|
|
||||||
|
|
||||||
self._subid = '%0x' % random.getrandbits(16 * 4)
|
|
||||||
self._state_machine = self.bind_to_states(STATES)
|
|
||||||
self.state = STATES.CONNECTING
|
|
||||||
|
|
||||||
def normalize_event(self, event):
|
|
||||||
user_name = event['user']['name'] or event['user']['username']
|
|
||||||
user_id = event['user']['id']
|
|
||||||
text = event.get('text', '')
|
|
||||||
attachments = [(file['type'], file['url']) for file in event.get('files', [])]
|
|
||||||
emojis = {emoji['name']: emoji['url'] for emoji in chain(event.get('emojis', []), event['user'].get('emojis', []))}
|
|
||||||
if text or attachments:
|
|
||||||
msg = Message(self._name, text or '',
|
|
||||||
user_name, user_id, USER_TYPE.USER,
|
|
||||||
id=event['id'], emotes=emojis or None,
|
|
||||||
attachments=attachments or None)
|
|
||||||
return msg
|
|
||||||
return None
|
|
||||||
|
|
||||||
def on_connecting(self, next_state):
|
|
||||||
self._ws = NonBlockingWebsocket(self._url)
|
|
||||||
self._ws.start()
|
|
||||||
payload = {
|
|
||||||
'type': 'connect',
|
|
||||||
'body': {
|
|
||||||
'channel': 'channel', # lol
|
|
||||||
'id': self._subid,
|
|
||||||
'params': {
|
|
||||||
'channelId': self.channelId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self._ws.send(json.dumps(payload))
|
|
||||||
return STATES.READING
|
|
||||||
|
|
||||||
def on_reading(self, next_state, timeout=0.1):
|
|
||||||
if self._ws.poll(timeout):
|
|
||||||
note_event = self._ws.recv()
|
|
||||||
try:
|
|
||||||
misskey_event = json.loads(note_event)
|
|
||||||
if misskey_event['body']['id'] == self._subid and misskey_event['body']['type'] == 'note':
|
|
||||||
note = misskey_event['body']['body'] # LOL
|
|
||||||
norm = None
|
|
||||||
try:
|
|
||||||
norm = self.normalize_event(note)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f'Failed to process note data: {note}')
|
|
||||||
if norm:
|
|
||||||
self.publish(norm)
|
|
||||||
except (KeyError, json.JSONDecodeError):
|
|
||||||
logger.error(f'Unknown data in websocket: {note_event}')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def loop(self, next_state):
|
|
||||||
return self._state_machine(self.state, next_state)
|
|
|
@ -5,17 +5,24 @@ import appdirs
|
||||||
from kdl import ParseConfig
|
from kdl import ParseConfig
|
||||||
|
|
||||||
def csv_parser(text, fragment):
|
def csv_parser(text, fragment):
|
||||||
text = fragment.fragment[1:-1]
|
data = fragment.fragment[1:-1]
|
||||||
return [field.strip() for field in text.split(',')]
|
return [field.strip() for field in data.split(',')]
|
||||||
|
|
||||||
def semisv_parser(text, fragment):
|
def semisv_parser(text, fragment):
|
||||||
text = fragment.fragment[1:-1]
|
data = fragment.fragment[1:-1]
|
||||||
return [field.strip() for field in text.split(';')]
|
return [field.strip() for field in data.split(';')]
|
||||||
|
|
||||||
|
class Secret(String):
|
||||||
|
pass
|
||||||
|
def secrets_parser(text, fragment):
|
||||||
|
name = fragment.fragment[1:-1]
|
||||||
|
return Secret(name)
|
||||||
|
|
||||||
customParsers = {
|
customParsers = {
|
||||||
'list': csv_parser,
|
'list': csv_parser,
|
||||||
'csv': csv_parser,
|
'csv': csv_parser,
|
||||||
'semisv': semisv_parser,
|
'semisv': semisv_parser,
|
||||||
|
'secret': secrets_parser,
|
||||||
}
|
}
|
||||||
|
|
||||||
kdl_parse_config = ParseConfig(valueConverters=customParsers)
|
kdl_parse_config = ParseConfig(valueConverters=customParsers)
|
||||||
|
|
60
ovtk_audiencekit/plugins/FakeChat/FakeChat.py
Normal file
60
ovtk_audiencekit/plugins/FakeChat/FakeChat.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import random
|
||||||
|
import asyncio
|
||||||
|
from enum import Enum, auto
|
||||||
|
|
||||||
|
from ovtk_audiencekit.plugins import PluginBase
|
||||||
|
from ovtk_audiencekit.events import Event, Message, SysMessage
|
||||||
|
from ovtk_audiencekit.events.Message import USER_TYPE
|
||||||
|
|
||||||
|
test_users = [
|
||||||
|
('Random user', '123123', USER_TYPE.USER),
|
||||||
|
('Some Guy', '723894', USER_TYPE.PATRON),
|
||||||
|
('xX_ButtSlayerMan1967_Xx', '324234', USER_TYPE.VIP),
|
||||||
|
('The hacker known as Anonymous', '1337', USER_TYPE.ANON),
|
||||||
|
('My name is uncessisarily long why does yt allow this', '123786986', USER_TYPE.USER),
|
||||||
|
('Taco Bell official (i wish)', '8979823', USER_TYPE.PATRON),
|
||||||
|
('skeh', '420', USER_TYPE.OWNER),
|
||||||
|
('chat maid', '6969', USER_TYPE.MODERATOR),
|
||||||
|
]
|
||||||
|
|
||||||
|
test_messages = [
|
||||||
|
('Another fake message from a fake fan (lol)', None),
|
||||||
|
('Why play games when you could eat bean', None),
|
||||||
|
('pog more like log', None),
|
||||||
|
('now thats what i call epic', None),
|
||||||
|
('POG', None),
|
||||||
|
('oh yeah, thats one neat chat', None),
|
||||||
|
('lmao fake chat', None),
|
||||||
|
(' i like m y whitespace ', None),
|
||||||
|
('no i \n\n\n like my\nwhite\nspace', None),
|
||||||
|
('Thanks for coming to my ted talk. Tonight, I discuss what exactly it means to be your little pogchamp, and how "come here" is actually propoganda in disquise. I am very good at parties i swear, please come to my party p l ea se', None),
|
||||||
|
('USRE VERY EXCITE POGGGG POG POGGGGGGGGGGGGGGGGGGGGGGGG POGPOGPOGGGG', None),
|
||||||
|
('spaamamspmapmdpmaspmspsapmspmapsmpasmspmapmpasmspmapmspampsmpaspaspamapmspmapmspmapsmpamspamspmapsmpmaspmapmspamspmapsmpamspmpamspms', None),
|
||||||
|
('poggy woggy freebie deeby', 0),
|
||||||
|
('Hey do you want a penny', 0.01),
|
||||||
|
('show feet', 10),
|
||||||
|
('whats up guys suspcicously wealthy furry here', 1_000),
|
||||||
|
]
|
||||||
|
|
||||||
|
class FakeChat(PluginBase):
|
||||||
|
def __init__(self, *args, max_delay=10, max_messages_per_chunk=1, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self._max_delay = max_delay
|
||||||
|
self._max_messages_per_chunk = max_messages_per_chunk
|
||||||
|
|
||||||
|
self._readtask = asyncio.get_event_loop().create_task(self.loop())
|
||||||
|
|
||||||
|
async def loop(self):
|
||||||
|
while True:
|
||||||
|
while range(int(random.random() * (self._max_messages_per_chunk + 1))):
|
||||||
|
author_name, author_id, author_type = random.choice(test_users)
|
||||||
|
text, monitization = random.choice(test_messages)
|
||||||
|
fake_message = Message(self._name, text,
|
||||||
|
author_name, author_id, author_type,
|
||||||
|
monitization=monitization)
|
||||||
|
self.send_to_bus(fake_message)
|
||||||
|
|
||||||
|
await asyncio.sleep(random.random() * self._max_delay)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
pass
|
1
ovtk_audiencekit/plugins/FakeChat/__init__.py
Normal file
1
ovtk_audiencekit/plugins/FakeChat/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .FakeChat import FakeChat as Plugin
|
1
ovtk_audiencekit/plugins/Misskey/__init__.py
Normal file
1
ovtk_audiencekit/plugins/Misskey/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .misskey import MisskeyChannel as Plugin
|
76
ovtk_audiencekit/plugins/Misskey/misskey.py
Normal file
76
ovtk_audiencekit/plugins/Misskey/misskey.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import asyncio
|
||||||
|
from enum import Enum, auto
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
import websockets
|
||||||
|
|
||||||
|
from ovtk_audiencekit.plugins import PluginBase
|
||||||
|
from ovtk_audiencekit.events.Message import Message, USER_TYPE
|
||||||
|
|
||||||
|
|
||||||
|
class MisskeyChannel(PluginBase):
|
||||||
|
def __init__(self, *args, instance=None, channel=None, token=None, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self._url = f'wss://{instance}/streaming'
|
||||||
|
if token:
|
||||||
|
self._url += f'?token={token}'
|
||||||
|
self.channelId = channel
|
||||||
|
self._subid = '%0x' % random.getrandbits(16 * 4)
|
||||||
|
|
||||||
|
self._readtask = asyncio.get_event_loop().create_task(self.read())
|
||||||
|
|
||||||
|
async def read(self):
|
||||||
|
async for ws in websockets.connect(self._url):
|
||||||
|
try:
|
||||||
|
await self.setup(ws)
|
||||||
|
while True:
|
||||||
|
note_event = await ws.recv()
|
||||||
|
try:
|
||||||
|
misskey_event = json.loads(note_event)
|
||||||
|
if misskey_event['body']['id'] == self._subid and misskey_event['body']['type'] == 'note':
|
||||||
|
note = misskey_event['body']['body'] # lol
|
||||||
|
norm = None
|
||||||
|
try:
|
||||||
|
norm = self.normalize_event(note)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f'Failed to process note data: {note}')
|
||||||
|
if norm:
|
||||||
|
self.send_to_bus(norm)
|
||||||
|
except (KeyError, json.JSONDecodeError):
|
||||||
|
self.logger.error(f'Unknown data in websocket: {note_event}')
|
||||||
|
except websockets.ConnectionClosed:
|
||||||
|
self.logger.error(f'Websocket disconnected! Retrying in a bit...')
|
||||||
|
continue
|
||||||
|
|
||||||
|
async def setup(self, ws):
|
||||||
|
payload = {
|
||||||
|
'type': 'connect',
|
||||||
|
'body': {
|
||||||
|
'channel': 'channel', # LOL
|
||||||
|
'id': self._subid,
|
||||||
|
'params': {
|
||||||
|
'channelId': self.channelId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ws.send(json.dumps(payload))
|
||||||
|
|
||||||
|
def normalize_event(self, event):
|
||||||
|
user_name = event['user']['name'] or event['user']['username']
|
||||||
|
user_id = event['user']['id']
|
||||||
|
text = event.get('text', '')
|
||||||
|
attachments = [(file['type'], file['url']) for file in event.get('files', [])]
|
||||||
|
emojis = {emoji['name']: emoji['url'] for emoji in chain(event.get('emojis', []), event['user'].get('emojis', []))}
|
||||||
|
if text or attachments:
|
||||||
|
msg = Message(self._name, text or '',
|
||||||
|
user_name, user_id, USER_TYPE.USER,
|
||||||
|
id=event['id'], emotes=emojis or None,
|
||||||
|
attachments=attachments or None)
|
||||||
|
return msg
|
||||||
|
return None
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
pass
|
Loading…
Add table
Reference in a new issue