7 changed files with 716 additions and 224 deletions
@ -0,0 +1,11 @@ |
|||
# Ignore pycache |
|||
|
|||
__pycache__ |
|||
|
|||
# Ignore dist |
|||
|
|||
/dist |
|||
|
|||
# Ignore pyproject |
|||
|
|||
pyproject.toml |
@ -1,224 +0,0 @@ |
|||
import requests |
|||
import json |
|||
from flask import request |
|||
from websocket import create_connection |
|||
import socketio |
|||
|
|||
|
|||
class Scopes: |
|||
"""Удобный класс, для простого указания прав в приложении""" |
|||
|
|||
USER_SHOW = "oauth-user-show" |
|||
|
|||
DONATION_SUBSCRIBE = "oauth-donation-subscribe" |
|||
DONATION_INDEX = "oauth-donation-index" |
|||
|
|||
CUSTOM_ALERT_STORE = "oauth-custom_alert-store" |
|||
|
|||
GOAL_SUBSCRIBE = "oauth-goal-subscribe" |
|||
POLL_SUBSCRIBE = "oauth-poll-subscribe" |
|||
|
|||
ALL_SCOPES = [USER_SHOW, DONATION_INDEX, DONATION_SUBSCRIBE, CUSTOM_ALERT_STORE, |
|||
GOAL_SUBSCRIBE, POLL_SUBSCRIBE] |
|||
|
|||
|
|||
class Channels: |
|||
"""Права для подписки на каналы Centrifugo""" |
|||
|
|||
NEW_DONATION_ALERTS = "$alerts:donation_" |
|||
|
|||
DONATION_GOALS_UPDATES = "$goals:goal_" |
|||
|
|||
POLLS_UPDATES = "$polls:poll_" |
|||
|
|||
ALL_CHANNELS = [NEW_DONATION_ALERTS, DONATION_GOALS_UPDATES, POLLS_UPDATES] |
|||
|
|||
|
|||
class DonationAlertsApi: |
|||
"""Основной класс для работы с DA API""" |
|||
|
|||
def __init__(self, client_id, client_secret, redirect_uri, scopes): |
|||
symbols = [",", ", ", " ", "%20"] |
|||
|
|||
if isinstance(scopes, list): |
|||
obj_scopes = [] |
|||
for scope in scopes: |
|||
obj_scopes.append(scope) |
|||
|
|||
scopes = " ".join(obj_scopes) |
|||
|
|||
for symbol in symbols: |
|||
if symbol in scopes: |
|||
self.scope = scopes.replace(symbol, "%20").strip() # Replaces some symbols on '%20' for stable work |
|||
else: |
|||
self.scope = scopes |
|||
|
|||
self.client_id = client_id |
|||
self.client_secret = client_secret |
|||
self.redirect_uri = redirect_uri |
|||
self.login_url = f"https://www.donationalerts.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&scope={self.scope}" |
|||
self.token_url = f"https://www.donationalerts.com/oauth/token" |
|||
|
|||
# API LINKS |
|||
self.user_api = "https://www.donationalerts.com/api/v1/user/oauth" |
|||
self.donations_api = "https://www.donationalerts.com/api/v1/alerts/donations" |
|||
self.custom_alerts_api = "https://www.donationalerts.com/api/v1/custom_alert" |
|||
|
|||
def login(self): |
|||
return self.login_url |
|||
|
|||
def get_code(self): |
|||
return request.args.get("code") # Получаем аргмент "code" из адресной строки |
|||
|
|||
def get_access_token(self, code, full=False): |
|||
""" Параметр full=False |
|||
|
|||
Если True, то выводит весь json объект, а не только access_token |
|||
|
|||
""" |
|||
|
|||
payload = { |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"grant_type": "authorization_code", |
|||
"code": code, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
access_token = requests.post(url=self.token_url, data=payload).json() |
|||
self.refresh_token = access_token.get("refresh_token") |
|||
|
|||
return access_token if full else access_token.get("access_token") |
|||
|
|||
def get_donations(self, access_token): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
donate_object = requests.get(url=self.donations_api, headers=headers).json() |
|||
|
|||
return donate_object |
|||
|
|||
def get_user(self, access_token): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
user_object = requests.get(url=self.user_api, headers=headers).json() |
|||
|
|||
return user_object["data"] |
|||
|
|||
def send_custom_alert(self, access_token, external_id, headline, message, image_url=None, sound_url=None, is_shown=0): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
data = { |
|||
"external_id": external_id, |
|||
"header": headline, |
|||
"message": message, |
|||
"is_shown": is_shown, |
|||
"image_url": image_url, |
|||
"sound_url": sound_url |
|||
} |
|||
custom_alert_object = requests.post(url=self.custom_alerts_api, data=data, headers=headers).json() |
|||
|
|||
return custom_alert_object |
|||
|
|||
def get_refresh_token(self): |
|||
headers = {"Content-Type": "application/x-www-form-urlencoded"} |
|||
data = { |
|||
"grant_type": "refresh_token", |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"refresh_token": self.refresh_token, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
response = requests.post(url=self.token_url, data=data, headers=headers).json() |
|||
return response |
|||
|
|||
|
|||
class Centrifugo: |
|||
"""Получение событий в реальном времени (Oauth2)""" |
|||
|
|||
def __init__(self, socket_connection_token, access_token, user_id): |
|||
self.socket_connection_token = socket_connection_token |
|||
self.access_token = access_token |
|||
self.user_id = user_id |
|||
|
|||
self.uri = "wss://centrifugo.donationalerts.com/connection/websocket" |
|||
|
|||
def connect(self): |
|||
self.ws = create_connection(self.uri) # Подключаемся к серверу |
|||
self.ws.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"token": self.socket_connection_token |
|||
}, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
self.ws_response = json.loads(self.ws.recv()) |
|||
|
|||
return self.ws_response |
|||
|
|||
def subscribe(self, channels): |
|||
chnls = [f"{channels}{self.user_id}"] |
|||
|
|||
if isinstance(channels, list): |
|||
chnls = [] |
|||
for channel in channels: |
|||
chnls.append(f"{channel}{self.user_id}") |
|||
|
|||
headers = { |
|||
"Authorization": f"Bearer {self.access_token}", |
|||
"Content-Type": "application/json" |
|||
} |
|||
data = { |
|||
"channels": chnls, |
|||
"client": self.ws_response["result"]["client"] |
|||
} |
|||
|
|||
response = requests.post(url="https://www.donationalerts.com/api/v1/centrifuge/subscribe", data=json.dumps(data), headers=headers).json() |
|||
for ch in response["channels"]: |
|||
self.ws.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"channel": ch["channel"], |
|||
"token": ch["token"] |
|||
}, |
|||
"method": 1, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
|
|||
answer = {"response": self.ws.recv(), "sec_response": self.ws.recv()} |
|||
return answer # Возвращаем первые два ответа от сервера |
|||
|
|||
def listen(self): |
|||
return json.loads(self.ws.recv())["result"]["data"]["data"] # Возвращаем 3-й ответ от сервера |
|||
|
|||
sio = socketio.Client() |
|||
|
|||
|
|||
class Alert: |
|||
"""Получение донатов в реальном времени без Oauth2""" |
|||
|
|||
def __init__(self, token): |
|||
self.token = token # TOKEN можно скопировать здесь - https://www.donationalerts.com/dashboard/general |
|||
|
|||
def event(self): |
|||
def wrapper(function): |
|||
@sio.on("connect") |
|||
def on_connect(): |
|||
sio.emit("add-user", {"token": self.token, "type": "alert_widget"}) |
|||
|
|||
@sio.on("donation") |
|||
def on_message(data): |
|||
function(json.loads(data)) # Отправляем полученные данные в функцию |
|||
|
|||
sio.connect("wss://socket.donationalerts.ru:443", transports="websocket") |
|||
return wrapper |
@ -0,0 +1,2 @@ |
|||
from .utils import * |
|||
from .donationalerts_api import * |
@ -0,0 +1,300 @@ |
|||
import json |
|||
|
|||
import asyncio |
|||
import socketio |
|||
import aiohttp |
|||
import websockets |
|||
|
|||
from .utils import Event, User, Data, Donations, DonationsData, CentrifugoResponse |
|||
|
|||
DEFAULT_URL = "https://www.donationalerts.com/oauth/" |
|||
DEFAULT_API_LINK = "https://www.donationalerts.com/api/v1/" |
|||
|
|||
|
|||
class DonationAlertsApi: |
|||
|
|||
def __init__(self, client_id, client_secret, redirect_uri, scopes): |
|||
symbols = [",", ", ", " ", "%20"] |
|||
|
|||
if isinstance(scopes, list): |
|||
obj_scopes = [] |
|||
for scope in scopes: |
|||
obj_scopes.append(scope) |
|||
|
|||
scopes = " ".join(obj_scopes) |
|||
|
|||
for symbol in symbols: |
|||
if symbol in scopes: |
|||
self.scope = scopes.replace(symbol, "%20").strip() # Replaces some symbols on '%20' for stable work |
|||
else: |
|||
self.scope = scopes |
|||
|
|||
self.client_id = client_id |
|||
self.client_secret = client_secret |
|||
self.redirect_uri = redirect_uri |
|||
|
|||
def login(self): |
|||
return f"{DEFAULT_URL}authorize?client_id={self.client_id}&redirect_uri={self.redirect_uri}&response_type=code&scope={self.scope}" |
|||
|
|||
async def get_access_token(self, code, *, full_json=False): |
|||
payload = { |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"grant_type": "authorization_code", |
|||
"code": code, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.post(f"{DEFAULT_URL}token", data=payload) as response: |
|||
obj = await response.json() |
|||
|
|||
return Data( |
|||
obj["access_token"], |
|||
obj["expires_in"], |
|||
obj["refresh_token"], |
|||
obj["token_type"], |
|||
obj |
|||
) if full_json else obj["access_token"] |
|||
|
|||
async def donations_list(self, access_token, *, current_page: int=1, from_page: int=1, last_page: int=13, per_page: int=30, to: int=30, total: int=385): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
|
|||
"""Pagination in development""" |
|||
meta = { |
|||
"current_page": current_page, |
|||
"from": from_page, |
|||
"last_page": last_page, |
|||
"path": f"{DEFAULT_API_LINK}alerts/donations", |
|||
"per_page": per_page, |
|||
"to": to, |
|||
"total": total |
|||
} |
|||
links = { |
|||
"first": f"{DEFAULT_API_LINK}alerts/donations?page={from_page}", |
|||
"last": f"{DEFAULT_API_LINK}alerts/donations?page={last_page}", |
|||
"last": f"{DEFAULT_API_LINK}alerts/donations?page={last_page}", |
|||
"next": f"{DEFAULT_API_LINK}alerts/donations?page={current_page + 1}", |
|||
"prev": None |
|||
} |
|||
|
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.get(f"{DEFAULT_API_LINK}alerts/donations", headers=headers) as response: |
|||
objs = await response.json() |
|||
donations = Donations(objects=objs["data"]) |
|||
|
|||
for obj in objs["data"]: |
|||
donation_object = DonationsData( |
|||
obj["amount"], |
|||
obj["amount_in_user_currency"], |
|||
obj["created_at"], |
|||
obj["currency"], |
|||
obj["id"], |
|||
obj["is_shown"], |
|||
obj["message"], |
|||
obj["message_type"], |
|||
obj["name"], |
|||
obj["payin_system"], |
|||
obj["recipient_name"], |
|||
obj["shown_at"], |
|||
obj["username"] |
|||
) |
|||
donations.donation.append(donation_object) |
|||
|
|||
return donations |
|||
|
|||
async def user(self, access_token): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
|
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.get(f"{DEFAULT_API_LINK}user/oauth", headers=headers) as response: |
|||
obj = await response.json() |
|||
|
|||
return User( |
|||
obj["data"]["avatar"], |
|||
obj["data"]["code"], |
|||
obj["data"]["email"], |
|||
obj["data"]["id"], |
|||
obj["data"]["language"], |
|||
obj["data"]["name"], |
|||
obj["data"]["socket_connection_token"], |
|||
obj["data"] |
|||
) |
|||
|
|||
async def send_custom_alert(self, access_token, external_id, headline, message, *, image_url=None, sound_url=None, is_shown=0): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
payload = { |
|||
"external_id": external_id, |
|||
"headline": headline, |
|||
"message": message, |
|||
"is_shown": is_shown, |
|||
"image_url": image_url, |
|||
"sound_url": sound_url |
|||
} |
|||
|
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.post(f"{DEFAULT_API_LINK}custom_alert", data=payload, headers=headers) as response: |
|||
return await response.json() |
|||
|
|||
async def get_refresh_token(self, access_token, refresh_token): |
|||
headers = { |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
payload = { |
|||
"grant_type": "refresh_token", |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"refresh_token": refresh_token, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.post(f"{DEFAULT_URL}token", data=payload, headers=headers) as response: |
|||
obj = await response.json() |
|||
|
|||
return Data( |
|||
obj["access_token"], |
|||
obj["expires_in"], |
|||
obj["refresh_token"], |
|||
obj["token_type"], |
|||
obj |
|||
) |
|||
|
|||
|
|||
class Centrifugo: |
|||
|
|||
def __init__(self, socket_connection_token, access_token, user_id): |
|||
self.socket_connection_token = socket_connection_token |
|||
self.access_token = access_token |
|||
self.user_id = user_id |
|||
|
|||
async def subscribe(self, channels): |
|||
chnls = [f"{channels}{self.user_id}"] |
|||
if isinstance(channels, list): |
|||
chnls = [] |
|||
for channel in channels: |
|||
chnls.append(f"{channel}{self.user_id}") |
|||
|
|||
async with websockets.connect("wss://centrifugo.donationalerts.com/connection/websocket") as websocket: |
|||
await websocket.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"token": self.socket_connection_token |
|||
}, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
|
|||
websocket_response = json.loads(await websocket.recv()) |
|||
|
|||
headers = { |
|||
"Authorization": f"Bearer {self.access_token}", |
|||
"Content-Type": "application/json" |
|||
} |
|||
data = { |
|||
"channels": chnls, |
|||
"client": websocket_response["result"]["client"] |
|||
} |
|||
|
|||
async with aiohttp.ClientSession(headers=headers) as session: |
|||
async with session.post(f"{DEFAULT_API_LINK}centrifuge/subscribe", data=json.dumps(data)) as response: |
|||
response = await response.json() |
|||
|
|||
for ch in response["channels"]: |
|||
await websocket.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"channel": ch["channel"], |
|||
"token": ch["token"] |
|||
}, |
|||
"method": 1, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
|
|||
await websocket.recv() |
|||
await websocket.recv() |
|||
|
|||
obj = json.loads(await websocket.recv())["result"]["data"]["data"] |
|||
return CentrifugoResponse( |
|||
obj["amount"], |
|||
obj["amount_in_user_currency"], |
|||
obj["created_at"], |
|||
obj["currency"], |
|||
obj["id"], |
|||
obj["is_shown"], |
|||
obj["message"], |
|||
obj["message_type"], |
|||
obj["name"], |
|||
obj["payin_system"], |
|||
obj["recipient_name"], |
|||
obj["shown_at"], |
|||
obj["username"], |
|||
obj["reason"], |
|||
obj |
|||
) |
|||
|
|||
|
|||
sio = socketio.AsyncClient() |
|||
|
|||
|
|||
class Alert: |
|||
|
|||
def __init__(self, token): |
|||
self.token = token |
|||
|
|||
def event(self): |
|||
def decorate(function): |
|||
async def wrapper(): |
|||
|
|||
@sio.on("connect") |
|||
async def on_connect(): |
|||
await sio.emit("add-user", {"token": self.token, "type": "alert_widget"}) |
|||
|
|||
@sio.on("donation") |
|||
async def on_message(data): |
|||
data = json.loads(data) |
|||
|
|||
await function( |
|||
Event( |
|||
data["id"], |
|||
data["alert_type"], |
|||
data["is_shown"], |
|||
json.loads(data["additional_data"]), |
|||
data["billing_system"], |
|||
data["billing_system_type"], |
|||
data["username"], |
|||
data["amount"], |
|||
data["amount_formatted"], |
|||
data["amount_main"], |
|||
data["currency"], |
|||
data["message"], |
|||
data["header"], |
|||
data["date_created"], |
|||
data["emotes"], |
|||
data["ap_id"], |
|||
data["_is_test_alert"], |
|||
data["message_type"], |
|||
data["preset_id"], |
|||
data |
|||
) |
|||
) |
|||
|
|||
await sio.connect("wss://socket.donationalerts.ru:443", transports="websocket") |
|||
|
|||
loop = asyncio.get_event_loop() |
|||
loop.run_until_complete(wrapper()) |
|||
return loop.run_forever() |
|||
|
|||
return decorate |
@ -0,0 +1,286 @@ |
|||
import json |
|||
import requests |
|||
|
|||
from websocket import create_connection |
|||
import socketio |
|||
|
|||
from .utils import Event, User, Data, Donations, DonationsData, CentrifugoResponse |
|||
|
|||
DEFAULT_URL = "https://www.donationalerts.com/oauth/" |
|||
DEFAULT_API_LINK = "https://www.donationalerts.com/api/v1/" |
|||
|
|||
|
|||
class DonationAlertsApi: |
|||
""" |
|||
This class describes work with Donation Alerts API |
|||
""" |
|||
|
|||
def __init__(self, client_id, client_secret, redirect_uri, scopes): |
|||
symbols = [",", ", ", " ", "%20"] |
|||
|
|||
if isinstance(scopes, list): |
|||
obj_scopes = [] |
|||
for scope in scopes: |
|||
obj_scopes.append(scope) |
|||
|
|||
scopes = " ".join(obj_scopes) |
|||
|
|||
for symbol in symbols: |
|||
if symbol in scopes: |
|||
self.scope = scopes.replace(symbol, "%20").strip() # Replaces some symbols on '%20' for stable work |
|||
else: |
|||
self.scope = scopes |
|||
|
|||
self.client_id = client_id |
|||
self.client_secret = client_secret |
|||
self.redirect_uri = redirect_uri |
|||
|
|||
def login(self): |
|||
return f"{DEFAULT_URL}authorize?client_id={self.client_id}&redirect_uri={self.redirect_uri}&response_type=code&scope={self.scope}" |
|||
|
|||
def get_access_token(self, code, *, full_json=False): |
|||
payload = { |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"grant_type": "authorization_code", |
|||
"code": code, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
access_token = requests.post(f"{DEFAULT_URL}token", data=payload).json() |
|||
self.refresh_token = access_token.get("refresh_token") |
|||
|
|||
return Data( |
|||
obj["access_token"], |
|||
obj["expires_in"], |
|||
obj["refresh_token"], |
|||
obj["token_type"], |
|||
obj |
|||
) if full_json else obj["access_token"] |
|||
|
|||
def donations_list(self, access_token, *, current_page: int=1, from_page: int=1, last_page: int=13, per_page: int=30, to: int=30, total: int=385): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
|
|||
"""Pagination in development""" |
|||
meta = { |
|||
"current_page": current_page, |
|||
"from": from_page, |
|||
"last_page": last_page, |
|||
"path": f"{DEFAULT_API_LINK}alerts/donations", |
|||
"per_page": per_page, |
|||
"to": to, |
|||
"total": total |
|||
} |
|||
links = { |
|||
"first": f"{DEFAULT_API_LINK}alerts/donations?page={from_page}", |
|||
"last": f"{DEFAULT_API_LINK}alerts/donations?page={last_page}", |
|||
"last": f"{DEFAULT_API_LINK}alerts/donations?page={last_page}", |
|||
"next": f"{DEFAULT_API_LINK}alerts/donations?page={current_page + 1}", |
|||
"prev": None |
|||
} |
|||
|
|||
objs = requests.get(f"{DEFAULT_API_LINK}alerts/donations", headers=headers).json() |
|||
donations = Donations(objects=objs["data"]) |
|||
|
|||
for obj in objs["data"]: |
|||
donation_object = DonationsData( |
|||
obj["amount"], |
|||
obj["amount_in_user_currency"], |
|||
obj["created_at"], |
|||
obj["currency"], |
|||
obj["id"], |
|||
obj["is_shown"], |
|||
obj["message"], |
|||
obj["message_type"], |
|||
obj["name"], |
|||
obj["payin_system"], |
|||
obj["recipient_name"], |
|||
obj["shown_at"], |
|||
obj["username"] |
|||
) |
|||
donations.donation.append(donation_object) |
|||
|
|||
return donations |
|||
|
|||
def user(self, access_token): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
obj = requests.get(f"{DEFAULT_API_LINK}user/oauth", headers=headers).json() |
|||
|
|||
return User( |
|||
obj["data"]["avatar"], |
|||
obj["data"]["code"], |
|||
obj["data"]["email"], |
|||
obj["data"]["id"], |
|||
obj["data"]["language"], |
|||
obj["data"]["name"], |
|||
obj["data"]["socket_connection_token"], |
|||
obj["data"] |
|||
) |
|||
|
|||
def send_custom_alert(self, access_token, external_id, headline, message, *, image_url=None, sound_url=None, is_shown=0): |
|||
headers = { |
|||
"Authorization": f"Bearer {access_token}", |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
payload = { |
|||
"external_id": external_id, |
|||
"headline": headline, |
|||
"message": message, |
|||
"is_shown": is_shown, |
|||
"image_url": image_url, |
|||
"sound_url": sound_url |
|||
} |
|||
|
|||
obj = requests.post(f"{DEFAULT_API_LINK}custom_alert", data=payload, headers=headers).json() |
|||
return obj |
|||
|
|||
def get_refresh_token(self, access_token, refresh_token): |
|||
headers = { |
|||
"Content-Type": "application/x-www-form-urlencoded" |
|||
} |
|||
payload = { |
|||
"grant_type": "refresh_token", |
|||
"client_id": self.client_id, |
|||
"client_secret": self.client_secret, |
|||
"refresh_token": refresh_token, |
|||
"redirect_uri": self.redirect_uri, |
|||
"scope": self.scope |
|||
} |
|||
|
|||
obj = requests.post(f"{DEFAULT_URL}token", data=payload, headers=headers).json() |
|||
return Data( |
|||
obj["access_token"], |
|||
obj["expires_in"], |
|||
obj["refresh_token"], |
|||
obj["token_type"], |
|||
obj |
|||
) |
|||
|
|||
|
|||
class Centrifugo: |
|||
|
|||
def __init__(self, socket_connection_token, access_token, user_id): |
|||
self.socket_connection_token = socket_connection_token |
|||
self.access_token = access_token |
|||
self.user_id = user_id |
|||
|
|||
self.uri = "wss://centrifugo.donationalerts.com/connection/websocket" |
|||
|
|||
def subscribe(self, channels): |
|||
chnls = [f"{channels}{self.user_id}"] |
|||
if isinstance(channels, list): |
|||
chnls = [] |
|||
for channel in channels: |
|||
chnls.append(f"{channel}{self.user_id}") |
|||
|
|||
ws = create_connection(self.uri) |
|||
ws.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"token": self.socket_connection_token |
|||
}, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
|
|||
ws_response = json.loads(ws.recv()) |
|||
|
|||
headers = { |
|||
"Authorization": f"Bearer {self.access_token}", |
|||
"Content-Type": "application/json" |
|||
} |
|||
data = { |
|||
"channels": chnls, |
|||
"client": ws_response["result"]["client"] |
|||
} |
|||
|
|||
response = requests.post(f"{DEFAULT_API_LINK}centrifuge/subscribe", data=json.dumps(data), headers=headers).json() |
|||
for ch in response["channels"]: |
|||
self.ws.send(json.dumps( |
|||
{ |
|||
"params": { |
|||
"channel": ch["channel"], |
|||
"token": ch["token"] |
|||
}, |
|||
"method": 1, |
|||
"id": self.user_id |
|||
} |
|||
)) |
|||
|
|||
ws.recv() |
|||
ws.recv() |
|||
|
|||
obj = json.loads(ws.recv())["result"]["data"]["data"] |
|||
return CentrifugoResponse( |
|||
obj["amount"], |
|||
obj["amount_in_user_currency"], |
|||
obj["created_at"], |
|||
obj["currency"], |
|||
obj["id"], |
|||
obj["is_shown"], |
|||
obj["message"], |
|||
obj["message_type"], |
|||
obj["name"], |
|||
obj["payin_system"], |
|||
obj["recipient_name"], |
|||
obj["shown_at"], |
|||
obj["username"], |
|||
obj["reason"], |
|||
obj |
|||
) |
|||
|
|||
|
|||
sio = socketio.Client() |
|||
|
|||
|
|||
class Alert: |
|||
|
|||
def __init__(self, token): |
|||
self.token = token |
|||
|
|||
def event(self): |
|||
def wrapper(function): |
|||
|
|||
@sio.on("connect") |
|||
def on_connect(): |
|||
sio.emit("add-user", {"token": self.token, "type": "alert_widget"}) |
|||
|
|||
@sio.on("donation") |
|||
def on_message(data): |
|||
data = json.loads(data) |
|||
|
|||
function( |
|||
Event( |
|||
data["id"], |
|||
data["alert_type"], |
|||
data["is_shown"], |
|||
json.loads(data["additional_data"]), |
|||
data["billing_system"], |
|||
data["billing_system_type"], |
|||
data["username"], |
|||
data["amount"], |
|||
data["amount_formatted"], |
|||
data["amount_main"], |
|||
data["currency"], |
|||
data["message"], |
|||
data["header"], |
|||
data["date_created"], |
|||
data["emotes"], |
|||
data["ap_id"], |
|||
data["_is_test_alert"], |
|||
data["message_type"], |
|||
data["preset_id"], |
|||
data |
|||
) |
|||
) |
|||
|
|||
sio.connect("wss://socket.donationalerts.ru:443", transports="websocket") |
|||
|
|||
return wrapper |
@ -0,0 +1,23 @@ |
|||
class Scopes: |
|||
USER_SHOW = "oauth-user-show" |
|||
|
|||
DONATION_SUBSCRIBE = "oauth-donation-subscribe" |
|||
DONATION_INDEX = "oauth-donation-index" |
|||
|
|||
CUSTOM_ALERT_STORE = "oauth-custom_alert-store" |
|||
|
|||
GOAL_SUBSCRIBE = "oauth-goal-subscribe" |
|||
POLL_SUBSCRIBE = "oauth-poll-subscribe" |
|||
|
|||
ALL_SCOPES = [USER_SHOW, DONATION_INDEX, DONATION_SUBSCRIBE, CUSTOM_ALERT_STORE, |
|||
GOAL_SUBSCRIBE, POLL_SUBSCRIBE] |
|||
|
|||
|
|||
class Channels: |
|||
NEW_DONATION_ALERTS = "$alerts:donation_" |
|||
|
|||
DONATION_GOALS_UPDATES = "$goals:goal_" |
|||
|
|||
POLLS_UPDATES = "$polls:poll_" |
|||
|
|||
ALL_CHANNELS = [NEW_DONATION_ALERTS, DONATION_GOALS_UPDATES, POLLS_UPDATES] |
@ -0,0 +1,94 @@ |
|||
from dataclasses import dataclass |
|||
|
|||
|
|||
@dataclass |
|||
class Event: |
|||
|
|||
id: int |
|||
alert_type: str |
|||
is_shown: str |
|||
additional_data: dict |
|||
billing_system: str |
|||
billing_system_type: str |
|||
username: str |
|||
amount: str |
|||
amount_formatted: str |
|||
amount_main: int |
|||
currency: str |
|||
message: str |
|||
header: str |
|||
date_created: str |
|||
emotes: str |
|||
ap_id: str |
|||
_is_test_alert: bool |
|||
message_type: str |
|||
preset_id: int |
|||
objects: dict |
|||
|
|||
|
|||
@dataclass |
|||
class Donations: |
|||
|
|||
donation = [] |
|||
objects: dict = None |
|||
|
|||
|
|||
@dataclass |
|||
class DonationsData: |
|||
|
|||
amount: int |
|||
amount_in_user_currency: float |
|||
created_at: str |
|||
currency: str |
|||
id: int |
|||
is_shown: int |
|||
message: str |
|||
message_type: str |
|||
name: str |
|||
payin_system: str |
|||
recipient_name: str |
|||
shown_at: str |
|||
username: str |
|||
|
|||
|
|||
@dataclass |
|||
class User: |
|||
|
|||
avatar: str |
|||
code: str |
|||
email: str |
|||
id: int |
|||
language: str |
|||
name: str |
|||
socket_connection_token: str |
|||
objects: dict |
|||
|
|||
|
|||
@dataclass |
|||
class Data: |
|||
|
|||
access_token: str |
|||
expires_in: int |
|||
refresh_token: str |
|||
token_type: str |
|||
objects: dict |
|||
|
|||
|
|||
@dataclass |
|||
class CentrifugoResponse: |
|||
|
|||
amount: int |
|||
amount_in_user_currency: float |
|||
created_at: str |
|||
currency: str |
|||
id: int |
|||
is_shown: int |
|||
message: str |
|||
message_type: str |
|||
name: str |
|||
payin_system: str |
|||
recipient_name: str |
|||
shown_at: str |
|||
username: str |
|||
reason: str |
|||
objects: dict |
Loading…
Reference in new issue