From 5262975275bfa7247a2da66b6b335e5615ba6b84 Mon Sep 17 00:00:00 2001 From: mctaylors Date: Wed, 26 Mar 2025 20:29:44 +0300 Subject: [PATCH] refactor: add config.py this change adds self validation in __init__, allows to make config values with different types (not just string) and stores config values in classes for easier accessibility Signed-off-by: mctaylors --- commands.py | 10 ++++------ config.ini | 4 ++-- config.py | 43 +++++++++++++++++++++++++++++++++++++++++++ inline_query.py | 9 ++++----- main.py | 26 ++++---------------------- 5 files changed, 57 insertions(+), 35 deletions(-) create mode 100644 config.py diff --git a/commands.py b/commands.py index 48ddc3d..5b001c8 100644 --- a/commands.py +++ b/commands.py @@ -3,8 +3,7 @@ from telegram.constants import ParseMode from telegram.ext import ContextTypes import html_parser -import main -from main import config +from config import * async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: @@ -29,11 +28,10 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No async def about_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: reply_markup = None - source_url = config.get('General', 'SourceUrl') - if source_url.startswith('http://') or source_url.startswith('https://'): + if general.sourceurl is not None: keyboard = [ [ - InlineKeyboardButton(f"source code", url=source_url) + InlineKeyboardButton(f"source code", url=general.sourceurl) ] ] reply_markup = InlineKeyboardMarkup(keyboard) @@ -43,7 +41,7 @@ async def about_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N f"{context.bot.first_name} is an inline image grabber written in python that grabs images from Danbooru " f"(or other similar services).\n\n" f"{html_parser.bold("currently configured instance:")}\n" - f"{html_parser.italic(config.get('App', 'Name'))} ({main.hostname})", + f"{html_parser.italic(app.name)} ({app.hostname})", parse_mode=ParseMode.HTML, reply_markup=reply_markup ) diff --git a/config.ini b/config.ini index e06a7be..67c053b 100644 --- a/config.ini +++ b/config.ini @@ -4,13 +4,13 @@ Token = ; (Optional) URL for "source code" button in /about. ; If not set, button will not appear in "about" menu. -SourceUrl = +SourceUrl = git.mctaylors.ru [App] ; Application name (e.g. Danbooru). Name = Danbooru ; Host (without http://) used to access the application API. -Host = danbooru.donmai.us +Host = stashboo.ru ; (Optional) Public host name (without http://) for the “Open in [App.Name]” button. ; Useful if the bot is hosted on the same server as the application. ; If not set, [App.Host] will be used instead. diff --git a/config.py b/config.py new file mode 100644 index 0000000..0d97476 --- /dev/null +++ b/config.py @@ -0,0 +1,43 @@ +import configparser +from typing import Optional + +import requests + +_c = configparser.ConfigParser() +_c.read("config.ini") + + +class _General: + token: str + sourceurl: Optional[str] + + def __init__(self): + self.token = _c.get('General', 'Token') + self.sourceurl = _c.get('General', 'SourceUrl') + if not self.sourceurl.startswith("http://") and not self.sourceurl.startswith("https://"): + self.sourceurl = None + + +class _App: + name: str + host: str + hostname: str + + def __init__(self): + self.name = _c.get('App', 'Name') + self.host = _c.get('App', 'Host') + # noinspection PyBroadException + try: + response = requests.get(f"http://{self.host}/status.json") + if response.status_code != 200: + raise + except: + print("Unable validate App.Host in config.ini.") + exit(1) + self.hostname = _c.get('App', 'HostName') + if not self.hostname: + self.hostname = self.host + + +general = _General() +app = _App() diff --git a/inline_query.py b/inline_query.py index 65e1c98..d308db3 100644 --- a/inline_query.py +++ b/inline_query.py @@ -6,9 +6,8 @@ from telegram import Update, InlineKeyboardButton, InlineQueryResultArticle, Inp from telegram.constants import ParseMode from telegram.ext import ContextTypes -import main +from config import * from extensions import humanize_tags_from_json, format_rating -from main import config # noinspection PyUnusedLocal @@ -21,7 +20,7 @@ async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No if not query.isdigit(): return - response = requests.get(f"http://{config.get('App', 'Host')}/posts/{query}.json") + response = requests.get(f"http://{app.host}/posts/{query}.json") if response.status_code != 200: await invalid_query(update, query) @@ -39,8 +38,8 @@ async def answer_query(update: Update, query: str, data) -> None: rating = format_rating(data['rating']) keyboard = [ [ - InlineKeyboardButton(f"Open in {config.get('App', 'Name')}", - url=f"https://{main.hostname}/posts/{query}"), + InlineKeyboardButton(f"Open in {app.name}", + url=f"https://{app.hostname}/posts/{query}"), InlineKeyboardButton("View original", url=data['file_url']) ] ] diff --git a/main.py b/main.py index eb36f96..4f19837 100644 --- a/main.py +++ b/main.py @@ -1,10 +1,10 @@ -import configparser import logging import os -import requests from telegram.ext import Application, CommandHandler, InlineQueryHandler +from config import * + logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) @@ -13,15 +13,8 @@ logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger(__name__) -config = configparser.ConfigParser() -config.read("config.ini") - -hostname = config.get('App', 'HostName') -hostname = hostname if hostname != "" else config.get('App', 'Host') - def main() -> None: - validate_config() application = Application.builder().token(get_token()).build() import commands @@ -35,23 +28,12 @@ def main() -> None: application.run_polling(allowed_updates=commands.Update.ALL_TYPES) -def validate_config() -> None: - # noinspection PyBroadException - try: - response = requests.get(f"http://{config.get('App', 'Host')}/status.json") - if response.status_code != 200: - raise - except: - print("Unable validate App.Host in config.ini.") - exit(1) - - def get_token(): if os.getenv("BOT_TOKEN") is not None: return os.getenv("BOT_TOKEN") - if config.get('General', 'Token') != "": - return config.get('General', 'Token') + if general.token != "": + return general.token print("Set BOT_TOKEN environment variable or use General.Token in config.ini to set bot token.") exit(1)