Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
6b57153d5e wip 2025-03-02 18:23:37 -05:00
3 changed files with 179 additions and 0 deletions

View file

@ -0,0 +1 @@
from .mod import ModPlugin as Plugin

View file

@ -0,0 +1,103 @@
from dataclasses import dataclass, field, asdict
from enum import Enum
import asyncio
from typing import Callable
import quart
import json
import random
import kdl
from ovtk_audiencekit.core import PluginBase
from ovtk_audiencekit.utils import format_exception
from ovtk_audiencekit.events.Message import SysMessage
class Judgement(Enum):
cringe = 0
based = 1
@dataclass
class Item:
id: int = field(init=False)
links: list[str]
files: list[str]
kdl: list[str]
ctx: dict
user: str = None
judgement: Judgement = None
def __post_init__(self):
self.id = random.getrandbits(32)
def describe(self):
return asdict(self)
class ModPlugin(PluginBase):
def setup(self):
self.requests = {}
self._queue_change_ev = asyncio.Event()
self.blueprint.add_url_rule('/', 'ctrlpanel', self.ui_ctrlpanel)
self.blueprint.add_url_rule('/<id>/<is_based>', 'api-review', self.ui_review)
self.blueprint.add_url_rule('/monitor', 'monitor', self.ui_monitor_ws, is_websocket=True)
async def run(self):
pass
async def send(self, _children=None, _ctx={}):
user = None
if source_ev := _ctx.get('event'):
if 'user_name' in source_ev.__dict__:
user = source_ev.user_name
item = Item(_children, _ctx, user)
self.requests[item.id] = item
self._queue_change_ev.set()
async def review(self, selector, judgement, _ctx={}):
if selector == 'last':
item_id = self.requests.keys()[-1]
item = self.requests[item_id]
else:
item = self.requests.get(selector)
if item is None:
if source := _ctx.get('event'):
msg = SysMessage(self._name, f"No item found", replies_to=source)
self.chats[source.via].send(msg)
return
item.judgement = Judgement(int(is_based))
self._queue_change_ev.set()
async def _runner_loop(self):
while True:
await self._queue_change_ev.wait()
for id, item in requests.items():
if item.judgement is not None:
await self.execute_kdl(item.kdl, _ctx=item.ctx)
async def ui_ctrlpanel(self):
groups = self._ui_get_state()
return await self.blueprint.render('index.html', init_state=json.dumps(groups))
async def ui_review(self, id=None):
data = await request.get_data()
self.judge(id, is_based)
return quart.Response(status=200)
async def ui_monitor_ws(self):
await quart.websocket.accept()
while True:
groups = self._ui_get_state()
await quart.websocket.send(json.dumps(groups))
await self._queue_change_ev.wait()
def _ui_get_state(self):
response = []
for id, item in self.requests.items():
if item.judgement is not None:
response.append((id, item.describe()))
return response

View file

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Moderatuin qyeye</title>
<script type="importmap">
{
"imports": { "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js" }
}
</script>
<script id="initial_state" type='text/kdl'>
<< init_state|safe >>
</script>
<script type="module">
import { createApp, ref, onMounted } from 'vue'
createApp({
setup() {
const scriptEl = document.getElementById("initial_state");
const groups = ref(JSON.parse(scriptEl.innerHTML));
onMounted(() => {
const websock = new WebSocket('<<url_for(".monitor")>>');
websock.addEventListener('message', (msg) => {
groups.value = JSON.parse(msg.data);
})
})
return { groups }
},
}).mount('#app')
</script>
</head>
<body id="root">
<div id="app">
<div v-for="(id, data) in groups" class="group">
<h3>{{ id }}</h3>
<p>{{ data }}</p>
</div>
</div>
<style type="text/css">
#app {
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-family: sans-serif;
gap: 8px;
}
p {
text-align: center;
}
h3 {
margin-right: 1em;
}
.group {
display: flex;
flex-direction: column;
gap: 4px;
}
.scene {
padding: 12px 24px;
user-select: none;
background-color: lightgray;
flex: 1;
}
.scene.pending {
background-color: lightgoldenrodyellow;
}
.scene.active {
background-color: lightgreen;
}
</style>
</body>
</html>