#meta developer: @matubuntu import requests, bs4 from datetime import datetime from .. import loader, utils import lxml # requires: lxml requests bs4 _FLAGS = { "AUD": "🇦🇺", "AZN": "🇦🇿", "GBP": "🇬🇧", "AMD": "🇦🇲", "BYN": "🇧🇾", "BGN": "🇧🇬", "BRL": "🇧🇷", "HUF": "🇭🇺", "VND": "🇻🇳", "HKD": "🇭🇰", "GEL": "🇬🇪", "DKK": "🇩🇰", "AED": "🇦🇪", "USD": "🇺🇸", "EUR": "🇪🇺", "EGP": "🇪🇬", "INR": "🇮🇳", "IDR": "🇮🇩", "KZT": "🇰🇿", "CAD": "🇨🇦", "QAR": "🇶🇦", "KGS": "🇰🇬", "CNY": "🇨🇳", "MDL": "🇲🇩", "NZD": "🇳🇿", "NOK": "🇳🇴", "PLN": "🇵🇱", "RON": "🇷🇴", "SGD": "🇸🇬", "TJS": "🇹🇯", "THB": "🇹🇭", "TRY": "🇹🇷", "TMT": "🇹🇲", "UZS": "🇺🇿", "UAH": "🇺🇦", "CZK": "🇨🇿", "SEK": "🇸🇪", "CHF": "🇨🇭", "RSD": "🇷🇸", "ZAR": "🇿🇦", "KRW": "🇰🇷", "JPY": "🇯🇵", } _CRYPTO_EMOJIS = { "BTC": "💰", "ETH": "💰", "SOL": "💰", "TON": "💰", "USDT": "💰", "XRP": "💰", "USDC": "💰", "ADA": "💰", "DOGE": "💰", "TRX": "💰", "AVAX": "💰", "LTC": "💰", "BCH": "💰", "ATOM": "💰", "XLM": "💰", "SHIB": "💰", "UNI": "💰", "XMR": "💰", "LINK": "💰", "ETC": "💰", "SUI": "💰", "NEAR": "💰", "VET": "💰", "FIL": "💰", "XTZ": "💰", "ALGO": "💰", "THETA": "💰", "FTM": "💰", "XDAI": "💰", "RUNE": "💰", "DOT": "💰", } _CRYPTO_LIST = { "BTC": "Bitcoin", "ETH": "Ethereum", "XMR": "Monero", "LTC": "Litecoin", "XRP": "XRP", "ADA": "Cardano", "DOGE": "Dogecoin", "SOL": "Solana", "DOT": "Polkadot", "USDT": "Tether", "TON": "Toncoin", "USDC": "USD Coin", "TRX": "TRON", "AVAX": "Avalanche", "BCH": "Bitcoin Cash", "ATOM": "Cosmos", "XLM": "Stellar", "SHIB": "Shiba Inu", "UNI": "Uniswap", "LINK": "Chainlink", "ETC": "Ethereum Classic", "SUI": "Sui", "NEAR": "NEAR Protocol", "VET": "VeChain", "FIL": "Filecoin", "XTZ": "Tezos", "ALGO": "Algorand", "THETA": "Theta Network", "FTM": "Fantom", "XDAI": "xDai", "RUNE": "THORChain", } def _fmt_num(v, d=3): p = f"{v:,.{d}f}".replace(",", " ").split(".") i = p[0] d = p[1].rstrip("0") if len(p) > 1 else "" return f"{i},{d}" if d else i @loader.tds class FinanceMod(loader.Module): strings = { "name": "FinanceMod", "valute_description": "<кол-во> <код> - курс валюты\n<кол-во> - список", "valute_no_args": ( "💵 Курс валюты с сайта ЦБ(РФ)\n" "Актуально на {}\n\n
{}
" ), "valute_specific": ( "💵 Курс валюты с сайта ЦБ(РФ)\n" "Актуально на {}\n\n{}" ), "valute_not_found": "🚫 Валюта {} не найдена", "crypto_description": "<кол-во> <код> - курс крипты\n<кол-во> - список", "crypto_no_args": "💎 Курсы криптовалют\n\n
{}
", "crypto_specific": "💎 Курс криптовалюты\n\n{}", "crypto_not_found": "🚫 Криптовалюта {} не найдена", "error": "🚫 Ошибка получения данных", } def __init__(self): self.config = loader.ModuleConfig( loader.ConfigValue( "crypto_currency", "USD", lambda: "Валюта для отображения крипты (USD, RUB, EUR)", validator=loader.validators.Choice(["USD", "RUB", "EUR"]) ) ) async def _get_curr_data(self): try: r = requests.get("https://www.cbr.ru/scripts/XML_daily.asp") s = bs4.BeautifulSoup(r.content, 'xml') d = datetime.strptime(s.ValCurs['Date'], "%d.%m.%Y").strftime("%d.%m.%Y") return d, s.find_all('Valute') except: return None, None async def _get_rates(self): try: r = requests.get("https://www.cbr.ru/scripts/XML_daily.asp") s = bs4.BeautifulSoup(r.content, 'xml') rt = {'USD': None, 'EUR': None} for v in s.find_all('Valute'): if v.CharCode.text in ['USD', 'EUR']: n = float(v.Nominal.text.replace(',', '.')) vl = float(v.Value.text.replace(',', '.')) rt[v.CharCode.text] = vl / n if rt['USD'] and rt['EUR']: rt['EUR_USD'] = rt['USD'] / rt['EUR'] else: rt['EUR_USD'] = None return rt except: return None async def _fmt_curr(self, v, a=1): if v.CharCode.text == "XDR": return None c = v.CharCode.text n = v.Name.text v = float(v.Value.text.replace(',', '.')) / float(v.Nominal.text.replace(',', '.')) t = v * a ts = _fmt_num(t, 3) return f"{_FLAGS.get(c, '🏳')} [{a}] {n} ({c}) - {ts} руб." async def _get_crypto(self): try: return requests.get("https://api.coinlore.net/api/tickers/").json().get('data', []) except: return None async def _fmt_crypto(self, c, a=1): r = await self._get_rates() if not r: return "🚫 Ошибка получения курсов валют" cr = self.config["crypto_currency"] try: p = float(c['price_usd']) except: return "🚫 Ошибка данных криптовалюты" if cr == "RUB": if not r['USD']: return "🚫 Курс USD не найден" p *= r['USD'] elif cr == "EUR": if not r['EUR_USD']: return "🚫 Курс EUR/USD не рассчитан" p *= r['EUR_USD'] t = p * a ts = _fmt_num(t) s = c['symbol'].upper() e = _CRYPTO_EMOJIS.get(s, "💠") n = _CRYPTO_LIST.get(s, c['name']) cs = {"USD": "$", "RUB": "₽", "EUR": "€"}.get(cr, "$") return f"{e} [{a}] {n} ({s}) - {ts}{cs}" @loader.command() async def valutecmd(self, m): """[count] [usd, eur, ...]""" a = utils.get_args(m) d, v = await self._get_curr_data() if not d or not v: return await utils.answer(m, self.strings["error"]) if len(a) == 0: l = [] for x in v: if (n := await self._fmt_curr(x)): l.append(n) await utils.answer(m, self.strings["valute_no_args"].format(d, "\n".join(l))) elif len(a) == 1: try: am = float(a[0]) l = [] for x in v: if (n := await self._fmt_curr(x, am)): l.append(n) await utils.answer(m, self.strings["valute_no_args"].format(d, "\n".join(l))) except: await utils.answer(m, "🚫 Некорректное число") elif len(a) == 2: try: am = float(a[0]) c = a[1].upper() for x in v: if x.CharCode.text == c: if (n := await self._fmt_curr(x, am)): return await utils.answer(m, self.strings["valute_specific"].format(d, n)) await utils.answer(m, self.strings["valute_not_found"].format(c)) except: await utils.answer(m, "🚫 Некорректное число") @loader.command() async def cryptocmd(self, m): """[count] [ton, btc, ...]""" a = utils.get_args(m) c = await self._get_crypto() if not c: return await utils.answer(m, self.strings["error"]) try: if len(a) == 0: f = [x for x in c if x['symbol'].upper() in _CRYPTO_LIST] l = [] for x in f: if (n := await self._fmt_crypto(x)): l.append(n) await utils.answer(m, self.strings["crypto_no_args"].format("\n".join(l))) elif len(a) == 1: am = float(a[0]) f = [x for x in c if x['symbol'].upper() in _CRYPTO_LIST] l = [] for x in f: if (n := await self._fmt_crypto(x, am)): l.append(n) await utils.answer(m, self.strings["crypto_no_args"].format("\n".join(l))) elif len(a) == 2: am = float(a[0]) t = a[1].upper() f = False for x in c: if x['symbol'].upper() == t: if (n := await self._fmt_crypto(x, am)): f = True await utils.answer(m, self.strings["crypto_specific"].format(n)) break if not f: await utils.answer(m, self.strings["crypto_not_found"].format(t)) except ValueError: await utils.answer(m, "🚫 Некорректное число") except Exception as e: await utils.answer(m, f"🚫 Ошибка: {str(e)}")