tsf-sh 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/__init__.py +4 -0
- tests/test_client.py +745 -0
- tsf_sh/__init__.py +35 -0
- tsf_sh/client.py +342 -0
- tsf_sh/exceptions.py +62 -0
- tsf_sh/models.py +96 -0
- tsf_sh-1.0.1.dist-info/METADATA +241 -0
- tsf_sh-1.0.1.dist-info/RECORD +10 -0
- tsf_sh-1.0.1.dist-info/WHEEL +5 -0
- tsf_sh-1.0.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tsf-sh
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Асинхронная Python библиотека для работы с tsf.sh API
|
|
5
|
+
Home-page: https://tsf.sh
|
|
6
|
+
Author: Towux
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Requires-Dist: httpx>=0.24.0
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: description
|
|
23
|
+
Dynamic: description-content-type
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: requires-python
|
|
27
|
+
Dynamic: summary
|
|
28
|
+
|
|
29
|
+
# tsf-sh
|
|
30
|
+
|
|
31
|
+
Асинхронная Python библиотека для работы с [tsf.sh](https://tsf.sh) API - сервисом для сокращения ссылок.
|
|
32
|
+
|
|
33
|
+
## Установка
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install tsf-sh
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Требования
|
|
40
|
+
|
|
41
|
+
- Python 3.8+
|
|
42
|
+
- httpx 0.24.0+
|
|
43
|
+
|
|
44
|
+
## Быстрый старт
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import asyncio
|
|
48
|
+
from tsf_sh import Client
|
|
49
|
+
|
|
50
|
+
async def main():
|
|
51
|
+
# Инициализация клиента
|
|
52
|
+
client = Client(api_key="your-api-key")
|
|
53
|
+
|
|
54
|
+
# Создание короткой ссылки
|
|
55
|
+
link = await client.create_link(
|
|
56
|
+
url="https://example.com",
|
|
57
|
+
ttl_hours=24
|
|
58
|
+
)
|
|
59
|
+
print(f"Создана ссылка: {link.short_url}")
|
|
60
|
+
|
|
61
|
+
# Получение информации о ссылке
|
|
62
|
+
link_info = await client.get_link(link.code)
|
|
63
|
+
print(f"Переходов: {link_info.clicks}")
|
|
64
|
+
|
|
65
|
+
# Закрытие клиента
|
|
66
|
+
await client.close()
|
|
67
|
+
|
|
68
|
+
asyncio.run(main())
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Использование с контекстным менеджером
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import asyncio
|
|
75
|
+
from tsf_sh import Client
|
|
76
|
+
|
|
77
|
+
async def main():
|
|
78
|
+
async with Client(api_key="your-api-key") as client:
|
|
79
|
+
# Создание ссылки
|
|
80
|
+
link = await client.create_link("https://example.com")
|
|
81
|
+
print(f"Ссылка: {link.short_url}")
|
|
82
|
+
|
|
83
|
+
# Получение списка всех ссылок
|
|
84
|
+
links = await client.get_links()
|
|
85
|
+
print(f"Всего ссылок: {len(links)}")
|
|
86
|
+
|
|
87
|
+
# Получение статистики
|
|
88
|
+
stats = await client.get_stats()
|
|
89
|
+
print(f"Всего переходов: {stats.total_clicks}")
|
|
90
|
+
|
|
91
|
+
asyncio.run(main())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API методы
|
|
95
|
+
|
|
96
|
+
### Создание ссылки
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
link = await client.create_link(
|
|
100
|
+
url="https://example.com",
|
|
101
|
+
ttl_hours=24, # Время жизни в часах (1-24)
|
|
102
|
+
password="optional_password" # Опциональный пароль
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Получение списка ссылок
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
links = await client.get_links()
|
|
110
|
+
# Список отсортирован по дате создания (новые первые)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Получение информации о ссылке
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
link = await client.get_link("abc123")
|
|
117
|
+
print(f"URL: {link.original_url}")
|
|
118
|
+
print(f"Переходов: {link.clicks}")
|
|
119
|
+
print(f"Истекает: {link.expires_datetime}")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Удаление ссылки
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
await client.delete_link("abc123")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Продление времени жизни ссылки
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
link = await client.extend_link("abc123", ttl_hours=24)
|
|
132
|
+
# TTL устанавливается от текущего момента
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Установка пароля
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
await client.set_password("abc123", "my_password")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Удаление пароля
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
await client.remove_password("abc123")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Перегенерация кода ссылки
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
new_code = await client.reroll_code("abc123")
|
|
151
|
+
print(f"Новый код: {new_code}")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Получение статистики
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
stats = await client.get_stats()
|
|
158
|
+
print(f"Активных ссылок: {stats.links_count}")
|
|
159
|
+
print(f"Всего переходов: {stats.total_clicks}")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Проверка здоровья API
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
health = await client.health_check()
|
|
166
|
+
print(f"Статус: {health.status}")
|
|
167
|
+
print(f"Redis: {health.services['redis']}")
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Модели данных
|
|
171
|
+
|
|
172
|
+
### Link
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
link.code # Код ссылки
|
|
176
|
+
link.short_url # Короткая ссылка
|
|
177
|
+
link.original_url # Оригинальный URL
|
|
178
|
+
link.clicks # Количество переходов
|
|
179
|
+
link.ttl_seconds # Время жизни в секундах
|
|
180
|
+
link.created_at # Unix timestamp создания
|
|
181
|
+
link.expires_at # Unix timestamp истечения
|
|
182
|
+
link.has_password # Наличие пароля
|
|
183
|
+
link.created_datetime # datetime объект для created_at
|
|
184
|
+
link.expires_datetime # datetime объект для expires_at
|
|
185
|
+
link.is_expired # Проверка истечения
|
|
186
|
+
link.remaining_seconds # Оставшееся время жизни
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### LinkStats
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
stats.links_count # Количество активных ссылок
|
|
193
|
+
stats.total_clicks # Всего переходов
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### HealthStatus
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
health.status # "healthy" или "degraded"
|
|
200
|
+
health.services # Словарь со статусами сервисов
|
|
201
|
+
health.is_healthy # True если API здоров
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Обработка ошибок
|
|
205
|
+
|
|
206
|
+
Библиотека выбрасывает специфичные исключения для разных типов ошибок:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from tsf_sh import (
|
|
210
|
+
ValidationError, # 400 - Ошибка валидации
|
|
211
|
+
UnauthorizedError, # 401 - Неверный API ключ
|
|
212
|
+
ForbiddenError, # 403 - Требуется премиум
|
|
213
|
+
NotFoundError, # 404 - Ресурс не найден
|
|
214
|
+
ConflictError, # 409 - Конфликт (ссылка уже существует)
|
|
215
|
+
RateLimitError, # 429 - Превышен лимит запросов
|
|
216
|
+
InternalServerError # 500 - Внутренняя ошибка сервера
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
link = await client.create_link("invalid-url")
|
|
221
|
+
except ValidationError as e:
|
|
222
|
+
print(f"Ошибка валидации: {e.message}")
|
|
223
|
+
except ConflictError as e:
|
|
224
|
+
print(f"Ссылка уже существует: {e.existing_code}")
|
|
225
|
+
except RateLimitError as e:
|
|
226
|
+
print(f"Лимит превышен. Попробуйте через {e.reset_time} секунд")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Получение API ключа
|
|
230
|
+
|
|
231
|
+
API ключ можно получить в Telegram боте [@tsf_sh_bot](https://t.me/tsf_sh_bot) в разделе профиля, но только после покупки премиума. Премиум покупается навсегда.
|
|
232
|
+
|
|
233
|
+
## Лицензия
|
|
234
|
+
|
|
235
|
+
MIT
|
|
236
|
+
|
|
237
|
+
## Ссылки
|
|
238
|
+
|
|
239
|
+
- [Документация API](https://tsf.sh/api/docs)
|
|
240
|
+
- [Telegram бот](https://t.me/tsf_sh_bot)
|
|
241
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
tests/__init__.py,sha256=SsNyijrCMUFgNu0GcJr1MAzRn0hxMd7eYjeYwiVHc_I,59
|
|
2
|
+
tests/test_client.py,sha256=tLbyXAYCS7dqEpihCJdVjSqxySilM2Zj_5XVqN-4OIs,26439
|
|
3
|
+
tsf_sh/__init__.py,sha256=CASxuiCk2ibcsjkPt21Wk8wXqo4zF8wbf1IioX7gDHc,670
|
|
4
|
+
tsf_sh/client.py,sha256=ZRApcPiY6KZbjQlrdSyF6gIi08xsCKsTG3WxUSPCjvA,12550
|
|
5
|
+
tsf_sh/exceptions.py,sha256=pY9yABA2kXL_Zn8OsHc4F3hy_L3HS_KckF3I0MiFp-c,2186
|
|
6
|
+
tsf_sh/models.py,sha256=ZkUb_4dM6jlMHQulKkcxR4c-4KwwGZgNCo1_p9HEgBk,2742
|
|
7
|
+
tsf_sh-1.0.1.dist-info/METADATA,sha256=fNnB3H0cccoj-axOFgEwr3ZWVJs-GmKCPwR7GD20lgA,7319
|
|
8
|
+
tsf_sh-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
tsf_sh-1.0.1.dist-info/top_level.txt,sha256=JcscsZMfZac3ie7Dd8z-N1wHhuZx3YjdJTJDPsresJs,13
|
|
10
|
+
tsf_sh-1.0.1.dist-info/RECORD,,
|