Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4945c7cbd3 | ||
|
|
9e672623ac |
No files matched your search
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
A read-only Telegram client that keeps everything. A userbot on your own account logs every incoming message into Postgres, including the ones later deleted or edited, along with media, reactions, presence and stories. A web client reads that archive back, and an MCP server hands it to agents.
|
A read-only Telegram client that keeps everything. A userbot on your own account logs every incoming message into Postgres, including the ones later deleted or edited, along with media, reactions, presence and stories. A web client reads that archive back, and an MCP server hands it to agents.
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
Useful on its own: a Telegram where nothing disappears. In the [beaver](https://git.kotikot.com/beaver) setup it is one of the agent's hands - the dispatcher reads chat history by the `chat_id` stored in a person's card.
|
Useful on its own: a Telegram where nothing disappears. In the [beaver](https://git.kotikot.com/beaver) setup it is one of the agent's hands - the dispatcher reads chat history by the `chat_id` stored in a person's card.
|
||||||
|
|
||||||
## What it keeps
|
## What it keeps
|
||||||
@@ -32,7 +31,8 @@ Read-only: `list_watched_bots`, `get_bot_stats`, `get_bot_updates`, `search_mess
|
|||||||
```sh
|
```sh
|
||||||
make env # .env and docker-compose.override.yml from the examples
|
make env # .env and docker-compose.override.yml from the examples
|
||||||
make -C backend session # log the account in once; the session file stays in backend/sessions
|
make -C backend session # log the account in once; the session file stays in backend/sessions
|
||||||
make deploy # build what changed, migrate, start the containers
|
make -C backend migrate # the schema
|
||||||
|
make recreate # build and start the services in COMPOSE_PROFILES
|
||||||
```
|
```
|
||||||
|
|
||||||
`COMPOSE_PROFILES` in `.env` selects what runs on the machine, `docker-compose.override.yml` in each part holds the published ports and the `caddy` network aliases. The web client and the MCP endpoint are served by `api`; the bearer for both is `AUTH__TOKEN`.
|
`COMPOSE_PROFILES` in `.env` selects what runs on the machine, `docker-compose.override.yml` in each part holds the published ports and the `caddy` network aliases. The web client and the MCP endpoint are served by `api`; the bearer for both is `AUTH__TOKEN`.
|
||||||
@@ -44,12 +44,3 @@ make fmt
|
|||||||
make check
|
make check
|
||||||
make -C frontend dev
|
make -C frontend dev
|
||||||
```
|
```
|
||||||
=======
|
|
||||||
```sh
|
|
||||||
make env # .env and docker-compose.override.yml from the examples
|
|
||||||
make recreate # the services in COMPOSE_PROFILES
|
|
||||||
make check
|
|
||||||
```
|
|
||||||
|
|
||||||
Parts: `backend/`, `frontend/`, each with its own Makefile.
|
|
||||||
>>>>>>> after updating
|
|
||||||
@@ -1,13 +1,4 @@
|
|||||||
COMPOSE := cd .. && docker compose
|
COMPOSE := cd .. && docker compose
|
||||||
<<<<<<< before updating
|
|
||||||
IMAGE := beavergram/backend
|
|
||||||
IMAGE_INPUTS := pyproject.toml uv.lock Dockerfile
|
|
||||||
CODE := src scripts ../frontend
|
|
||||||
SERVICES := api userbot watcher
|
|
||||||
changed = ! git diff --quiet $(1) -- $(2) 2>/dev/null
|
|
||||||
stamp = { git update-ref $(1) HEAD 2>/dev/null || true; }
|
|
||||||
=======
|
|
||||||
>>>>>>> after updating
|
|
||||||
|
|
||||||
.PHONY: fmt check build migrate revision session
|
.PHONY: fmt check build migrate revision session
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,12 @@ if config.config_file_name is not None:
|
|||||||
target_metadata = SQLModel.metadata
|
target_metadata = SQLModel.metadata
|
||||||
|
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
def _async_url() -> str:
|
def _async_url() -> str:
|
||||||
return env.db.connection_url.replace("postgresql://", "postgresql+asyncpg://", 1)
|
return env.db.connection_url.replace("postgresql://", "postgresql+asyncpg://", 1)
|
||||||
=======
|
|
||||||
|
|
||||||
def include_name(name: str | None, type_: str, _parents: object) -> bool:
|
def include_name(name: str | None, type_: str, _parents: object) -> bool:
|
||||||
return not (type_ == "table" and name is not None and name.startswith("taskiq_"))
|
return not (type_ == "table" and name is not None and name.startswith("taskiq_"))
|
||||||
>>>>>>> after updating
|
|
||||||
|
|
||||||
|
|
||||||
def run_migrations_offline() -> None:
|
def run_migrations_offline() -> None:
|
||||||
@@ -37,17 +36,12 @@ def run_migrations_offline() -> None:
|
|||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
def _do_run_migrations(connection) -> None: # noqa: ANN001
|
def _do_run_migrations(connection) -> None: # noqa: ANN001
|
||||||
context.configure(connection=connection, target_metadata=target_metadata)
|
|
||||||
=======
|
|
||||||
def do_run_migrations(connection: Connection) -> None:
|
|
||||||
context.configure(
|
context.configure(
|
||||||
connection=connection,
|
connection=connection,
|
||||||
target_metadata=target_metadata,
|
target_metadata=target_metadata,
|
||||||
include_name=include_name,
|
include_name=include_name,
|
||||||
)
|
)
|
||||||
>>>>>>> after updating
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ unfixable = ["F401"]
|
|||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
[tool.ruff.lint.per-file-ignores]
|
||||||
"scripts/*" = ["INP"]
|
"scripts/*" = ["INP"]
|
||||||
|
"scripts/check_imports.py" = ["T201"]
|
||||||
"t/*" = ["ALL"]
|
"t/*" = ["ALL"]
|
||||||
"*.lock" = ["ALL"]
|
"*.lock" = ["ALL"]
|
||||||
"migrations/*" = ["INP", "D", "E501"]
|
"migrations/*" = ["INP", "D", "E501"]
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import sys
|
|||||||
|
|
||||||
HEAVY = ["aiogram", "pyrogram", "fastapi", "google.genai"]
|
HEAVY = ["aiogram", "pyrogram", "fastapi", "google.genai"]
|
||||||
SERVICES = {
|
SERVICES = {
|
||||||
"api": (["api.app"], {"fastapi"}),
|
"api": (["api.app"], {"fastapi", "pyrogram"}),
|
||||||
"userbot": (["userbot.runner", "userbot.handlers"], {"pyrogram"}),
|
"userbot": (["userbot.runner", "userbot.handlers"], {"pyrogram"}),
|
||||||
|
"watcher": (["watcher.runner"], {"pyrogram"}),
|
||||||
}
|
}
|
||||||
PROBE = """
|
PROBE = """
|
||||||
import importlib, sys
|
import importlib, sys
|
||||||
@@ -13,7 +14,7 @@ for module in sys.argv[1].split(","):
|
|||||||
importlib.import_module(module)
|
importlib.import_module(module)
|
||||||
print(" ".join(name for name in sys.argv[2:] if name in sys.modules))
|
print(" ".join(name for name in sys.argv[2:] if name in sys.modules))
|
||||||
"""
|
"""
|
||||||
ENV = dict(os.environ)
|
ENV = {**os.environ, "AUTH__TOKEN": "check"}
|
||||||
|
|
||||||
|
|
||||||
def loaded(modules: list[str]) -> tuple[set[str], str]:
|
def loaded(modules: list[str]) -> tuple[set[str], str]:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from userbot.modules.client import PyroClient
|
|||||||
from utils.env import env
|
from utils.env import env
|
||||||
from utils.logging import logger, setup_logging
|
from utils.logging import logger, setup_logging
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
setup_logging()
|
setup_logging()
|
||||||
|
|
||||||
|
|
||||||
@@ -19,9 +18,6 @@ def _finalize_session(sessions_dir: Path, name: str) -> Path:
|
|||||||
target = sessions_dir / f"{name}.session"
|
target = sessions_dir / f"{name}.session"
|
||||||
(sessions_dir / "generated.session").rename(target)
|
(sessions_dir / "generated.session").rename(target)
|
||||||
return target
|
return target
|
||||||
=======
|
|
||||||
from userbot.modules.client import PyroClient
|
|
||||||
>>>>>>> after updating
|
|
||||||
|
|
||||||
|
|
||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from pyrogram.errors import AuthTokenExpired, SessionPasswordNeeded
|
|||||||
from pyrogram.qrlogin import QRLogin
|
from pyrogram.qrlogin import QRLogin
|
||||||
from pyrogram.types import User
|
from pyrogram.types import User
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
from utils.env import env
|
from utils.env import env
|
||||||
|
|
||||||
LOGIN_TTL_SECONDS = 900
|
LOGIN_TTL_SECONDS = 900
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from pyrogram.errors import FloodWait, RPCError
|
|||||||
from pyrogram.types import User
|
from pyrogram.types import User
|
||||||
|
|
||||||
from api.login import LoginError, login_manager
|
from api.login import LoginError, login_manager
|
||||||
from userbot import DEVICE_MODEL_LIMIT
|
from userbot.modules.client import DEVICE_MODEL_LIMIT
|
||||||
from utils.read import accounts
|
from utils.read import accounts
|
||||||
from utils.read.models import AccountView
|
from utils.read.models import AccountView
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,4 @@ from dishka import make_async_container
|
|||||||
from dependencies.providers.postgres import DbProvider
|
from dependencies.providers.postgres import DbProvider
|
||||||
from dependencies.providers.storage import StorageProvider
|
from dependencies.providers.storage import StorageProvider
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
container = make_async_container(DbProvider(), StorageProvider())
|
container = make_async_container(DbProvider(), StorageProvider())
|
||||||
=======
|
|
||||||
container = make_async_container(DbProvider(), RepositoryProvider())
|
|
||||||
>>>>>>> after updating
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<<<<<<< before updating
|
|
||||||
from userbot.modules.client import DEVICE_MODEL, DEVICE_MODEL_LIMIT, PyroClient
|
|
||||||
|
|
||||||
__all__ = ["DEVICE_MODEL", "DEVICE_MODEL_LIMIT", "PyroClient"]
|
|
||||||
=======
|
|
||||||
>>>>>>> after updating
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from pyrogram.types import Message
|
from pyrogram.types import Message
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import repository
|
from userbot.modules.capture import repository
|
||||||
from userbot.modules.capture.repository import CHANNEL_ID_THRESHOLD
|
from userbot.modules.capture.repository import CHANNEL_ID_THRESHOLD
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from pyrogram.types import Message
|
from pyrogram.types import Message
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import repository
|
from userbot.modules.capture import repository
|
||||||
from userbot.modules.capture.chat_meta import meta_from_chat
|
from userbot.modules.capture.chat_meta import meta_from_chat
|
||||||
from userbot.modules.capture.message import sender_id
|
from userbot.modules.capture.message import sender_id
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.media import capture_media, media_unique_id, self_destruct_ttl
|
from userbot.modules.media import capture_media, media_unique_id, self_destruct_ttl
|
||||||
from userbot.modules.raw_json import raw_json
|
from userbot.modules.raw_json import raw_json
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from pyrogram.types import Message
|
from pyrogram.types import Message
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import capture_message
|
from userbot.modules.capture import capture_message
|
||||||
from userbot.modules.capture.chat_meta import meta_from_chat
|
from userbot.modules.capture.chat_meta import meta_from_chat
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.stt import is_transcribable
|
from userbot.modules.stt import is_transcribable
|
||||||
from userbot.modules.stt.gate import safe_transcribe
|
from userbot.modules.stt.gate import safe_transcribe
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from datetime import UTC, datetime
|
|||||||
|
|
||||||
from pyrogram.types import User
|
from pyrogram.types import User
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.presence import repository
|
from userbot.modules.presence import repository
|
||||||
from userbot.modules.raw_json import raw_json
|
from userbot.modules.raw_json import raw_json
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from pyrogram import raw
|
from pyrogram import raw
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
|
|
||||||
HANDLES = (raw.types.UpdateContactsReset, raw.types.UpdateUser)
|
HANDLES = (raw.types.UpdateContactsReset, raw.types.UpdateUser)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from pyrogram import raw
|
from pyrogram import raw
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
|
|
||||||
HANDLES = (
|
HANDLES = (
|
||||||
raw.types.UpdateDialogFilter,
|
raw.types.UpdateDialogFilter,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from collections.abc import Awaitable, Callable
|
|||||||
|
|
||||||
from pyrogram import raw
|
from pyrogram import raw
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.handlers.raw import (
|
from userbot.handlers.raw import (
|
||||||
contacts,
|
contacts,
|
||||||
dialog_filters,
|
dialog_filters,
|
||||||
@@ -12,6 +11,7 @@ from userbot.handlers.raw import (
|
|||||||
read_receipts,
|
read_receipts,
|
||||||
transcribed,
|
transcribed,
|
||||||
)
|
)
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
|
|
||||||
RawHandler = Callable[..., Awaitable[None]]
|
RawHandler = Callable[..., Awaitable[None]]
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ from dataclasses import replace
|
|||||||
|
|
||||||
from pyrogram import raw
|
from pyrogram import raw
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.avatars import capture_avatar
|
from userbot.modules.avatars import capture_avatar
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.profiles import active_username, snapshot_from_user
|
from userbot.modules.profiles import active_username, snapshot_from_user
|
||||||
from userbot.modules.profiles.parse import ProfileFields
|
from userbot.modules.profiles.parse import ProfileFields
|
||||||
from userbot.modules.profiles.repository import get_peer, write_profile
|
from userbot.modules.profiles.repository import get_peer, write_profile
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from pyrogram import raw, utils
|
from pyrogram import raw, utils
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import repository
|
from userbot.modules.capture import repository
|
||||||
from userbot.modules.capture.chat_meta import meta_from_peer
|
from userbot.modules.capture.chat_meta import meta_from_peer
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|
||||||
HANDLES = (raw.types.UpdateMessageReactions,)
|
HANDLES = (raw.types.UpdateMessageReactions,)
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ from datetime import UTC, datetime
|
|||||||
|
|
||||||
from pyrogram import raw, utils
|
from pyrogram import raw, utils
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture.chat_meta import meta_from_chat_id
|
from userbot.modules.capture.chat_meta import meta_from_chat_id
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.raw_json import raw_json
|
from userbot.modules.raw_json import raw_json
|
||||||
from userbot.modules.read_receipts import repository as receipts
|
from userbot.modules.read_receipts import repository as receipts
|
||||||
from userbot.modules.stt import repository
|
from userbot.modules.stt import repository
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from datetime import UTC, datetime
|
|||||||
|
|
||||||
from pyrogram import raw, utils
|
from pyrogram import raw, utils
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.raw_json import raw_json
|
from userbot.modules.raw_json import raw_json
|
||||||
from userbot.modules.read_receipts import repository
|
from userbot.modules.read_receipts import repository
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from pyrogram import raw
|
from pyrogram import raw
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture.chat_meta import meta_from_peer
|
from userbot.modules.capture.chat_meta import meta_from_peer
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.stt import repository
|
from userbot.modules.stt import repository
|
||||||
|
|
||||||
HANDLES = (raw.types.UpdateTranscribedAudio,)
|
HANDLES = (raw.types.UpdateTranscribedAudio,)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from pyrogram.types import Story
|
from pyrogram.types import Story
|
||||||
|
|
||||||
from userbot import PyroClient
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.stories.service import save_story
|
from userbot.modules.stories.service import save_story
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ class ChatMetaCache:
|
|||||||
chat_id: int,
|
chat_id: int,
|
||||||
meta: tuple[str | None, str | None],
|
meta: tuple[str | None, str | None],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
from userbot.modules.groups.repository import ( # noqa: PLC0415
|
from userbot.modules.groups.repository import get_latest_chat_meta # noqa: PLC0415
|
||||||
get_latest_chat_meta,
|
|
||||||
)
|
|
||||||
|
|
||||||
if chat_id not in self._cache:
|
if chat_id not in self._cache:
|
||||||
self._cache[chat_id] = await get_latest_chat_meta(pool, account_id, chat_id)
|
self._cache[chat_id] = await get_latest_chat_meta(pool, account_id, chat_id)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import asyncpg
|
|||||||
import uvloop
|
import uvloop
|
||||||
|
|
||||||
from dependencies.container import container
|
from dependencies.container import container
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import CaptureContext, build_capture_context
|
from userbot.modules.capture import CaptureContext, build_capture_context
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.jobs import JobConsumer
|
from userbot.modules.jobs import JobConsumer
|
||||||
from utils.env import env
|
from utils.env import env
|
||||||
from utils.jobs import enqueue
|
from utils.jobs import enqueue
|
||||||
|
|||||||
@@ -4,27 +4,7 @@ from pydantic import Field, SecretStr
|
|||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
<<<<<<< before updating
|
|
||||||
class DatabaseSettings(BaseSettings):
|
class DatabaseSettings(BaseSettings):
|
||||||
=======
|
|
||||||
def is_prod() -> bool:
|
|
||||||
return os.getenv("RUN_ENVIRONMENT") == "prod"
|
|
||||||
|
|
||||||
|
|
||||||
class Section(BaseSettings):
|
|
||||||
model_config = SettingsConfigDict(extra="ignore")
|
|
||||||
|
|
||||||
|
|
||||||
class LogSettings(Section):
|
|
||||||
level: str = "INFO"
|
|
||||||
level_external: str = "WARNING"
|
|
||||||
show_time: bool = False
|
|
||||||
show_locals: bool = False
|
|
||||||
console_width: int = 150
|
|
||||||
|
|
||||||
|
|
||||||
class DatabaseSettings(Section):
|
|
||||||
>>>>>>> after updating
|
|
||||||
host: str = "postgres"
|
host: str = "postgres"
|
||||||
port: int = 5432
|
port: int = 5432
|
||||||
user: str = "beavergram"
|
user: str = "beavergram"
|
||||||
@@ -76,6 +56,7 @@ class LogSettings(BaseSettings):
|
|||||||
level: str = "INFO"
|
level: str = "INFO"
|
||||||
level_external: str = "WARNING"
|
level_external: str = "WARNING"
|
||||||
show_time: bool = False
|
show_time: bool = False
|
||||||
|
show_locals: bool = False
|
||||||
console_width: int = 150
|
console_width: int = 150
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ from dataclasses import dataclass
|
|||||||
from pyrogram import raw, types
|
from pyrogram import raw, types
|
||||||
from pyrogram.errors import RPCError
|
from pyrogram.errors import RPCError
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import capture_message
|
from userbot.modules.capture import capture_message
|
||||||
from userbot.modules.capture.chat_meta import meta_from_chat
|
from userbot.modules.capture.chat_meta import meta_from_chat
|
||||||
from userbot.modules.capture.context import CaptureContext
|
from userbot.modules.capture.context import CaptureContext
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from utils.logging import logger
|
from utils.logging import logger
|
||||||
|
|
||||||
EARLIEST_PTS = 1
|
EARLIEST_PTS = 1
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ from pyrogram.handlers import (
|
|||||||
MessageHandler,
|
MessageHandler,
|
||||||
)
|
)
|
||||||
|
|
||||||
from userbot import PyroClient
|
|
||||||
from userbot.modules.capture import capture_message
|
from userbot.modules.capture import capture_message
|
||||||
from userbot.modules.capture.chat_meta import meta_from_chat
|
from userbot.modules.capture.chat_meta import meta_from_chat
|
||||||
|
from userbot.modules.client import PyroClient
|
||||||
from userbot.modules.jobs import JobConsumer
|
from userbot.modules.jobs import JobConsumer
|
||||||
from utils.events import notify_bg_event
|
from utils.events import notify_bg_event
|
||||||
from utils.jobs import enqueue
|
from utils.jobs import enqueue
|
||||||
|
|||||||
Reference in new issue
Block a user