feat(userbot,api,frontend): backfill stories and unbreak all-stories list
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
from collections.abc import AsyncIterator, Callable
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.errors import FloodPremiumWait, FloodWait, RPCError
|
||||
from pyrogram.types import Story
|
||||
|
||||
from userbot.modules.capture.context import CaptureContext
|
||||
from userbot.modules.jobs.context import JobContext
|
||||
from userbot.modules.jobs.registry import register
|
||||
from userbot.modules.stories.service import save_story
|
||||
|
||||
SAVE_EVERY = 10
|
||||
|
||||
StorySource = Callable[[], AsyncIterator[Story]]
|
||||
|
||||
|
||||
def _sources(client: Client, peer_id: int, *, own: bool) -> dict[str, StorySource]:
|
||||
sources: dict[str, StorySource] = {
|
||||
"active": lambda: client.get_chat_stories(peer_id),
|
||||
"pinned": lambda: client.get_pinned_stories(peer_id),
|
||||
}
|
||||
if own:
|
||||
sources["archived"] = lambda: client.get_archived_stories(peer_id)
|
||||
return sources
|
||||
|
||||
|
||||
async def _drain(
|
||||
ctx: JobContext, capture: CaptureContext, name: str, source: StorySource
|
||||
) -> int:
|
||||
client = ctx.client
|
||||
if client is None:
|
||||
return 0
|
||||
saved = 0
|
||||
async for story in source():
|
||||
try:
|
||||
await save_story(client, capture, story)
|
||||
except (FloodWait, FloodPremiumWait):
|
||||
raise
|
||||
except RPCError:
|
||||
continue
|
||||
saved += 1
|
||||
if saved % SAVE_EVERY == 0:
|
||||
await ctx.report_progress({"saved": saved, "source": name})
|
||||
if await ctx.is_canceled():
|
||||
break
|
||||
return saved
|
||||
|
||||
|
||||
@register("backfill_stories")
|
||||
async def backfill_stories(ctx: JobContext) -> None:
|
||||
client = ctx.client
|
||||
if client is None:
|
||||
return
|
||||
capture = getattr(client, "capture", None)
|
||||
if capture is None:
|
||||
return
|
||||
peer_id = ctx.job.params["peer_id"]
|
||||
own = client.me is not None and client.me.id == peer_id
|
||||
saved = 0
|
||||
errors: dict[str, str] = {}
|
||||
for name, source in _sources(client, peer_id, own=own).items():
|
||||
try:
|
||||
saved += await _drain(ctx, capture, name, source)
|
||||
except (FloodWait, FloodPremiumWait):
|
||||
raise
|
||||
except RPCError as exc:
|
||||
errors[name] = type(exc).__name__
|
||||
if await ctx.is_canceled():
|
||||
break
|
||||
await ctx.report_progress({"saved": saved, "done": True, "errors": errors})
|
||||
Reference in New Issue
Block a user