Compare commits
1 commit
main
...
wip/modque
Author | SHA1 | Date | |
---|---|---|---|
6b57153d5e |
3 changed files with 179 additions and 0 deletions
1
src/ovtk_audiencekit/plugins/ModQueue/__init__.py
Normal file
1
src/ovtk_audiencekit/plugins/ModQueue/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .mod import ModPlugin as Plugin
|
103
src/ovtk_audiencekit/plugins/ModQueue/mod.py
Normal file
103
src/ovtk_audiencekit/plugins/ModQueue/mod.py
Normal 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
|
75
src/ovtk_audiencekit/plugins/ModQueue/templates/index.html
Normal file
75
src/ovtk_audiencekit/plugins/ModQueue/templates/index.html
Normal 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>
|
Loading…
Add table
Reference in a new issue