Created
April 14, 2026 23:06
-
-
Save hu553in/5a15d4e50ec72d4cd2ce2b44930c7774 to your computer and use it in GitHub Desktop.
Yandex Cloud Function to get currency price in rubles via Yandex Alice skill
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import json | |
| import logging | |
| from urllib.request import urlopen | |
| from xml.etree import ElementTree | |
| logger = logging.getLogger() | |
| logger.setLevel(logging.INFO) | |
| CBR_URL = "https://www.cbr.ru/scripts/XML_daily.asp" | |
| CURRENCY_ALIASES = { | |
| "доллар": "USD", | |
| "долларов": "USD", | |
| "доллара": "USD", | |
| "долларе": "USD", | |
| "бакс": "USD", | |
| "баксов": "USD", | |
| "баксы": "USD", | |
| "евро": "EUR", | |
| "фунт": "GBP", | |
| "фунтов": "GBP", | |
| "фунта": "GBP", | |
| "стерлинг": "GBP", | |
| "юань": "CNY", | |
| "юаней": "CNY", | |
| "юаня": "CNY", | |
| "лира": "TRY", | |
| "лир": "TRY", | |
| "лиры": "TRY", | |
| "рупия": "INR", | |
| "рупий": "INR", | |
| "рупии": "INR", | |
| "дирхам": "AED", | |
| "дирхамов": "AED", | |
| "дирхама": "AED", | |
| "риал": "QAR", | |
| "риалов": "QAR", | |
| "риала": "QAR", | |
| "риял": "SAR", | |
| "риялов": "SAR", | |
| "рияла": "SAR", | |
| "франк": "CHF", | |
| "франков": "CHF", | |
| "франка": "CHF", | |
| "крона": "SEK", | |
| "крон": "SEK", | |
| "кроны": "SEK", | |
| "йена": "JPY", | |
| "йен": "JPY", | |
| "иена": "JPY", | |
| "иен": "JPY", | |
| "вона": "KRW", | |
| "вон": "KRW", | |
| "злотый": "PLN", | |
| "злотых": "PLN", | |
| "манат": "AZN", | |
| "манатов": "AZN", | |
| "маната": "AZN", | |
| "лари": "GEL", | |
| "тенге": "KZT", | |
| "гривна": "UAH", | |
| "гривен": "UAH", | |
| "гривны": "UAH", | |
| "бат": "THB", | |
| "батов": "THB", | |
| "бата": "THB", | |
| "реал": "BRL", | |
| "реалов": "BRL", | |
| "реала": "BRL", | |
| "рэнд": "ZAR", | |
| "рэндов": "ZAR", | |
| "рэнда": "ZAR", | |
| "рупий индонезийских": "IDR", | |
| "рупия индонезийская": "IDR", | |
| "донг": "VND", | |
| "донгов": "VND", | |
| "сом": "KGS", | |
| "сомов": "KGS", | |
| "сома": "KGS", | |
| "сомони": "TJS", | |
| "лей": "RON", | |
| "леев": "RON", | |
| "лея": "RON", | |
| "динар": "RSD", | |
| "динаров": "RSD", | |
| "динара": "RSD", | |
| "форинт": "HUF", | |
| "форинтов": "HUF", | |
| "форинта": "HUF", | |
| "сум": "UZS", | |
| "сумов": "UZS", | |
| "сума": "UZS", | |
| "песо": "CUP", | |
| "найра": "NGN", | |
| "найр": "NGN", | |
| "быр": "ETB", | |
| "быров": "ETB", | |
| "кьят": "MMK", | |
| "кьятов": "MMK", | |
| "тугрик": "MNT", | |
| "тугриков": "MNT", | |
| "тугрика": "MNT", | |
| "так": "BDT", | |
| "боливиано": "BOB", | |
| "белорусский рубль": "BYN", | |
| "белорусских рублей": "BYN", | |
| "белорусского рубля": "BYN", | |
| "австралийский доллар": "AUD", | |
| "австралийских долларов": "AUD", | |
| "австралийского доллара": "AUD", | |
| "канадский доллар": "CAD", | |
| "канадских долларов": "CAD", | |
| "канадского доллара": "CAD", | |
| "новозеландский доллар": "NZD", | |
| "новозеландских долларов": "NZD", | |
| "новозеландского доллара": "NZD", | |
| "сингапурский доллар": "SGD", | |
| "сингапурских долларов": "SGD", | |
| "сингапурского доллара": "SGD", | |
| "гонконгский доллар": "HKD", | |
| "гонконгских долларов": "HKD", | |
| "гонконгского доллара": "HKD", | |
| "датская крона": "DKK", | |
| "датских крон": "DKK", | |
| "датской кроны": "DKK", | |
| "норвежская крона": "NOK", | |
| "норвежских крон": "NOK", | |
| "норвежской кроны": "NOK", | |
| "шведская крона": "SEK", | |
| "шведских крон": "SEK", | |
| "шведской кроны": "SEK", | |
| "чешская крона": "CZK", | |
| "чешских крон": "CZK", | |
| "чешской кроны": "CZK", | |
| "катарский риал": "QAR", | |
| "катарских риалов": "QAR", | |
| "катарского риала": "QAR", | |
| "саудовский риял": "SAR", | |
| "саудовских риялов": "SAR", | |
| "саудовского рияла": "SAR", | |
| "оманский риал": "OMR", | |
| "оманских риалов": "OMR", | |
| "оманского риала": "OMR", | |
| "бахрейнский динар": "BHD", | |
| "бахрейнских динаров": "BHD", | |
| "бахрейнского динара": "BHD", | |
| "сербский динар": "RSD", | |
| "сербских динаров": "RSD", | |
| "сербского динара": "RSD", | |
| "алжирский динар": "DZD", | |
| "алжирских динаров": "DZD", | |
| "алжирского динара": "DZD", | |
| "египетский фунт": "EGP", | |
| "египетских фунтов": "EGP", | |
| "египетского фунта": "EGP", | |
| "иранский риал": "IRR", | |
| "иранских риалов": "IRR", | |
| "иранского риала": "IRR", | |
| "туркменский манат": "TMT", | |
| "туркменских манатов": "TMT", | |
| "туркменского маната": "TMT", | |
| "азербайджанский манат": "AZN", | |
| "азербайджанских манатов": "AZN", | |
| "азербайджанского маната": "AZN", | |
| "молдавский лей": "MDL", | |
| "молдавских леев": "MDL", | |
| "молдавского лея": "MDL", | |
| "румынский лей": "RON", | |
| "румынских леев": "RON", | |
| "румынского лея": "RON", | |
| "армянский драм": "AMD", | |
| "армянских драмов": "AMD", | |
| "армянского драма": "AMD", | |
| "драм": "AMD", | |
| "драмов": "AMD", | |
| "usd": "USD", | |
| "eur": "EUR", | |
| "gbp": "GBP", | |
| "cny": "CNY", | |
| "jpy": "JPY", | |
| "chf": "CHF", | |
| "try": "TRY", | |
| "inr": "INR", | |
| "aed": "AED", | |
| "qar": "QAR", | |
| "sar": "SAR", | |
| "krw": "KRW", | |
| "pln": "PLN", | |
| "azn": "AZN", | |
| "gel": "GEL", | |
| "kzt": "KZT", | |
| "uah": "UAH", | |
| "thb": "THB", | |
| "brl": "BRL", | |
| "zar": "ZAR", | |
| "idr": "IDR", | |
| "vnd": "VND", | |
| "kgs": "KGS", | |
| "tjs": "TJS", | |
| "ron": "RON", | |
| "rsd": "RSD", | |
| "huf": "HUF", | |
| "uzs": "UZS", | |
| "cup": "CUP", | |
| "ngn": "NGN", | |
| "etb": "ETB", | |
| "mmk": "MMK", | |
| "mnt": "MNT", | |
| "bdt": "BDT", | |
| "bob": "BOB", | |
| "byn": "BYN", | |
| "aud": "AUD", | |
| "cad": "CAD", | |
| "nzd": "NZD", | |
| "sgd": "SGD", | |
| "hkd": "HKD", | |
| "dkk": "DKK", | |
| "nok": "NOK", | |
| "sek": "SEK", | |
| "czk": "CZK", | |
| "omr": "OMR", | |
| "bhd": "BHD", | |
| "dzd": "DZD", | |
| "egp": "EGP", | |
| "irr": "IRR", | |
| "tmt": "TMT", | |
| "mdl": "MDL", | |
| "amd": "AMD", | |
| "xdr": "XDR", | |
| } | |
| def fetch_rates(): | |
| with urlopen(CBR_URL, timeout=5) as resp: | |
| tree = ElementTree.parse(resp) | |
| rates = {} | |
| names = {} | |
| for valute in tree.findall("Valute"): | |
| code = valute.findtext("CharCode") | |
| name = valute.findtext("Name") | |
| value = float(valute.findtext("VunitRate").replace(",", ".")) | |
| rates[code] = value | |
| names[code] = name | |
| return rates, names, tree.getroot().attrib.get("Date", "") | |
| def parse_currency(text): | |
| lower = text.lower() | |
| for alias in sorted(CURRENCY_ALIASES, key=len, reverse=True): | |
| if alias in lower: | |
| return CURRENCY_ALIASES[alias] | |
| return None | |
| def respond(text, end_session=False): | |
| return { | |
| "response": {"text": text, "tts": text, "end_session": end_session}, | |
| "version": "1.0", | |
| } | |
| def handler(event, context): | |
| body = event if "request" in event else json.loads(event.get("body", "{}")) | |
| session = body.get("session", {}) | |
| req = body.get("request", {}) | |
| logger.info("Incoming: %s", json.dumps(body, ensure_ascii=False)) | |
| if session.get("new"): | |
| logger.info("New session") | |
| return respond("Привет! Спроси курс любой валюты. Например: сколько стоит доллар?") | |
| utterance = req.get("original_utterance", "").strip() | |
| if not utterance: | |
| logger.warning("Empty utterance") | |
| return respond("Не расслышала. Повтори.") | |
| code = parse_currency(utterance) | |
| if not code: | |
| logger.warning("Could not parse currency from: %s", utterance) | |
| return respond("Не поняла валюту. Скажи, например: курс доллара, или курс евро.") | |
| logger.info("Fetching rate for %s", code) | |
| try: | |
| rates, names, date = fetch_rates() | |
| if code not in rates: | |
| logger.warning("Currency %s not found in CBR response", code) | |
| return respond(f"ЦБ не публикует курс {code}.", end_session=True) | |
| value = rates[code] | |
| name = names.get(code, code) | |
| text = f"{name} на {date}: {value:.2f} рублей." | |
| logger.info("Success: %s", text) | |
| except Exception as exc: | |
| logger.exception("Failed to fetch rates") | |
| text = f"Не удалось получить курс: {exc}" | |
| return respond(text, end_session=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment