mirror of
https://github.com/Redume/Shirino.git
synced 2024-12-24 17:23:46 +03:00
CoinAPI token rotation
This commit is contained in:
parent
2573253e2b
commit
b98c16f642
3 changed files with 45 additions and 10 deletions
|
@ -1,5 +1,5 @@
|
|||
DEBUG=false # debug logging
|
||||
TIMEOUT=2 # http requests timeout
|
||||
NDIGITS=3 # digits after floating point or after zeroes
|
||||
COINAPI_KEY= # coinapi key
|
||||
COINAPI_KEYS=["key"] # coinapi keys list
|
||||
TELEGRAM_TOKEN= # telegram bot token
|
||||
|
|
12
README.md
12
README.md
|
@ -10,7 +10,7 @@ https://t.me/Shirino_bot
|
|||
Вставьте в файл `.env` в формате:
|
||||
|
||||
```
|
||||
COINAPI_KEY=Токен от апи CoinAPI
|
||||
COINAPI_KEYS=["Токен от CoinAPI"]
|
||||
TELEGRAM_TOKEN=Токен Telegram-бота
|
||||
```
|
||||
|
||||
|
@ -24,3 +24,13 @@ TIMEOUT=таймаут для библиотеки requests, в секундах
|
|||
Ставьте pylint и mypy для статической проверки кода.
|
||||
Конфиги уже есть в репозитории.
|
||||
После проверок можете открывать PR.
|
||||
|
||||
## Почему энв для CoinAPI -- список?
|
||||
Можно получить несколько ключей на разные почтовые ящики
|
||||
и все ключи вписать в список:
|
||||
```
|
||||
COINAPI_KEYS=["первый", "второй", "и так далее"]
|
||||
```
|
||||
|
||||
Если вдруг один из них будет заблокирован по рейтлимиту,
|
||||
бот автоматически переключиться на следующий (token rotation).
|
||||
|
|
33
main.py
33
main.py
|
@ -31,7 +31,7 @@ class Settings(BaseSettings):
|
|||
debug: bool
|
||||
timeout: int = 2
|
||||
ndigits: int = 3
|
||||
coinapi_key: str
|
||||
coinapi_keys: List[str]
|
||||
telegram_token: str
|
||||
|
||||
class Config:
|
||||
|
@ -57,6 +57,8 @@ if settings.debug:
|
|||
# ---
|
||||
|
||||
|
||||
coinapi_len = len(settings.coinapi_keys)
|
||||
coinapi_active = [0] # API key index
|
||||
bot = Bot(token=settings.telegram_token)
|
||||
dp = Dispatcher(bot)
|
||||
|
||||
|
@ -143,8 +145,15 @@ class CurrencyConverter:
|
|||
|
||||
return True
|
||||
|
||||
def coinapi(self) -> None:
|
||||
"""Get data from CoinAPI (for cryptocurrencies)"""
|
||||
def coinapi(self, depth: int = coinapi_len) -> None:
|
||||
"""Get data from CoinAPI (for cryptocurrencies)
|
||||
|
||||
Args:
|
||||
depth (int, optional): Counter protecting from infinite recursion
|
||||
"""
|
||||
|
||||
if depth <= 0:
|
||||
raise RecursionError('Рейтлимит на всех токенах')
|
||||
|
||||
resp = requests.get(
|
||||
(
|
||||
|
@ -152,11 +161,16 @@ class CurrencyConverter:
|
|||
f'/{self.conv_currency}'
|
||||
),
|
||||
headers={
|
||||
'X-CoinAPI-Key': settings.coinapi_key,
|
||||
'X-CoinAPI-Key': settings.coinapi_keys[coinapi_active[0]],
|
||||
},
|
||||
timeout=settings.timeout,
|
||||
)
|
||||
|
||||
if resp.status_code == 429:
|
||||
log.warning('CoinAPI ratelimited, rotating token')
|
||||
rotate_token(settings.coinapi_keys, coinapi_active)
|
||||
self.coinapi(depth - 1)
|
||||
|
||||
data: Dict[str, Any] = resp.json()
|
||||
rate = data.get('rate')
|
||||
if rate is None:
|
||||
|
@ -164,6 +178,17 @@ class CurrencyConverter:
|
|||
self.conv_amount = float(rate * self.amount)
|
||||
|
||||
|
||||
def rotate_token(lst: List[str], active: List[int]) -> None:
|
||||
"""Rotates API key to prevent ratelimits
|
||||
|
||||
Args:
|
||||
lst (List[str]): Keys list
|
||||
active (List[str]): Mutable object with current key index
|
||||
"""
|
||||
|
||||
active[0] = (active[0] + 1) % len(lst)
|
||||
|
||||
|
||||
@dp.inline_handler()
|
||||
async def currency(inline_query: InlineQuery) -> None:
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue