add balance
This commit is contained in:
@@ -116,21 +116,16 @@ class BackgroundTaskManager:
|
||||
Returns:
|
||||
Number of tasks cancelled
|
||||
"""
|
||||
cancelled = 0
|
||||
|
||||
async with self._lock:
|
||||
for task in list(self._tasks.values()):
|
||||
if not task.done():
|
||||
task.cancel()
|
||||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
cancelled += 1
|
||||
|
||||
running = [t for t in self._tasks.values() if not t.done()]
|
||||
for task in running:
|
||||
task.cancel()
|
||||
if running:
|
||||
await asyncio.gather(*running, return_exceptions=True)
|
||||
self._tasks.clear()
|
||||
self._task_info.clear()
|
||||
|
||||
|
||||
cancelled = len(running)
|
||||
logger.info(f"All tasks cancelled: {cancelled}")
|
||||
return cancelled
|
||||
|
||||
|
||||
+55
-2
@@ -44,6 +44,7 @@ class TaskStorage:
|
||||
"successful_visits": params.successful_visits,
|
||||
"links_found": params.links_found,
|
||||
"chat_id": params.chat_id,
|
||||
"user_id": params.user_id,
|
||||
"started_at": params.started_at.isoformat() if params.started_at else None,
|
||||
}
|
||||
|
||||
@@ -69,6 +70,7 @@ class TaskStorage:
|
||||
successful_visits=data.get("successful_visits", 0),
|
||||
links_found=data.get("links_found", 0),
|
||||
chat_id=data.get("chat_id"),
|
||||
user_id=data.get("user_id"),
|
||||
)
|
||||
if data.get("started_at"):
|
||||
try:
|
||||
@@ -84,8 +86,12 @@ class TaskStorage:
|
||||
def _load_sync(self) -> dict:
|
||||
if not self.file_path.exists():
|
||||
return {}
|
||||
with open(self.file_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
try:
|
||||
with open(self.file_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, IOError) as e:
|
||||
logger.warning(f"Failed to load tasks: {e}")
|
||||
return {}
|
||||
|
||||
async def save_tasks(self, tasks: Dict[str, TaskParams]) -> None:
|
||||
async with self._lock:
|
||||
@@ -165,3 +171,50 @@ class ChatStorage:
|
||||
if key in data and channel in data[key]:
|
||||
data[key].remove(channel)
|
||||
await asyncio.to_thread(self._save_sync, data)
|
||||
|
||||
|
||||
class BalanceStorage:
|
||||
"""Баланс переходов пользователей."""
|
||||
|
||||
def __init__(self, file_path: str = "data/balances.json"):
|
||||
self.file_path = Path(file_path)
|
||||
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
def _load_sync(self) -> dict:
|
||||
if not self.file_path.exists():
|
||||
return {}
|
||||
try:
|
||||
with open(self.file_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, IOError) as e:
|
||||
logger.warning(f"Failed to load balances: {e}")
|
||||
return {}
|
||||
|
||||
def _save_sync(self, data: dict) -> None:
|
||||
with open(self.file_path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
async def get_balance(self, user_id: int) -> int:
|
||||
async with self._lock:
|
||||
data = await asyncio.to_thread(self._load_sync)
|
||||
return data.get(str(user_id), 0)
|
||||
|
||||
async def add_balance(self, user_id: int, amount: int) -> int:
|
||||
async with self._lock:
|
||||
data = await asyncio.to_thread(self._load_sync)
|
||||
data[str(user_id)] = data.get(str(user_id), 0) + amount
|
||||
await asyncio.to_thread(self._save_sync, data)
|
||||
return data[str(user_id)]
|
||||
|
||||
async def deduct(self, user_id: int, amount: int = 1) -> int:
|
||||
async with self._lock:
|
||||
data = await asyncio.to_thread(self._load_sync)
|
||||
new_bal = max(0, data.get(str(user_id), 0) - amount)
|
||||
data[str(user_id)] = new_bal
|
||||
await asyncio.to_thread(self._save_sync, data)
|
||||
return new_bal
|
||||
|
||||
async def get_all(self) -> dict:
|
||||
async with self._lock:
|
||||
return await asyncio.to_thread(self._load_sync)
|
||||
|
||||
@@ -48,7 +48,8 @@ class TaskParams:
|
||||
successful_visits: int = 0
|
||||
links_found: int = 0
|
||||
chat_id: Optional[int] = None
|
||||
|
||||
user_id: Optional[int] = None # Telegram user_id, если задача создана пользователем
|
||||
|
||||
completed: bool = False # Задача завершена
|
||||
stopped: bool = False # Задача остановлена пользователем
|
||||
|
||||
@@ -241,15 +242,22 @@ class TaskManager:
|
||||
|
||||
async def get_stats(self) -> dict:
|
||||
"""Общая статистика."""
|
||||
twitch_tasks = await self.get_twitch_tasks()
|
||||
visit_tasks = await self.get_visit_tasks()
|
||||
|
||||
twitch = visit = paused = active = 0
|
||||
for p in self._tasks.values():
|
||||
if p.task_type == "twitch_irc":
|
||||
twitch += 1
|
||||
elif p.task_type == "visit":
|
||||
visit += 1
|
||||
if p.paused:
|
||||
paused += 1
|
||||
else:
|
||||
active += 1
|
||||
return {
|
||||
"total": len(self._tasks),
|
||||
"twitch": len(twitch_tasks),
|
||||
"visit": len(visit_tasks),
|
||||
"paused": sum(1 for p in self._tasks.values() if p.paused),
|
||||
"active": sum(1 for p in self._tasks.values() if not p.paused),
|
||||
"twitch": twitch,
|
||||
"visit": visit,
|
||||
"paused": paused,
|
||||
"active": active,
|
||||
}
|
||||
|
||||
def _get_task_info(self, task_id: str, params: TaskParams) -> str:
|
||||
|
||||
Reference in New Issue
Block a user