|
|
|
@ -3,6 +3,7 @@ logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
|
|
|
|
import os |
|
|
|
|
import yaml |
|
|
|
|
import hmac |
|
|
|
|
from aiohttp import web |
|
|
|
|
from telethon import TelegramClient |
|
|
|
|
from telethon.utils import _get_file_info |
|
|
|
@ -13,27 +14,52 @@ with open('config.yaml') as file:
|
|
|
|
|
|
|
|
|
|
client = TelegramClient('streamtg', config['telegram']['api_id'], config['telegram']['api_hash']) |
|
|
|
|
authorized_tokens = config.get('authorized_tokens') |
|
|
|
|
hmacs = [hmac.new(i['key'].encode(), digestmod=i['digest']) for i in config.get('hmac', ())] |
|
|
|
|
port = os.environ.get('PORT', 8080) |
|
|
|
|
|
|
|
|
|
def verify_token(token): |
|
|
|
|
return token in authorized_tokens |
|
|
|
|
|
|
|
|
|
def verify_hmac(hexdigest, chat_id, message_ids): |
|
|
|
|
text = f'{chat_id}|{"|".join(message_ids)}'.encode() |
|
|
|
|
for i in hmacs: |
|
|
|
|
i = i.copy() |
|
|
|
|
i.update(text) |
|
|
|
|
if hmac.compare_digest(hexdigest, i.hexdigest()): |
|
|
|
|
return True |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
async def handler(request): |
|
|
|
|
query = request.query |
|
|
|
|
if authorized_tokens: |
|
|
|
|
if 'token' not in query: |
|
|
|
|
return web.Response(status=401, text='Unauthorized') |
|
|
|
|
if query['token'] not in authorized_tokens: |
|
|
|
|
return web.Response(status=403, text='Forbidden') |
|
|
|
|
token = query.get('token') |
|
|
|
|
hexdigest = query.get('hmac') |
|
|
|
|
if not token and not hexdigest and (authorized_tokens or hmacs): |
|
|
|
|
return web.Response(status=401, text='Missing token or hmac') |
|
|
|
|
if 'chat_id' not in query: |
|
|
|
|
return web.Response(status=400, text='Missing chat_id') |
|
|
|
|
chat_id = query['chat_id'] |
|
|
|
|
try: |
|
|
|
|
chat_id = int(chat_id) |
|
|
|
|
except ValueError: |
|
|
|
|
pass |
|
|
|
|
try: |
|
|
|
|
chat_id = await client.get_peer_id(chat_id) |
|
|
|
|
except BaseException: |
|
|
|
|
if authorized_tokens or hmacs: |
|
|
|
|
logging.exception('Exception occured while getting chat id of %s, returning 403 to hide known chats', chat_id) |
|
|
|
|
return web.Response(status=403, text='Forbidden') |
|
|
|
|
raise |
|
|
|
|
if 'message_id' not in query: |
|
|
|
|
return web.Response(status=400, text='Missing message_id') |
|
|
|
|
message_ids = query.getall('message_id') |
|
|
|
|
if any(True for i in message_ids if not i.isnumeric() or i == '0'): |
|
|
|
|
return web.Response(status=400, text='Invalid message_id') |
|
|
|
|
if authorized_tokens or hmacs: |
|
|
|
|
if not token or not verify_token(token): |
|
|
|
|
if hexdigest: |
|
|
|
|
if not verify_hmac(hexdigest, chat_id, message_ids): |
|
|
|
|
return web.Response(status=403, text='Forbidden') |
|
|
|
|
else: |
|
|
|
|
return web.Response(status=403, text='Forbidden') |
|
|
|
|
message_ids = list(map(int, message_ids)) |
|
|
|
|
messages = await client.get_messages(chat_id, ids=message_ids) |
|
|
|
|
if any(True for i in messages if i is None): |
|
|
|
|