mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-08-02 06:09:36 +08:00
189 lines
4.5 KiB
Python
189 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright (c) 2026 KenanZhu.
|
|
All rights reserved.
|
|
|
|
This software is provided "as is", without any warranty of any kind.
|
|
You may use, modify, and distribute this file under the terms of the MIT License.
|
|
See the LICENSE file for details.
|
|
"""
|
|
from datetime import datetime
|
|
|
|
from PySide6.QtCore import (
|
|
QObject,
|
|
QTimer,
|
|
Signal,
|
|
Slot
|
|
)
|
|
|
|
from gui.ALBulletinWorker import ALBulletinFetchWorker
|
|
from managers.bulletin.BulletinManager import instance as bulletinInstance
|
|
|
|
|
|
class ALBulletinPoller(QObject):
|
|
"""
|
|
Background bulletin poller.
|
|
|
|
Owns the periodic poll timer and the ALBulletinFetchWorker
|
|
lifecycle. Emits signals when new bulletins are detected so
|
|
the owner can show tray notifications without knowing the
|
|
fetch / merge details.
|
|
"""
|
|
|
|
newBulletinsDetected = Signal(int)
|
|
|
|
def __init__(
|
|
self,
|
|
parent=None
|
|
):
|
|
|
|
super().__init__(parent)
|
|
self.__timer = QTimer(self)
|
|
self.__timer.timeout.connect(self.__poll)
|
|
self.__worker = None
|
|
self.__dialog_open = False
|
|
self.__stopped = False
|
|
self.__mgr = bulletinInstance()
|
|
|
|
def start(
|
|
self
|
|
):
|
|
|
|
self.__stopped = False
|
|
interval_ms = self.__mgr.syncInterval()*60*1000
|
|
self.__timer.start(interval_ms)
|
|
|
|
def stop(
|
|
self
|
|
):
|
|
|
|
self.__stopped = True
|
|
self.__timer.stop()
|
|
self.__cleanupWorker()
|
|
|
|
def restart(
|
|
self
|
|
):
|
|
|
|
self.stop()
|
|
self.start()
|
|
|
|
def fetchNow(
|
|
self
|
|
):
|
|
|
|
if self.__worker is not None:
|
|
return
|
|
if self.__dialog_open:
|
|
return
|
|
self.__doFetch()
|
|
|
|
def isPolling(
|
|
self
|
|
) -> bool:
|
|
|
|
return self.__timer.isActive()
|
|
|
|
def setDialogOpen(
|
|
self,
|
|
open: bool
|
|
):
|
|
|
|
self.__dialog_open = open
|
|
|
|
def __disconnectWorker(
|
|
self,
|
|
worker: ALBulletinFetchWorker
|
|
):
|
|
|
|
try:
|
|
worker.fetchWorkerIsFinished.disconnect(self.__onFetched)
|
|
except (TypeError, RuntimeError):
|
|
pass
|
|
try:
|
|
worker.fetchWorkerFinishedWithError.disconnect(self.__onError)
|
|
except (TypeError, RuntimeError):
|
|
pass
|
|
|
|
def __cleanupWorker(
|
|
self
|
|
):
|
|
|
|
if self.__worker is None:
|
|
return
|
|
self.__disconnectWorker(self.__worker)
|
|
self.__worker.wait(2000)
|
|
self.__worker.deleteLater()
|
|
self.__worker = None
|
|
|
|
def __doFetch(
|
|
self
|
|
):
|
|
|
|
params = self.__mgr.getSyncDateTimeAndRange()
|
|
self.__worker = ALBulletinFetchWorker(
|
|
self, self.__mgr.apiUrl(), params
|
|
)
|
|
self.__worker.fetchWorkerIsFinished.connect(self.__onFetched)
|
|
self.__worker.fetchWorkerFinishedWithError.connect(self.__onError)
|
|
self.__worker.start()
|
|
|
|
@Slot()
|
|
def __poll(
|
|
self
|
|
):
|
|
|
|
if self.__worker is not None:
|
|
return
|
|
if self.__dialog_open:
|
|
return
|
|
self.__doFetch()
|
|
|
|
@Slot(dict)
|
|
def __onFetched(
|
|
self,
|
|
data: dict
|
|
):
|
|
|
|
worker = self.sender()
|
|
if worker is not self.__worker:
|
|
return
|
|
self.__disconnectWorker(worker)
|
|
worker.wait(2000)
|
|
worker.deleteLater()
|
|
self.__worker = None
|
|
old_ids = {str(b.get("id", "")) for b in self.__mgr.bulletins()}
|
|
bulletins = data.get("bulletins", [])
|
|
delete_ids = data.get("delete_ids", [])
|
|
self.__mgr.updateAndMergeBulletins(bulletins, delete_ids)
|
|
self.__mgr.setLastSyncTime(datetime.now().astimezone().isoformat())
|
|
delete_id_set = {str(d) for d in delete_ids}
|
|
new_ids = {
|
|
str(b.get("id", ""))
|
|
for b in bulletins
|
|
if str(b.get("id", "")) and str(b.get("id", "")) not in old_ids
|
|
}
|
|
new_ids -= delete_id_set
|
|
if new_ids:
|
|
self.newBulletinsDetected.emit(len(new_ids))
|
|
if not self.__stopped:
|
|
interval_ms = self.__mgr.syncInterval()*60*1000
|
|
self.__timer.start(interval_ms)
|
|
|
|
@Slot(str)
|
|
def __onError(
|
|
self,
|
|
error_message: str
|
|
):
|
|
|
|
worker = self.sender()
|
|
if worker is not self.__worker:
|
|
return
|
|
self.__disconnectWorker(worker)
|
|
worker.wait(2000)
|
|
worker.deleteLater()
|
|
self.__worker = None
|
|
if not self.__stopped:
|
|
interval_ms = self.__mgr.syncInterval()*60*1000
|
|
self.__timer.start(interval_ms)
|