-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1eab598
commit 2ffbba2
Showing
3 changed files
with
307 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,5 +2,5 @@ | |
/__pycache__ | ||
/dataBase.db | ||
/.env | ||
/tg | ||
/out | ||
/out | ||
/Telegram_provider/dataBase.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,287 @@ | ||
""" | ||
by AndcoolSystems, 2024 | ||
""" | ||
|
||
from aiogram import Bot, Dispatcher, types, F | ||
from aiogram.fsm.context import FSMContext | ||
from aiogram.fsm.state import StatesGroup, State | ||
from aiogram.filters.command import Command | ||
from aiogram.utils.keyboard import InlineKeyboardBuilder | ||
from aiogram.methods import DeleteWebhook | ||
from prisma import Prisma | ||
import os | ||
import time | ||
import asyncio | ||
import io | ||
import aiohttp | ||
|
||
"""Создание всех нужных объектов""" | ||
bot = Bot(token="6423586916:AAF9HVUbtsiuE7I1UKn9QfMkn82KM8NHKLU") | ||
dp = Dispatcher() | ||
db = Prisma() | ||
version = "beta 0.0.1" | ||
|
||
class States(StatesGroup): | ||
"""Стейты для aiogram""" | ||
|
||
wait_to_data = State() | ||
login_register = State() | ||
|
||
|
||
async def upload(bytes: bytearray, filename: str, user): | ||
form_data = aiohttp.FormData() | ||
form_data.add_field('file', bytes, filename=filename) | ||
headers = {} | ||
if user: | ||
headers = {"Authorization": "Bearer " + user.token} | ||
|
||
async with aiohttp.ClientSession("https://fu.andcool.ru") as session: | ||
async with session.post(f"/api/upload/private", | ||
data=form_data, headers=headers) as r: | ||
return r, await r.json() | ||
|
||
|
||
async def get_files(token: str): | ||
async with aiohttp.ClientSession("https://fu.andcool.ru") as session: | ||
async with session.get(f"/api/get_files/private", headers={"Authorization": "Bearer " + token}) as r: | ||
return r, await r.json() | ||
|
||
|
||
async def send_login_message(message: types.Message): | ||
builder = InlineKeyboardBuilder() | ||
builder.add(types.InlineKeyboardButton( | ||
text="Log in", | ||
callback_data=f"log_login") | ||
) | ||
builder.add(types.InlineKeyboardButton( | ||
text="Register", | ||
callback_data=f"log_register") | ||
) | ||
|
||
await message.answer(f"_To access your files from any device, sign in. " + \ | ||
"The files will be linked to your account and you will have full access to them._", | ||
reply_markup=builder.as_markup(), | ||
parse_mode="Markdown") | ||
|
||
|
||
@dp.message(Command('start')) | ||
async def start(message: types.Message, state: FSMContext): | ||
"""Хэндлер для команды /start""" | ||
|
||
await state.clear() | ||
await message.answer("*Attention! This bot is in open beta testing, so there may be significant bugs and errors in operation.\n*" + \ | ||
f"Current version: {version}", parse_mode="Markdown") | ||
await message.answer(f"Hello, {message.from_user.full_name}!\n" + \ | ||
f"I am the Telegram provider of the fu.andcool.ru service. To get started, send me the file that needs to be uploaded.") | ||
|
||
|
||
@dp.message(Command('account')) | ||
async def account(message: types.Message, state: FSMContext): | ||
user = await db.user.find_first(where={"user_id": message.from_user.id}) | ||
if not user: | ||
await send_login_message(message) | ||
return | ||
|
||
else: | ||
response, response_json = await get_files(user.token) | ||
if response.status == 401: | ||
await db.user.delete(where={"id": user.id}) | ||
await send_login_message(message) | ||
return | ||
|
||
if response.status == 429: | ||
await message.answer("Sorry, the servers are overloaded right now") | ||
return | ||
|
||
builder = InlineKeyboardBuilder() | ||
builder.add(types.InlineKeyboardButton( | ||
text="Log out", | ||
callback_data=f"logout") | ||
) | ||
|
||
await message.answer(f"*Account:*\n*Username:* {user.username}\n" + \ | ||
f"*Files on account:* {len(response_json['data'])}", | ||
reply_markup=builder.as_markup(), | ||
parse_mode="Markdown") | ||
|
||
|
||
@dp.callback_query(F.data.startswith("log_")) | ||
async def log(callback: types.CallbackQuery, state: FSMContext): | ||
await callback.message.delete() | ||
await callback.message.answer(f"OK, now send me the data from your account in the format:\n```\nMy cool username\nMy cool password```", | ||
parse_mode="Markdown") | ||
await state.set_state(States.wait_to_data) | ||
await state.update_data(login_register=callback.data.replace("log_", "")) | ||
|
||
|
||
@dp.message(F.text, States.wait_to_data) | ||
async def log_reg(message: types.Message, state: FSMContext): | ||
login_register = (await state.get_data())["login_register"] | ||
login_and_password = message.text.replace('`', '').split("\n") | ||
|
||
if len(login_and_password) < 2: | ||
await message.answer('The data was sent incorrectly') | ||
return | ||
|
||
async with aiohttp.ClientSession("https://fu.andcool.ru") as session: | ||
async with session.post(f"/api/{'login' if login_register == 'login' else 'register'}?bot=true", | ||
json={"username": login_and_password[0], | ||
"password": login_and_password[1]}) as r: | ||
|
||
await message.delete() | ||
data_resp = await r.json() | ||
if r.status == 400 or r.status == 404: | ||
await message.answer(data_resp['message']) | ||
return | ||
|
||
if r.status == 200: | ||
await db.user.create(data={ | ||
"user_id": message.from_user.id, | ||
"username": data_resp['username'], | ||
'token': data_resp['accessToken'] | ||
}) | ||
await account(message, state) | ||
await state.clear() | ||
return | ||
|
||
await message.answer("Unhandled error") | ||
return | ||
|
||
|
||
@dp.callback_query(F.data == "logout") | ||
async def log(callback: types.CallbackQuery, state: FSMContext): | ||
user = await db.user.find_first(where={"user_id": callback.from_user.id}) | ||
if not user: | ||
await callback.message.answer("You are not logged in") | ||
return | ||
|
||
async with aiohttp.ClientSession("https://fu.andcool.ru") as session: | ||
async with session.get(f"/api/logout", headers={"Authorization": "Bearer " + user.token}) as response: | ||
if response.status == 401 or response.status == 200: | ||
await db.user.delete(where={"id": user.id}) | ||
await callback.message.answer("Logged out!") | ||
await callback.message.delete() | ||
return | ||
|
||
|
||
@dp.message(F.content_type.in_({'document', 'photo', 'video', 'animation', 'video_note', 'voice', 'text'})) | ||
async def send_file(message: types.Message, state: FSMContext): | ||
"""Хэндлер для файлов""" | ||
|
||
match message.content_type: | ||
case "document": | ||
document = message.document | ||
file_id = document.file_id | ||
|
||
bio = io.BytesIO() | ||
filename = document.file_name | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "photo": | ||
photo = message.photo[-1] | ||
file_id = photo.file_id | ||
file = await bot.get_file(file_id) | ||
|
||
bio = io.BytesIO() | ||
filename = file.file_path | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "video": | ||
video = message.video | ||
file_id = video.file_id | ||
file = await bot.get_file(file_id) | ||
|
||
bio = io.BytesIO() | ||
filename = file.file_path | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "animation": | ||
animation = message.animation | ||
file_id = animation.file_id | ||
file = await bot.get_file(file_id) | ||
|
||
bio = io.BytesIO() | ||
filename = file.file_path | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "video_note": | ||
video_note = message.video_note | ||
file_id = video_note.file_id | ||
file = await bot.get_file(file_id) | ||
|
||
bio = io.BytesIO() | ||
filename = file.file_path | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "voice": | ||
voice = message.voice | ||
file_id = voice.file_id | ||
file = await bot.get_file(file_id) | ||
|
||
bio = io.BytesIO() | ||
filename = f"voice.mp3" | ||
file_bytes = await bot.download(file_id, destination=bio) | ||
bio.seek(0) | ||
|
||
case "text": | ||
file_bytes = message.text.encode() | ||
filename = 'text.txt' | ||
|
||
user = await db.user.find_first(where={"user_id": message.from_user.id}) | ||
response, result = await upload(file_bytes, filename, user) | ||
|
||
if response.status != 200: | ||
error = result['error'] if response.status == 429 else result['message'] | ||
await message.reply(error) | ||
return | ||
|
||
builder = InlineKeyboardBuilder() | ||
builder.add(types.InlineKeyboardButton( | ||
text="Delete file", | ||
callback_data=f"delete_{result['file_url']}_{result['key']}") | ||
) | ||
|
||
await message.reply(f"*Your file has been uploaded.!*\n*Link:* {result['file_url_full']}\n*Size:* {result['size']}", | ||
reply_markup=builder.as_markup(), | ||
parse_mode="Markdown") | ||
|
||
|
||
@dp.callback_query(F.data.startswith("delete_")) | ||
async def delete_file(callback: types.CallbackQuery, state: FSMContext): | ||
"""Хэндлер для колбэка кнопок выбора удаления""" | ||
|
||
file_data = callback.data.replace("delete_", "").split("_") | ||
async with aiohttp.ClientSession("https://fu.andcool.ru") as session: | ||
async with session.get(f"/api/delete/{file_data[0]}?key={file_data[1]}") as r: | ||
response = await r.json() | ||
if response['status'] == 'success': | ||
await callback.message.delete() | ||
await callback.message.answer("File has been deleted!") | ||
else: | ||
await callback.message.answer(response['message']) | ||
|
||
|
||
async def start(): | ||
"""Асинхронная функция для запуска диспатчера""" | ||
|
||
await db.connect() # Connecting to database | ||
started = True | ||
while started: | ||
try: | ||
await bot(DeleteWebhook(drop_pending_updates=True)) | ||
await dp.start_polling(bot) | ||
started = False | ||
except Exception: | ||
started = True | ||
print("An error has occurred, reboot in 10 seconds") | ||
time.sleep(10) | ||
print("rebooting...") | ||
|
||
|
||
if __name__ == '__main__': | ||
asyncio.run(start()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
datasource db { | ||
// could be postgresql or mysql | ||
provider = "sqlite" | ||
url = "file:dataBase.db" | ||
} | ||
|
||
generator db { | ||
provider = "prisma-client-py" | ||
interface = "asyncio" | ||
recursive_type_depth = 5 | ||
} | ||
|
||
model User { | ||
id Int @id @default(autoincrement()) | ||
user_id BigInt @default(0) | ||
username String @default("") | ||
token String @default("") | ||
} |