diff --git a/README.md b/README.md index 7a8f4eb..a9c3ce4 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ OverUB is a modular Telegram userbot built around a plugin-first architecture. - `phone` (default) - `qr` (QR login) - `sms` (force SMS code) +5. Optional: set `bot.session_string` or `OVERUB_SESSION_STRING` to use a Telethon StringSession ## CLI - `python -m __main__ create-plugin ` diff --git a/core/app.py b/core/app.py index 509bc35..f6fe67b 100644 --- a/core/app.py +++ b/core/app.py @@ -118,6 +118,7 @@ class OverUB: phone=str(bot_cfg.get("phone", "")), qr_path=bot_cfg.get("login_qr_path"), qr_open=bool(bot_cfg.get("login_qr_open", False)), + session_string=bot_cfg.get("session_string"), ) await self.client.attach_handlers(self) await self._load_builtin_modules() diff --git a/core/client.py b/core/client.py index 93920a3..625fc60 100644 --- a/core/client.py +++ b/core/client.py @@ -27,14 +27,19 @@ class ClientWrapper: phone: Optional[str] = None, qr_path: Optional[str] = None, qr_open: bool = False, + session_string: Optional[str] = None, ) -> None: try: from telethon import TelegramClient from telethon.errors import SessionPasswordNeededError + from telethon.sessions import StringSession except ImportError as exc: raise RuntimeError("Telethon not installed") from exc - self.client = TelegramClient(self.session_name, self.api_id, self.api_hash) + if session_string: + self.client = TelegramClient(StringSession(session_string), self.api_id, self.api_hash) + else: + self.client = TelegramClient(self.session_name, self.api_id, self.api_hash) if login_mode == "qr": await self.client.connect() if await self.client.is_user_authorized(): diff --git a/core/config.py b/core/config.py index 2e21f72..729fd74 100644 --- a/core/config.py +++ b/core/config.py @@ -38,6 +38,7 @@ class ConfigManager: "OVERUB_API_ID": ("bot", "api_id"), "OVERUB_API_HASH": ("bot", "api_hash"), "OVERUB_SESSION": ("bot", "session_name"), + "OVERUB_SESSION_STRING": ("bot", "session_string"), "OVERUB_PREFIX": ("bot", "command_prefix"), "OVERUB_LOG_LEVEL": ("logging", "level"), "OVERUB_GIT_REMOTE": ("updates", "git", "remote"), diff --git a/scripts/generate-session-string.py b/scripts/generate-session-string.py new file mode 100644 index 0000000..80e69ce --- /dev/null +++ b/scripts/generate-session-string.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +""" +Generate a Telethon StringSession for OverUB. +""" + +import asyncio +import os +from getpass import getpass + +from telethon import TelegramClient +from telethon.sessions import StringSession + + +async def generate() -> None: + api_id = os.getenv("OVERUB_API_ID") or os.getenv("API_ID") + api_hash = os.getenv("OVERUB_API_HASH") or os.getenv("API_HASH") + if not api_id or not api_hash: + print("API_ID/API_HASH required (set OVERUB_API_ID/OVERUB_API_HASH or API_ID/API_HASH).") + return + try: + api_id = int(api_id) + except ValueError: + print("API_ID must be an integer") + return + + print("Starting session generation. You will be prompted to log in.") + client = TelegramClient(StringSession(), api_id, api_hash) + await client.start() + session_string = client.session.save() + await client.disconnect() + + print("\nSession string:") + print(session_string) + print("\nSet this in config/config.yml as bot.session_string or in env OVERUB_SESSION_STRING.") + + +def main() -> None: + asyncio.run(generate()) + + +if __name__ == "__main__": + main()