Metadata-Version: 2.5
Name: monokeys
Version: 0.2.0
Summary: Клиент «Ключей»: маленькие умные функции одним вызовом, без зависимостей
Project-URL: Homepage, https://monoblock.casa/keys/
Project-URL: Documentation, https://monoblock.casa/keys/client
Project-URL: Repository, https://github.com/monorez3/keys
Author: Monoblock
License: MIT
Keywords: api,keys,telegram,utilities
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# monokeys

Клиент «Ключей» — маленьких умных функций, которые зовутся одним вызовом.
Зависимостей нет: внутри только стандартная библиотека, один файл.

```bash
pip install monokeys
```

```python
from monokeys import Keys

k = Keys()                      # ничего настраивать не надо
res = k.alive("@durov")

print(res.is_alive)             # True
print(res.title)                # Pavel Durov
```

## Ключ доступа заводить не нужно

Мы сделали работу за вас: публичный ключ работает у всех, **без счётчика и без
срока**. Клиент берёт его сам, поэтому `Keys()` работает сразу — ни
регистрации, ни настройки.

```python
from monokeys import Keys
print(Keys().alive.text("@durov"))   # и всё, больше ничего не нужно
```

Свой ключ нужен только тем, кто хочет собственный рубильник: его выдаёт
владелец сервиса, он тоже бессрочный и без счётчика. Положите его в `.env`:

```
KEYS_API_KEY=kx_...
```

Отозвать свой ключ, если он утёк:

```bash
curl -X POST -H "Authorization: Bearer kx_..." https://АДРЕС/token/revoke
```

## Три способа позвать ключ

```python
k.alive("@durov")                    # весь ответ: объект с полями
k.alive.members_count("@durov")      # только одно поле, уже числом
k.alive.text("@durov")               # строка для человека
```

```
жив · channel · Pavel Durov · 11 005 185 subscribers
```

## Аргументы

### `Keys(...)` — подключение

| Аргумент | По умолчанию | Что делает |
| --- | --- | --- |
| `token` | `KEYS_API_KEY`, иначе публичный ключ с сервера | ключ доступа; передаётся только заголовком |
| `base` | адрес, откуда скачан клиент | адрес сервера |
| `timeout` | `20.0` | сколько ждать ответа, секунд |
| `retries` | `1` | повторов при обрыве связи (отказ сервера не повторяется) |
| `user_agent` | `monokeys/<версия>` | как представляться серверу |

```python
k = Keys(token="kx_...", base="https://АДРЕС", timeout=5, retries=2)
```

### `k.<ключ>(...)` — вызов

| Аргумент | По умолчанию | Что делает |
| --- | --- | --- |
| `value` | — | главное значение: для `alive` это ссылка, `@username` или `+hash` |
| `only` | `""` | вернуть только это поле вместо всего ответа |
| `fmt` | `"json"` | `json` — поля, `text` — строка для человека, `bool` — да/нет |
| `timeout` | как у клиента | переопределить ожидание для одного вызова |
| `**params` | — | остальные параметры ключа по именам |

```python
k.alive("@durov", only="members_count")   # 11005185
k.alive("@durov", fmt="bool")             # 'true'
k.alive("@durov", timeout=3)              # не ждать дольше трёх секунд
```

### Что можно спросить у клиента

| Вызов | Что вернёт |
| --- | --- |
| `k.names()` | имена всех доступных ключей |
| `k.fields("alive")` | какие поля возвращает ключ |
| `k.alive.fields()` | то же самое, короче |
| `k.catalog(refresh=True)` | полный каталог с описаниями, спросить заново |
| `k.call("alive", "@durov")` | позвать ключ, имя которого известно только в рантайме |

## Ответ

`Answer` — это словарь, который умеет отвечать и как объект:

```python
res = k.alive("@durov")
res.title == res["title"]     # одно и то же
bool(res)                     # True, если ключ ответил утвердительно
dict(res)                     # обычный словарь
```

Опечатка в имени поля не молчит:

```python
res.tittle
# AttributeError: в ответе нет поля 'tittle'; есть: username, url, is_alive, ...

k.alive.members_cout("@durov")
# AttributeError: у ключа 'alive' нет поля 'members_cout'; есть: is_alive, kind, ...
```

## Ошибки

| Исключение | Когда |
| --- | --- |
| `AccessDenied` | ключ неизвестен, отозван или отправлен не по HTTPS |
| `Unavailable` | сервер занят или источник не ответил — осмысленно повторить |
| `KeysError` | всё остальное: нет такого ключа, мусор на входе |

У всех трёх есть `.status` (код ответа) и `.body` (что сказал сервер).
`AccessDenied` и `Unavailable` — потомки `KeysError`, так что можно ловить
одним `except KeysError`.

```python
from monokeys import Keys, AccessDenied, Unavailable

try:
    res = k.alive("@durov")
except AccessDenied:
    print("ключ доступа не подошёл — попросите новый у владельца")
except Unavailable:
    print("сейчас занято, попробую позже")
```

## Методы не зашиты в клиент

Список ключей и их полей приходит с сервера. Появился новый ключ — он
доступен сразу, без обновления пакета:

```python
k.names()          # ['alive', ...]
k.несуществующий   # AttributeError со списком существующих
```

## Если ставить пакет не хочется

Тот же самый файл можно просто скачать — это буквально один исходник, из
которого собран пакет:

```bash
curl https://АДРЕС/sdk/python > monokeys.py
```

А можно вообще без клиента — ключ это обычная ссылка:

```
https://АДРЕС/alive/@durov  ->  жив · channel · Pavel Durov · ...
```
