diff --git a/app/DataStore.py b/app/DataStore.py index c3089da5..a92b3fdf 100644 --- a/app/DataStore.py +++ b/app/DataStore.py @@ -59,6 +59,9 @@ class DataStore: raise KeyError(f'{key=} or {url=} not found.') + def getById(self, id: str) -> Download | None: + return self.dict[id] if id in self.dict else None + def items(self) -> list[tuple[str, Download]]: return self.dict.items() diff --git a/app/main.py b/app/main.py index 8866dbf0..a42cb92f 100644 --- a/app/main.py +++ b/app/main.py @@ -97,11 +97,8 @@ class Main: self.connection.row_factory = sqlite3.Row self.connection.execute('PRAGMA journal_mode=wal') - self.queue = DownloadQueue( - notifier=Notifier(sio=self.sio, serializer=self.serializer, webhooks=self.webhooks), - connection=self.connection, - serializer=self.serializer, - ) + self.notifier = Notifier(sio=self.sio, serializer=self.serializer, webhooks=self.webhooks) + self.queue = DownloadQueue(notifier=self.notifier, connection=self.connection, serializer=self.serializer) self.app.on_startup.append(lambda _: self.queue.initialize()) self.addRoutes() @@ -297,6 +294,43 @@ class Main: return web.Response(text=self.serializer.encode(status)) + @self.routes.post(self.config.url_prefix + 'item/{id}') + async def update_item(request: Request) -> Response: + id: str = request.match_info.get('id') + if not id: + raise web.HTTPBadRequest(reason='id is required.') + + item = self.queue.done.getById(id) + if not item: + raise web.HTTPNotFound(reason='Item not found.') + + try: + post = await request.json() + if not post: + raise web.HTTPBadRequest(reason='no data provided.') + except Exception as e: + raise web.HTTPBadRequest(reason=str(e)) + + updated = False + + for k, v in post.items(): + if not hasattr(item.info, k): + continue + + if getattr(item.info, k) == v: + continue + + updated = True + setattr(item.info, k, v) + LOG.info(f'Updated [{k}] to [{v}] for [{item.info.id}]') + + status = 200 if updated else 304 + if updated: + self.queue.done.put(item) + await self.notifier.emit('update', item.info) + + return web.Response(text=self.serializer.encode(item.info), status=status) + @self.routes.get(self.config.url_prefix + 'history') async def history(_) -> Response: history = {'done': [], 'queue': []} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index e375391f..cf1b2d52 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -113,6 +113,15 @@ onMounted(() => { data.deleting = dl?.deleting; downloading[data._id] = data; }); + + socket.on("update", stream => { + const data = JSON.parse(stream); + if (false === (data._id in completed)) { + return; + } + completed[data._id] = data; + }); + }); const deleteItem = (type, item) => {