Code refactoring

This commit is contained in:
DarkCat09 2023-05-30 14:33:41 +04:00
parent 68e7a44cb3
commit ca8816a77d

202
main.py
View file

@ -1,103 +1,173 @@
import requests
import json import json
import hashlib import hashlib
from aiogram import Bot, types import logging
from typing import Any, Dict, List, Optional
import requests
from pydantic import BaseSettings
from aiogram import Bot
from aiogram.dispatcher import Dispatcher from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor from aiogram.utils import executor
from aiogram.types import InlineQuery
from aiogram.types import InlineQueryResultArticle
from aiogram.types import InputTextMessageContent
bot = Bot(token="5193950006:AAGU8elNfNB9FocVSIb4DnqoEvQk70Mqh5E")
# Constants
DDG_URL = 'https://duckduckgo.com/js/spice/currency'
COINAPI_URL = 'https://rest.coinapi.io/v1/exchangerate'
# ---
# Config from .env
class Settings(BaseSettings):
debug: bool
coinapi_key: str
telegram_token: str
class Config:
env_file = '.env'
env_file_encoding = 'utf-8'
settings = Settings()
# ---
# Logging
log = logging.getLogger('shirino')
handler = logging.StreamHandler()
fmt = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(fmt)
log.addHandler(handler)
if settings.debug:
handler.setLevel(logging.DEBUG)
log.setLevel(logging.DEBUG)
# ---
bot = Bot(token=settings.telegram_token)
dp = Dispatcher(bot) dp = Dispatcher(bot)
class TypeDict: class CurrencyConverter:
def __init__(self):
self.amount = None
self.from_amount = None
self.from_currency = None
self.to_currency = None
@staticmethod def __init__(self) -> None:
def get_currency(self, amount, from_currency, to_currency):
if amount is None:
amount = "1"
try: self.amount = 1.0
page = requests.get(f"https://duckduckgo.com/js/spice/currency/{amount}/{from_currency}/{to_currency}") self.conv_amount = 0.0
page = page.text.replace('ddg_spice_currency(', "").replace(');', "") self.from_currency = ''
page = json.loads(page) self.conv_currency = ''
if page["headers"]["description"].find("ERROR") != -1: def convert(self) -> None:
print(from_currency, to_currency) """Currency conversion"""
crypto = requests.get(f"https://rest.coinapi.io/v1/exchangerate/{from_currency.upper()}/{to_currency.upper()}", headers={
"X-CoinAPI-Key": "8A465920-C233-4EE2-860B-A0AF9EC21FFF"
}).json()
print(crypto) if not self.ddgapi():
self.coinapi()
self.from_amount = crypto.get("rate") def ddgapi(self) -> bool:
return crypto.get("rate") """Get data from DuckDuckGo's currency API
except KeyError: Returns:
print("blyat slomal") `False` if the currency does not exist,
return None `True` on successful conversion
"""
return page.get("conversion") # API request
resp = requests.get(
f'{DDG_URL}/{self.amount}/{self.from_currency}'
f'/{self.conv_currency}'
)
@staticmethod log.debug(resp.text)
def is_num(value):
return value.isdecimal() or value.replace('.', '', 1).isdecimal()
# Parsing JSON data
data: Dict[str, Any] = json.loads(
resp.text \
.replace('ddg_spice_currency(', '') \
.replace(');', '')
)
type_dict = TypeDict() log.debug(data)
# If the currency does not exist
descr = data.get('headers', {}).get('description', '')
if descr.find('ERROR') != -1:
return False
# Otherwise
conv: Dict[str, str] = data.get('conversion', {})
self.conv_amount = float(conv.get('converted-amount', 0))
log.debug(conv)
return True
def coinapi(self) -> None:
"""Get data from CoinAPI (for cryptocurrencies)"""
resp = requests.get(
(
f'{COINAPI_URL}/{self.from_currency}'
f'/{self.conv_currency}'
),
headers={
'X-CoinAPI-Key': settings.coinapi_key,
},
)
data: Dict[str, Any] = resp.json()
self.conv_amount = float(data.get('rate', 0))
@dp.inline_handler() @dp.inline_handler()
async def currency(query: types.InlineQuery): async def currency(inline_query: InlineQuery) -> None:
text = query.query.split(" ")
result_id: str = hashlib.md5(query.query.encode()).hexdigest()
if text == ['']: query = inline_query.query
return article: List[Optional[InlineQueryResultArticle]] = [None]
for i in range(len(text)): text = query.split()
if type_dict.is_num(text[i]): len_ = len(text)
continue
if text[i].find(",") != -1: result_id = hashlib.md5(query.encode()).hexdigest()
text[i] = text[i].replace(",", ".") conv = CurrencyConverter()
try: try:
if type_dict.is_num(text[0]): if len_ == 3:
res, crypto_rate = type_dict.get_currency(text[0], text[1], text[2]) conv.amount = float(text[0])
conv.from_currency = text[1].upper()
conv.conv_currency = text[2].upper()
conv.convert()
elif len_ == 2:
conv.from_currency = text[0].upper()
conv.conv_currency = text[1].upper()
conv.convert()
else: else:
res, crypto_rate = type_dict.get_currency(None, text[0], text[1]) raise ValueError('Надо 2 или 3 аргумента')
except Exception:
return
if res is None: result = (
return f'{conv.amount} {conv.from_currency} = '
f'{conv.conv_amount} {conv.conv_currency}'
)
print(res) except Exception as ex:
result = f'{type(ex)}: {ex}'
from_amount = res.get('from_amount', res['from-amount']) article[0] = InlineQueryResultArticle(
from_currency_symbol = res.get('from_currency_symbol', res['from-currency-symbol'])
converted_amount = res.get('converted_amount', res['converted-amount'])
to_currency_symbol = res.get('to_currency_symbol', res['to-currency-symbol'])
result = f"{from_amount} {from_currency_symbol} = {converted_amount} {to_currency_symbol}"
if crypto_rate:
result += f" | Crypto Rate: {crypto_rate}"
article = [types.InlineQueryResultArticle(
id=result_id, id=result_id,
title=result, title=result,
input_message_content=types.InputTextMessageContent( input_message_content=InputTextMessageContent(
message_text=result message_text=result,
))] ),
)
await inline_query.answer(
article,
cache_time=1,
is_personal=True,
)
await query.answer(article, cache_time=1, is_personal=True)
executor.start_polling(dp, skip_updates=True) executor.start_polling(dp, skip_updates=True)