chore: update version; move scripts into examples folder
This commit is contained in:
@@ -2,62 +2,6 @@
|
||||
|
||||
Эта папка содержит примеры использования ITD SDK для различных сценариев.
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
examples/
|
||||
├── README.md # Этот файл
|
||||
└── stream/ # Примеры работы с SSE потоком уведомлений
|
||||
├── basic_stream.py
|
||||
├── stop_stream.py
|
||||
├── filter_notifications.py
|
||||
└── notification_logger.py
|
||||
```
|
||||
|
||||
## Подготовка
|
||||
|
||||
Перед запуском примеров установите зависимости:
|
||||
|
||||
```bash
|
||||
pip install -r ../requirements.txt
|
||||
```
|
||||
|
||||
## Получение cookies
|
||||
|
||||
Все примеры требуют cookies с `refresh_token`. Как их получить:
|
||||
|
||||
1. Откройте [итд.com](https://xn--d1ah4a.com) в браузере
|
||||
2. Откройте DevTools (F12)
|
||||
3. Перейдите на вкладку **Network**
|
||||
4. Найдите запрос к `/auth/refresh`
|
||||
5. Скопируйте значение **Cookie** из Request Headers
|
||||
6. Формат: `refresh_token=...; __ddg1_=...; is_auth=1`
|
||||
|
||||
См. `cookie-screen.png` в корне проекта для примера.
|
||||
|
||||
---
|
||||
|
||||
## Stream - Прослушивание уведомлений
|
||||
|
||||
Примеры работы с SSE потоком уведомлений в реальном времени.
|
||||
|
||||
📁 **Папка:** `stream/`
|
||||
📖 **Документация:** [stream/README.md](stream/README.md)
|
||||
|
||||
**Примеры:**
|
||||
- `basic_stream.py` - Базовое прослушивание всех уведомлений
|
||||
- `stop_stream.py` - Программная остановка потока
|
||||
- `filter_notifications.py` - Фильтрация по типу уведомлений
|
||||
- `notification_logger.py` - Логирование в JSON файл
|
||||
|
||||
**Быстрый старт:**
|
||||
```bash
|
||||
cd stream
|
||||
python basic_stream.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Дополнительная информация
|
||||
|
||||
- [Основной README](../README.md) - Документация по всему SDK
|
||||
|
||||
7
examples/kilyabin/README.md
Normal file
7
examples/kilyabin/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Коллекция скриптов от [@kilyabin](https://github.com/kilyabin)
|
||||
|
||||
Пока всего два скрипта, однако будет дополняться
|
||||
|
||||
Работают через аргументы командной строки (например, `--file` или `--text`)
|
||||
|
||||
Есть помощь при аргументе `-h`, потому - разберетесь
|
||||
56
examples/kilyabin/itd-change-banner.py
Normal file
56
examples/kilyabin/itd-change-banner.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
from argparse import ArgumentParser
|
||||
from os import getenv
|
||||
from os.path import isfile
|
||||
import sys
|
||||
|
||||
from itd import ITDClient
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(
|
||||
description='Upload image and set it as profile banner'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--token',
|
||||
default=getenv('ITD_TOKEN'),
|
||||
help='API token (or ITD_TOKEN env var)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--file',
|
||||
required=True,
|
||||
help='Path to image file'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.token:
|
||||
print('❌ Токен не задан (--token или ITD_TOKEN)', file=sys.stderr)
|
||||
quit()
|
||||
|
||||
file_path = args.file
|
||||
|
||||
if not isfile(file_path):
|
||||
print(f'❌ Файл не найден: {file_path}', file=sys.stderr)
|
||||
quit()
|
||||
|
||||
try:
|
||||
client = ITDClient(None, args.token)
|
||||
data, _ = client.update_banner_new(file_path)
|
||||
|
||||
print('✅ Баннер обновлён!')
|
||||
print('📄 Информация о файле:')
|
||||
print(f' id: {data.id}')
|
||||
print(f' filename: {data.filename}')
|
||||
print(f' mime_type: {data.mime_type}')
|
||||
print(f' size: {data.size} bytes')
|
||||
print(f' url: {data.url}')
|
||||
|
||||
except Exception as e:
|
||||
print('❌ Произошла ошибка:', e, file=sys.stderr)
|
||||
quit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
78
examples/kilyabin/itd-create-post.py
Normal file
78
examples/kilyabin/itd-create-post.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
from uuid import UUID
|
||||
from argparse import ArgumentParser
|
||||
from os import getenv
|
||||
from os.path import isfile, basename
|
||||
|
||||
from itd import ITDClient
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(
|
||||
description='Create a post on ITD via CLI'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--token',
|
||||
default=getenv('ITD_TOKEN'),
|
||||
help='Refresh token (or set ITD_TOKEN environment variable)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--text',
|
||||
required=True,
|
||||
help='Text content of the post'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--file',
|
||||
help='Optional file to attach to the post'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--filename',
|
||||
help='Filename on server (if --file is used, default: local filename)'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.token:
|
||||
print('❌ Token not provided (--token or ITD_TOKEN)')
|
||||
quit()
|
||||
|
||||
try:
|
||||
client = ITDClient(None, args.token)
|
||||
|
||||
file_id = None
|
||||
if args.file:
|
||||
if not isfile(args.file):
|
||||
print(f'❌ File not found: {args.file}')
|
||||
quit()
|
||||
|
||||
server_name = args.filename or basename(args.file)
|
||||
with open(args.file, 'rb') as f:
|
||||
response = client.upload_file(server_name, f)
|
||||
|
||||
file_id = str(getattr(response, 'id', None))
|
||||
if not file_id:
|
||||
print('❌ Failed to get file ID')
|
||||
quit()
|
||||
print(f'✅ File uploaded: {response.filename} (id={file_id})')
|
||||
|
||||
# Создаём пост с правильным аргументом 'content'
|
||||
if file_id:
|
||||
post_resp = client.create_post(content=args.text, attach_ids=[UUID(file_id)])
|
||||
else:
|
||||
post_resp = client.create_post(content=args.text)
|
||||
|
||||
print('✅ Post created successfully!')
|
||||
print(f' id: {post_resp.id}')
|
||||
print(f' text: {args.text}')
|
||||
if file_id:
|
||||
print(f' attached file id: {file_id}')
|
||||
|
||||
except Exception as e:
|
||||
print('❌ Error:', e)
|
||||
quit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -5,20 +5,20 @@ import sys
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from itd import ITDClient, StreamConnect, StreamNotification
|
||||
from itd import ITDClient, StreamConnect
|
||||
|
||||
def main():
|
||||
cookies = 'YOUR_COOKIES_HERE'
|
||||
|
||||
|
||||
if cookies == 'YOUR_COOKIES_HERE':
|
||||
print('! Укажите cookies в переменной cookies')
|
||||
print(' См. examples/README.md для инструкций')
|
||||
return
|
||||
|
||||
|
||||
client = ITDClient(cookies=cookies)
|
||||
|
||||
|
||||
print('-- Подключение к SSE...')
|
||||
|
||||
|
||||
try:
|
||||
for event in client.stream_notifications():
|
||||
if isinstance(event, StreamConnect):
|
||||
@@ -29,7 +29,7 @@ def main():
|
||||
if event.preview:
|
||||
preview = event.preview[:50] + '...' if len(event.preview) > 50 else event.preview
|
||||
print(f' {preview}')
|
||||
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print(f'\n! Отключение...')
|
||||
|
||||
|
||||
@@ -5,48 +5,47 @@ import sys
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from itd import ITDClient, StreamConnect, StreamNotification
|
||||
from itd import ITDClient, StreamConnect
|
||||
from itd.enums import NotificationType
|
||||
|
||||
def main():
|
||||
cookies = 'YOUR_COOKIES_HERE'
|
||||
|
||||
|
||||
if cookies == 'YOUR_COOKIES_HERE':
|
||||
print('! Укажите cookies в переменной cookies')
|
||||
print(' См. examples/README.md для инструкций')
|
||||
return
|
||||
|
||||
|
||||
client = ITDClient(cookies=cookies)
|
||||
|
||||
# Настройка: какие типы уведомлений показывать
|
||||
|
||||
SHOW_TYPES = {
|
||||
NotificationType.LIKE,
|
||||
NotificationType.FOLLOW,
|
||||
NotificationType.COMMENT,
|
||||
NotificationType.COMMENT
|
||||
}
|
||||
|
||||
|
||||
print('-- Подключение к SSE...')
|
||||
print(f'-- Фильтр: {", ".join(t.value for t in SHOW_TYPES)}\n')
|
||||
|
||||
|
||||
try:
|
||||
for event in client.stream_notifications():
|
||||
if isinstance(event, StreamConnect):
|
||||
print(f'✅ Подключено! User ID: {event.user_id}\n')
|
||||
continue
|
||||
|
||||
|
||||
if event.type not in SHOW_TYPES:
|
||||
continue
|
||||
|
||||
|
||||
# Обработка разных типов
|
||||
if event.type == NotificationType.LIKE:
|
||||
print(f'❤️ {event.actor.display_name} лайкнул ваш пост')
|
||||
|
||||
|
||||
elif event.type == NotificationType.FOLLOW:
|
||||
print(f'👤 {event.actor.display_name} подписался на вас')
|
||||
|
||||
|
||||
elif event.type == NotificationType.COMMENT:
|
||||
print(f'💬 {event.actor.display_name}: {event.preview}')
|
||||
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print(f'\n! Отключение...')
|
||||
|
||||
|
||||
@@ -5,29 +5,29 @@ import sys
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from itd import ITDClient, StreamConnect, StreamNotification
|
||||
from itd import ITDClient, StreamConnect
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
def main():
|
||||
cookies = 'YOUR_COOKIES_HERE'
|
||||
|
||||
|
||||
if cookies == 'YOUR_COOKIES_HERE':
|
||||
print('! Укажите cookies в переменной cookies')
|
||||
print(' См. examples/README.md для инструкций')
|
||||
return
|
||||
|
||||
|
||||
client = ITDClient(cookies=cookies)
|
||||
log_file = f'notifications_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'
|
||||
|
||||
|
||||
print(f'-- Подключение к SSE...')
|
||||
print(f'-- Логирование в: {log_file}\n')
|
||||
|
||||
|
||||
try:
|
||||
with open(log_file, 'w', encoding='utf-8') as f:
|
||||
for event in client.stream_notifications():
|
||||
timestamp = datetime.now().isoformat()
|
||||
|
||||
|
||||
if isinstance(event, StreamConnect):
|
||||
log_entry = {
|
||||
'timestamp': timestamp,
|
||||
@@ -49,10 +49,10 @@ def main():
|
||||
'target_id': str(event.target_id) if event.target_id else None
|
||||
}
|
||||
print(f'* {event.type.value}: {event.actor.username}')
|
||||
|
||||
|
||||
f.write(json.dumps(log_entry, ensure_ascii=False) + '\n')
|
||||
f.flush()
|
||||
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print(f'\n! Отключение... Лог сохранен в {log_file}')
|
||||
|
||||
|
||||
@@ -6,19 +6,17 @@ from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
import threading
|
||||
import time
|
||||
from itd import ITDClient, StreamConnect, StreamNotification
|
||||
from itd import ITDClient, StreamConnect
|
||||
|
||||
def main():
|
||||
cookies = 'YOUR_COOKIES_HERE'
|
||||
|
||||
cookies = 'YOUR_COOKIES_HERE'
|
||||
|
||||
if cookies == 'YOUR_COOKIES_HERE':
|
||||
print('! Укажите cookies в переменной cookies')
|
||||
return
|
||||
|
||||
|
||||
client = ITDClient(cookies=cookies)
|
||||
|
||||
# Функция для прослушивания в отдельном потоке
|
||||
|
||||
def listen():
|
||||
print('! Начинаем прослушивание...')
|
||||
try:
|
||||
@@ -29,17 +27,16 @@ def main():
|
||||
print(f'🔔 {event.type.value}: {event.actor.username}')
|
||||
except Exception as e:
|
||||
print(f'! Ошибка: {e}')
|
||||
|
||||
# В отдельном потоке
|
||||
|
||||
thread = threading.Thread(target=listen, daemon=True)
|
||||
thread.start()
|
||||
|
||||
|
||||
print('Прослушивание запущено. Нажмите Enter для остановки...')
|
||||
input()
|
||||
|
||||
|
||||
print('!! Останавливаем прослушивание...')
|
||||
client.stop_stream()
|
||||
|
||||
|
||||
thread.join(timeout=5)
|
||||
print('! Остановлено')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user