import asyncio
import logging
import aiohttp
from typing import Dict, Tuple, Union, Optional, List
from .. import utils, loader
from hikkatl.tl.patched import Message
from difflib import get_close_matches
from ..inline.types import InlineMessage
# meta developer: @sqlmerr_m
# meta icon: https://github.com/sqlmerr/hikka_mods/blob/main/assets/icons/currencyconverter.png?raw=true
# meta banner: https://github.com/sqlmerr/hikka_mods/blob/main/assets/banners/currencyconverter.png?raw=true
async def find_currency(from_: str, to: str) -> Optional[Tuple[str, str, float]]:
async with aiohttp.ClientSession() as session:
res = await session.get(
"https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies.json"
)
json: Dict[str, str] = await res.json()
close_match = get_close_matches(from_, json.keys(), 1, cutoff=0.1)
if not close_match or close_match[0] == "":
return
from_currency = json[close_match[0]]
if not from_currency:
return
from_currency = close_match[0].upper()
res2 = await session.get(
f"https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/{close_match[0]}.json"
)
json2: Dict[str, Union[str, Dict[str, str]]] = await res2.json()
close_match2 = get_close_matches(
to, json2[close_match[0]].keys(), 1, cutoff=0.1
)
if close_match2 and close_match2[0] != "":
to_currency = json2[close_match[0]]
if not to_currency:
return
to_currency = close_match2[0].upper()
price = json2[from_currency.lower()][to_currency.lower()]
if not isinstance(price, float):
return
else:
return
return from_currency, to_currency, price
@loader.tds
class CurrencyConverter(loader.Module):
"""Module for converting a large number of currencies to other currencies"""
strings = {
"name": "Currency Converter",
"msg": "💲 Convert\n{from_} / {to} {price}",
"no_args": "❌ No args!",
"args_too_short": "❌ Args are too short!",
"not_found": "❌ Currency not found!",
"_cfg_autoupdate": "Auto update message",
"_cfg_update_delay": "Message auto update delay. In hours",
}
strings_ru = {
"msg": "💲 Конвертация\n{from_} / {to} {price}",
"no_args": "❌ Вы не передали аргументы!",
"args_too_short": "❌ Слишком короткие аргументы!",
"not_found": "❌ Валюта не найдена!",
"_cls_doc": "Модуль для конвертации большого количества валют в другие валюты",
"_cfg_autoupdate": "Автообновление сообщения",
"_cfg_update_delay": "Кд автообновления сообщения. В часах",
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"autoupdate",
False,
lambda: self.strings("_cfg_autoupdate"),
validator=loader.validators.Boolean(),
),
loader.ConfigValue(
"update_delay",
24,
lambda: self.strings("_cfg_update_delay"),
validator=loader.validators.Integer(),
),
)
@loader.command(ru_doc="[from] [to] Конвертировать одну валюту в другую")
async def cconvert(self, message: Message):
"""[from] [to] Convert currency to other currency"""
args = utils.get_args(message)
if len(args) == 0:
await utils.answer(message, self.strings("no_args"))
return
if len(args) < 2:
await utils.answer(message, self.strings("args_too_short"))
return
from_, to = args[0].lower(), args[1].lower()
result = await find_currency(from_, to)
if result is None:
await utils.answer(message, self.strings("not_found"))
return
if not self.config["autoupdate"]:
await utils.answer(
message,
self.strings["msg"].format(
from_=result[0], to=result[1], price=round(result[2], 2)
),
)
return
msg: InlineMessage = await self.inline.form(
message=message,
text=self.strings["msg"].format(
from_=result[0], to=result[1], price=round(result[2], 2)
),
reply_markup={"text": "\u0020\u2800", "data": "empty"},
)
msgs_to_upd = self.get("msgs", [])
msgs_to_upd.append(
{
"msg_id": msg.inline_message_id,
"unit_id": msg.unit_id,
"from": from_,
"to": to,
}
)
self.set("msgs", msgs_to_upd)
@loader.loop(interval=1, autostart=True)
async def loop(self) -> None:
if not self.config["autoupdate"]:
return
msgs_to_upd: List[dict] = self.get("msgs", [])
for msg in msgs_to_upd:
result = await find_currency(msg["from"], msg["to"])
if result is None:
continue
await self.inline._edit_unit(
text=self.strings["msg"].format(
from_=result[0], to=result[1], price=round(result[2], 2)
),
inline_message_id=msg["msg_id"],
unit_id=msg["unit_id"],
)
logging.info("updated")
await asyncio.sleep(self.config["update_delay"] * 3600)