From ae039e231056b871dfc112e7df25ce94d11281a7 Mon Sep 17 00:00:00 2001 From: Redume Date: Wed, 26 Mar 2025 14:13:20 +0300 Subject: [PATCH 1/3] refactor: Fixed the code, removed the problematic characters, and made indents --- functions/convert.py | 18 ++++++---- functions/create_chart.py | 17 ++++----- main.py | 75 +++++++++++++++++++++++++++------------ utils/format_number.py | 5 ++- utils/inline_query.py | 6 ++-- 5 files changed, 80 insertions(+), 41 deletions(-) diff --git a/functions/convert.py b/functions/convert.py index 8d1931a..fc9407e 100644 --- a/functions/convert.py +++ b/functions/convert.py @@ -9,7 +9,7 @@ import yaml from utils.format_number import format_number -config = yaml.safe_load(open('config.yaml')) +config = yaml.safe_load(open('config.yaml', 'r', encoding='utf-8')) class Converter: def __init__(self): @@ -17,7 +17,7 @@ class Converter: self.conv_amount: float = 0.0 self.from_currency: str = '' self.conv_currency: str = '' - + async def convert(self) -> None: if not await self.kekkai(): await self.ddg() @@ -45,26 +45,32 @@ class Converter: async def ddg(self) -> None: - async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=3)) as session: + async with aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=3) + ) as session: async with session.get( 'https://duckduckgo.com/js/spice/currency/' f'{self.amount}/{self.from_currency}/{self.conv_currency}' ) as res: data_text = await res.text() - + data = json.loads(re.findall(r'\(\s*(.*)\s*\);$', data_text)[0]) for key in ['terms', 'privacy', 'timestamp']: data.pop(key, None) if not data.get('to'): - raise RuntimeError('Failed to get the exchange rate from DuckDuckGo') + raise RuntimeError( + 'Failed to get the exchange rate from DuckDuckGo' + ) conv = data.get('to')[0] conv_amount = conv.get('mid') if conv_amount is None: - raise RuntimeError('Error when converting currency via DuckDuckGo') + raise RuntimeError( + 'Error when converting currency via DuckDuckGo' + ) self.conv_amount = float(conv_amount) diff --git a/functions/create_chart.py b/functions/create_chart.py index 117dd4d..9498298 100644 --- a/functions/create_chart.py +++ b/functions/create_chart.py @@ -1,19 +1,20 @@ +from http import HTTPStatus + import yaml import aiohttp -from http import HTTPStatus - -config = yaml.safe_load(open('config.yaml')) +config = yaml.safe_load(open('config.yaml', 'r', encoding='utf-9')) async def create_chart(from_currency: str, conv_currency: str) -> (dict, None): async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=3)) as session: - async with session.get(f'{config["kekkai_instance"]}/api/getChart/month/', params={ - 'from_currency': from_currency, - 'conv_currency': conv_currency - }) as res: + async with session.get( + f'{config["kekkai_instance"]}/api/getChart/month/', params={ + 'from_currency': from_currency, + 'conv_currency': conv_currency + }) as res: if not HTTPStatus(res.status).is_success: return None - + data = await res.json() return data.get('message', None) diff --git a/main.py b/main.py index 4b499b5..a94dba3 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,4 @@ -from functions.convert import Converter -from utils.format_number import format_number -from utils.inline_query import reply -from functions.create_chart import create_chart - +import hashlib import yaml from aiohttp import web @@ -13,10 +9,16 @@ from aiogram.enums import ParseMode from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application from aiogram.filters import CommandStart -import hashlib +from functions.convert import Converter +from functions.create_chart import create_chart +from utils.format_number import format_number +from utils.inline_query import reply -config = yaml.safe_load(open('config.yaml')) -bot = Bot(token=config['telegram_token'], default=DefaultBotProperties(parse_mode=ParseMode.HTML)) +config = yaml.safe_load(open('config.yaml', 'r', encoding='utf-8')) +bot = Bot( + token=config['telegram_token'], + default=DefaultBotProperties(parse_mode=ParseMode.HTML) + ) router = Router() @@ -57,13 +59,26 @@ async def currency(query: types.InlineQuery) -> None: try: conv.amount = float(args[0].replace(',', '.')) if conv.amount < 0: - return await reply(result_id, [("Negative amounts are not supported.", None, None)], query) + return await reply( + result_id, + [ + ("Negative amounts are not supported.", None, None) + ], + query + ) except ValueError: - return await reply(result_id, [("Please enter a valid number for the amount.", - f'@{get_bot.username} USD RUB \n' - f'@{get_bot.username} 12 USD RUB', - None, None)], query) + return await reply( + result_id, + [ + ( + "Please enter a valid number for the amount.", + f'@{get_bot.username} USD RUB \n' + f'@{get_bot.username} 12 USD RUB', + None, None + ) + ], + query) from_currency = args[1] conv_currency = args[2] @@ -71,23 +86,37 @@ async def currency(query: types.InlineQuery) -> None: from_currency = args[0] conv_currency = args[1] else: - return await reply(result_id, - [( - 'The source and target currency could not be determined.', - None, None - )], - query) + return await reply( + result_id, + [ + ( + 'The source and target currency could not be determined.', + None, None + ) + ], + query + ) conv.from_currency = from_currency.upper() conv.conv_currency = conv_currency.upper() try: await conv.convert() - except RuntimeError as e: - return await reply(result_id, [('The currency exchange rate could not be determined', None, None)], query) + except RuntimeError: + return await reply( + result_id, + [ + ( + 'The currency exchange rate could not be determined', + None, None + ) + ], + query + ) chart = await create_chart(from_currency, conv_currency) - message = f'{format_number(conv.amount)} {conv.from_currency} = {conv.conv_amount} {conv.conv_currency}' + message = f'{format_number(conv.amount)} {conv.from_currency} ' \ + f'= {conv.conv_amount} {conv.conv_currency}' results = [(message, None, None)] @@ -99,7 +128,7 @@ async def currency(query: types.InlineQuery) -> None: async def on_startup(bot: Bot) -> None: await bot.set_webhook( - f"{config['webhook']['base_url']}{config['webhook']['path']}", + f"{config['webhook']['base_url']}{config['webhook']['path']}", secret_token=config['webhook']['secret_token'], allowed_updates=['inline_query', 'message'] ) diff --git a/utils/format_number.py b/utils/format_number.py index bcc1e9b..d9a2766 100644 --- a/utils/format_number.py +++ b/utils/format_number.py @@ -11,7 +11,10 @@ def format_number(number): return formatted_integer fractional_str = f"{fractional_part:.30f}".split('.')[1] - first_non_zero = next((i for i, char in enumerate(fractional_str) if char != '0'), len(fractional_str)) + first_non_zero = next( + (i for i, char in enumerate(fractional_str) if char != '0'), + len(fractional_str) + ) result_fractional = fractional_str[:first_non_zero + 3] result_fractional = result_fractional.rstrip('0') diff --git a/utils/inline_query.py b/utils/inline_query.py index f9c1aba..3d36a2a 100644 --- a/utils/inline_query.py +++ b/utils/inline_query.py @@ -1,7 +1,7 @@ -from aiogram import types - import re +from aiogram import types + async def reply(result_id: str, args: list, query: types.InlineQuery) -> None: if not args: return @@ -32,4 +32,4 @@ async def reply(result_id: str, args: list, query: types.InlineQuery) -> None: parse_mode='markdown', cache_time=0, is_personal=True - ) \ No newline at end of file + ) From 87ef0b2daf3542e96cc10307e9d511bdf3d0a52b Mon Sep 17 00:00:00 2001 From: Redume Date: Wed, 26 Mar 2025 17:55:59 +0300 Subject: [PATCH 2/3] fix: corrected the name of the encoding --- functions/create_chart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/create_chart.py b/functions/create_chart.py index 9498298..9348789 100644 --- a/functions/create_chart.py +++ b/functions/create_chart.py @@ -3,7 +3,7 @@ from http import HTTPStatus import yaml import aiohttp -config = yaml.safe_load(open('config.yaml', 'r', encoding='utf-9')) +config = yaml.safe_load(open('config.yaml', 'r', encoding='utf-8')) async def create_chart(from_currency: str, conv_currency: str) -> (dict, None): async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=3)) as session: From c0680d38d54e268862866cc794e83face22d3fb1 Mon Sep 17 00:00:00 2001 From: Redume Date: Wed, 26 Mar 2025 17:57:14 +0300 Subject: [PATCH 3/3] fix: Fixed a bug, at midnight, when there is no currency rate, it did not give anything, now the date will be in the same timezone as kekkai --- functions/convert.py | 17 ++++++++++++++++- requirements.txt | 3 ++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/functions/convert.py b/functions/convert.py index fc9407e..d4b15ac 100644 --- a/functions/convert.py +++ b/functions/convert.py @@ -4,6 +4,7 @@ from datetime import datetime from decimal import Decimal from http import HTTPStatus +import pytz import aiohttp import yaml @@ -24,9 +25,23 @@ class Converter: self.conv_amount = format_number(Decimal(self.conv_amount)) + async def get_timezone(self) -> str: + async with aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=3) + ) as session: + async with session.get( + f'{config['kekkai_instance']}/api/metadata' + ) as res: + + if not HTTPStatus(res.status).is_success: + return 'UTC' + + data = await res.json() + return data.get('timezone', 'UTC') async def kekkai(self) -> bool: - date = datetime.today().strftime('%Y-%m-%d') + timezone = pytz.timezone(await self.get_timezone()) + date = datetime.now(timezone).strftime('%Y-%m-%d') async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=3)) as session: async with session.get(f'{config['kekkai_instance']}/api/getRate/', params={ diff --git a/requirements.txt b/requirements.txt index 21259b5..96dd1bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ aiohttp~=3.9.5 PyYAML~=6.0.1 -aiogram~=3.15.0 \ No newline at end of file +aiogram~=3.15.0 +pytz~=2025.2 \ No newline at end of file