Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
42f95b6e9d |
169
.gitignore
vendored
|
@ -1,169 +0,0 @@
|
|||
.DS_Store
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
BIN
architecture.png
Before Width: | Height: | Size: 35 KiB |
BIN
bot/.DS_Store
vendored
Normal file
21
bot/Dockerfile
Normal file
|
@ -0,0 +1,21 @@
|
|||
FROM python:3.10.7
|
||||
|
||||
# python envs
|
||||
ENV PYTHONFAULTHANDLER=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONHASHSEED=random \
|
||||
PIP_NO_CACHE_DIR=off \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100
|
||||
|
||||
# python dependencies
|
||||
COPY ./requirements.txt /
|
||||
RUN pip install -r /requirements.txt
|
||||
|
||||
COPY ./scripts/start.sh ./scripts/gunicorn.sh /
|
||||
|
||||
RUN chmod +x /start.sh
|
||||
RUN chmod +x /gunicorn.sh
|
||||
|
||||
|
||||
WORKDIR /app
|
BIN
bot/__pycache__/create_bot.cpython-312.pyc
Normal file
BIN
bot/__pycache__/memcached_def.cpython-312.pyc
Normal file
BIN
bot/__pycache__/messages.cpython-312.pyc
Normal file
BIN
bot/__pycache__/req.cpython-312.pyc
Normal file
BIN
bot/__pycache__/wrapper.cpython-312.pyc
Normal file
BIN
bot/avatar.jpg
Normal file
After Width: | Height: | Size: 7.7 KiB |
64
bot/back_send.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
import json
|
||||
import io
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks
|
||||
from pydantic import BaseModel
|
||||
from create_bot import bot, important_message, url
|
||||
from aiogram import types
|
||||
from create_bot import request_url, api_token
|
||||
import requests
|
||||
import time
|
||||
import re
|
||||
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo, ReplyKeyboardRemove
|
||||
from loguru import logger
|
||||
|
||||
def get_answer_keyboard():
|
||||
keyboard = InlineKeyboardMarkup()
|
||||
button1 = InlineKeyboardButton('Главное меню', callback_data='main_menu_text')
|
||||
keyboard.add(button1)
|
||||
return keyboard
|
||||
|
||||
class AlertSchema(BaseModel):
|
||||
tg_id: int
|
||||
message: str
|
||||
|
||||
class DispatchSchema(BaseModel):
|
||||
tg_id: int
|
||||
text: str
|
||||
attachment_path: str
|
||||
button_name: str | None = None
|
||||
button_url: str | None = None
|
||||
web_app_button_name: str | None = None
|
||||
|
||||
send_message_router = APIRouter(
|
||||
prefix=''
|
||||
)
|
||||
|
||||
@send_message_router.post('/dispatch/')
|
||||
async def handle_dispatch(data: DispatchSchema, background_tasks: BackgroundTasks):
|
||||
try:
|
||||
media = io.BytesIO(requests.get(data.attachment_path).content)
|
||||
media.seek(0)
|
||||
attachment = types.InputFile(media)
|
||||
keyboard = InlineKeyboardMarkup()
|
||||
if data.button_name and data.button_url:
|
||||
button1 = InlineKeyboardButton(f'{data.button_name}', url=f"{data.button_url}")
|
||||
keyboard.add(button1)
|
||||
if data.web_app_button_name:
|
||||
button2 = InlineKeyboardButton(f'{data.web_app_button_name}', web_app=WebAppInfo(url=f"{url}"))
|
||||
keyboard.add(button2)
|
||||
|
||||
if not data.button_name and not data.web_app_button_name:
|
||||
await bot.send_photo(data.tg_id, attachment, caption=data.text, parse_mode=types.ParseMode.MARKDOWN, reply_markup=ReplyKeyboardRemove())
|
||||
else:
|
||||
await bot.send_photo(data.tg_id, attachment, caption=data.text, reply_markup=keyboard, parse_mode=types.ParseMode.MARKDOWN)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
return {'ok': True}
|
||||
|
||||
@send_message_router.post('/alert/')
|
||||
async def handle_alert(data: AlertSchema):
|
||||
try:
|
||||
await bot.send_message(chat_id=data.tg_id, text=data.message, parse_mode=types.ParseMode.MARKDOWN) #, reply_markup=get_answer_keyboard())
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
return {'ok': True}
|
27
bot/config.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import logging
|
||||
from aiogram import Bot, types
|
||||
from aiogram import Dispatcher
|
||||
from create_bot import bot, token, WEBHOOK_URL
|
||||
from handlers.register_handlers import register_all_handlers
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from loguru import logger
|
||||
|
||||
dp = Dispatcher(bot, storage=MemoryStorage())
|
||||
|
||||
logger.add("logs.log", format = "{time} | {module} : {function} | {level} | {message}", level = "INFO", rotation = "1 week", compression = "zip")#, serialize = True)
|
||||
|
||||
|
||||
async def on_startup():
|
||||
webhook_info = await bot.get_webhook_info()
|
||||
if webhook_info.url != WEBHOOK_URL:
|
||||
await bot.set_webhook(
|
||||
url=WEBHOOK_URL,
|
||||
drop_pending_updates=True
|
||||
)
|
||||
|
||||
register_all_handlers(dp)
|
||||
|
||||
|
||||
async def on_shutdown():
|
||||
await bot.session.close()
|
||||
await bot.delete_webhook()
|
24
bot/create_bot.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from aiogram import Bot
|
||||
import os
|
||||
|
||||
token = os.getenv('TG_TOKEN', '7748003961:AAEIXu8NFICPabNaQP5JQ3AcY79nZdUbKdI')
|
||||
api_token = os.getenv('API_TOKEN', 'b43fa8ccea5b6dd5e889a8ad3890ce14ce36a8bc') # TODO: remove
|
||||
backend_url = os.getenv('BACKEND_URL', 'http://backend:8000')
|
||||
request_url = f'{backend_url}/api'
|
||||
url = os.getenv('URL', 'https://google.com')
|
||||
bot_name = os.getenv('BOT_NAME', 'https://t.me/danyadjan_test_bot')
|
||||
|
||||
bucket_name = 'brawny-basket'
|
||||
username = 'e80165bc-8d55-42a3-a96b-f62314446f87'
|
||||
password = '0d8e160fc5625ff0f176a0f70a22e336e8fb21a9841a5d20223714b7cee19341'
|
||||
endpoint_url = 'https://s3.aeza.cloud/brawny-basket'
|
||||
|
||||
WEBHOOK_HOST = f'{url}/bot'
|
||||
WEBHOOK_PATH = 'wh'
|
||||
WEBHOOK_URL = f'{WEBHOOK_HOST}/{WEBHOOK_PATH}/{token}'
|
||||
|
||||
bot = Bot(token=token)
|
||||
|
||||
important_message = {}
|
||||
|
||||
event_number = {}
|
1
bot/handlers/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from cgitb import handler
|
BIN
bot/handlers/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
bot/handlers/__pycache__/instruction.cpython-312.pyc
Normal file
BIN
bot/handlers/__pycache__/register_handlers.cpython-312.pyc
Normal file
BIN
bot/handlers/__pycache__/start_handler.cpython-312.pyc
Normal file
103
bot/handlers/instruction.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
from aiogram import types
|
||||
from aiogram import Bot, Dispatcher
|
||||
import re
|
||||
import json
|
||||
from create_bot import bot, important_message, event_number
|
||||
from memcached_def import add_rec, get_rec
|
||||
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, FSInputFile
|
||||
|
||||
from loguru import logger
|
||||
|
||||
def get_event_keyboard(number):
|
||||
kb = []
|
||||
dlina = 5
|
||||
button1 = InlineKeyboardButton(text='←', callback_data="num_decr")
|
||||
button2 = InlineKeyboardButton(text=f'{number + 1}/{dlina}', callback_data="element")
|
||||
button3 = InlineKeyboardButton(text='→', callback_data="num_incr")
|
||||
button4 = InlineKeyboardButton(text='Главное меню', callback_data='main_menu_delete')
|
||||
if int(number + 1) == 1:
|
||||
kb = [[button2, button3]]
|
||||
elif int(number + 1) == dlina:
|
||||
kb = [[button1, button2]]
|
||||
else:
|
||||
kb = [[button1, button2, button3]]
|
||||
kb.append([button4])
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=kb)
|
||||
return keyboard
|
||||
|
||||
def read_data_from_file(file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as file:
|
||||
data_lines = file.readlines()
|
||||
|
||||
data_dict = {}
|
||||
for line in data_lines:
|
||||
key, value = line.strip().split(": ")
|
||||
data_dict[key.strip()] = value.strip()
|
||||
|
||||
return data_dict
|
||||
except FileNotFoundError:
|
||||
print("File not found.")
|
||||
return None
|
||||
except Exception as e:
|
||||
print("An error occurred:", e)
|
||||
return None
|
||||
|
||||
def update_file(file_path, data_dict):
|
||||
try:
|
||||
with open(file_path, 'r') as file:
|
||||
existing_data = file.readlines()
|
||||
|
||||
with open(file_path, 'w') as file:
|
||||
for line in existing_data:
|
||||
key = line.split(":")[0].strip()
|
||||
if key in data_dict:
|
||||
file.write(f"{key}: {data_dict[key]}\n")
|
||||
else:
|
||||
file.write(line)
|
||||
|
||||
for key, value in data_dict.items():
|
||||
if key not in existing_data:
|
||||
file.write(f"{key}: {value}\n")
|
||||
|
||||
# print("File updated successfully.")
|
||||
except Exception as e:
|
||||
print("An error occurred:", e)
|
||||
|
||||
# Example usage:
|
||||
file_path = "data.txt"
|
||||
|
||||
|
||||
ins_list = ['1.png',
|
||||
'2.png',
|
||||
'3.png',
|
||||
'4.png',
|
||||
'5.png']
|
||||
|
||||
async def instruction_message(call: types.CallbackQuery):
|
||||
logger.info(f"{call.from_user.id} - @{call.from_user.username} : инструкция")
|
||||
|
||||
add_rec(call.from_user.id, 0)
|
||||
|
||||
await call.message.delete()
|
||||
await bot.send_photo(call.from_user.id, FSInputFile('pictures/1.png', 'rb'), reply_markup=get_event_keyboard(0))
|
||||
|
||||
async def update_instruction(message: types.Message, new_value: int):
|
||||
photo = FSInputFile(f'pictures/{new_value + 1}.png')
|
||||
await message.edit_media(types.InputMediaPhoto(media=photo), reply_markup=get_event_keyboard(new_value))
|
||||
|
||||
async def callbacks_instruction(callback: types.CallbackQuery):
|
||||
user_value = int(get_rec(callback.from_user.id))
|
||||
action = callback.data.split("_")[1]
|
||||
|
||||
if action == "incr":
|
||||
if len(ins_list) > user_value + 1:
|
||||
add_rec(callback.from_user.id, user_value + 1)
|
||||
await update_instruction(callback.message, user_value + 1)
|
||||
elif action == "decr":
|
||||
if user_value - 1 >= 0:
|
||||
add_rec(callback.from_user.id, user_value - 1)
|
||||
await update_instruction(callback.message, user_value - 1)
|
||||
#print("-1")
|
||||
|
||||
await callback.answer()
|
27
bot/handlers/register_handlers.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from aiogram import Router
|
||||
from aiogram.filters import Command
|
||||
from aiogram import F
|
||||
|
||||
from handlers.start_handler import (command_start,
|
||||
get_main_menu_answer,
|
||||
get_main_menu_after_picture)
|
||||
|
||||
from handlers.instruction import (instruction_message,
|
||||
callbacks_instruction)
|
||||
|
||||
|
||||
|
||||
def register_all_handlers(router: Router):
|
||||
handle_register_start_message(router)
|
||||
handle_instruction_message(router)
|
||||
|
||||
|
||||
def handle_register_start_message(router: Router):
|
||||
router.message.register(command_start, Command(commands=["start"]))
|
||||
router.callback_query.register(get_main_menu_after_picture, F.data.startswith('main_menu_delete'))
|
||||
router.callback_query.register(get_main_menu_answer, F.data.startswith('main_menu'))
|
||||
router.callback_query.register(instruction_message, F.data.startswith("instruction_inline"))
|
||||
|
||||
def handle_instruction_message(router: Router):
|
||||
router.callback_query.register(callbacks_instruction, F.data.startswith("num_"))
|
||||
|
73
bot/handlers/start_handler.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
import asyncio
|
||||
from aiogram import Bot, Dispatcher, types
|
||||
import re
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
import random
|
||||
from create_bot import bot, request_url, important_message, url, token, bucket_name, username, password, endpoint_url
|
||||
from req import check_register
|
||||
import urllib.request
|
||||
from messages import get_main_menu_message
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
|
||||
|
||||
from loguru import logger
|
||||
|
||||
import boto3
|
||||
from botocore.config import Config
|
||||
|
||||
def get_answer_keyboard():
|
||||
button1 = InlineKeyboardButton(text='Главное меню', callback_data='main_menu')
|
||||
kb = [[button1]]
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=kb)
|
||||
return keyboard
|
||||
|
||||
def get_main_keyboard_inline(is_admin=False, ref_code=None):
|
||||
button1 = InlineKeyboardButton(text='👾 Кликер', web_app=WebAppInfo(url=f'{url}?referred_by={ref_code}'))
|
||||
button2 = InlineKeyboardButton(text='ℹ️ Инструкция', callback_data='instruction_inline')
|
||||
button3 = InlineKeyboardButton(text='🔥 Кто мы?', web_app=WebAppInfo(url='https://test.com'))
|
||||
button4 = InlineKeyboardButton(text='ТЕСТ', callback_data='test_message')
|
||||
kb = [[button1], [button2], [button3]]
|
||||
if is_admin:
|
||||
kb.append([button4])
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=kb)
|
||||
return keyboard
|
||||
|
||||
def gen_ok_keyboard(number):
|
||||
kb = [[InlineKeyboardButton(text='Подтвердить ✅', callback_data=f'approve_{number}'), InlineKeyboardButton(text='Изменить 🔄', callback_data=f'edit_{number}')]]
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=kb)
|
||||
return keyboard
|
||||
|
||||
async def get_main_menu_answer(call: types.CallbackQuery):
|
||||
logger.info(f"{call.from_user.id} - @{call.from_user.username} : главное меню через инлайн кнопку")
|
||||
await call.message.edit_text(get_main_menu_message(), reply_markup=get_main_keyboard_inline(), parse_mode=ParseMode.MARKDOWN)
|
||||
|
||||
async def get_main_menu_after_picture(call: types.CallbackQuery):
|
||||
logger.info(f"{call.from_user.id} - @{call.from_user.username} : главное меню через инлайн кнопку после картинки")
|
||||
await call.message.delete()
|
||||
await bot.send_message(call.from_user.id, get_main_menu_message(), reply_markup=get_main_keyboard_inline(), parse_mode=ParseMode.MARKDOWN)
|
||||
|
||||
async def command_start(message : types.Message):
|
||||
ref_code = ''
|
||||
if message.text[7:].startswith('user_'):
|
||||
ref_code = message.text[12:]
|
||||
if not check_register(message.from_user.id):
|
||||
|
||||
logger.info(f"{message.from_user.id} - @{message.from_user.username} : команда /start и не зарегистрирован")
|
||||
await bot.send_message(message.from_user.id, '👋', reply_markup=ReplyKeyboardRemove())
|
||||
# await asyncio.sleep(3)
|
||||
await bot.send_message(message.from_user.id, '👑 Я - KYC Кликер бот! Зарабатывай баллы кликами, поднимайся в рейтинге и получай бонусы. Развивайся быстрее с нашей специальной системой для новичков!', reply_markup=ReplyKeyboardRemove())
|
||||
# await asyncio.sleep(3)
|
||||
await bot.send_message(message.from_user.id, '🎁 Используй баллы в аукционе за ценные призы! Победителей много, приглашаем в увлекательную битву кликов!', reply_markup=ReplyKeyboardRemove())
|
||||
# await asyncio.sleep(3)
|
||||
await bot.send_message(message.from_user.id, '👯 Участвуй в реферальной программе, чтобы получать % с кликов друзей и зарабатывать больше баллов для аукциона. ', reply_markup=ReplyKeyboardRemove())
|
||||
# await asyncio.sleep(3)
|
||||
await bot.send_message(message.from_user.id, '🍀 Удачи в битве!', reply_markup=ReplyKeyboardRemove())
|
||||
# await asyncio.sleep(3)
|
||||
else:
|
||||
logger.info(f"{message.from_user.id} - @{message.from_user.username} : команда /start")
|
||||
|
||||
await bot.send_message(message.from_user.id, get_main_menu_message(), reply_markup=get_main_keyboard_inline(ref_code=ref_code), parse_mode=ParseMode.MARKDOWN)
|
21
bot/log.ini
Normal file
|
@ -0,0 +1,21 @@
|
|||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=logfile
|
||||
|
||||
[formatters]
|
||||
keys=logfileformatter
|
||||
|
||||
[logger_root]
|
||||
level=INFO
|
||||
handlers=logfile
|
||||
|
||||
[formatter_logfileformatter]
|
||||
format=[%(asctime)s.%(msecs)03d] %(levelname)s [%(thread)d] - %(message)s
|
||||
|
||||
[handler_logfile]
|
||||
class=handlers.RotatingFileHandler
|
||||
level=INFO
|
||||
args=('logfile.log','a')
|
||||
formatter=logfileformatter
|
8
bot/logs.log
Normal file
|
@ -0,0 +1,8 @@
|
|||
2024-10-27T23:59:11.744491+0300 | main : main | INFO | Starting bot
|
||||
2024-10-27T23:59:12.269505+0300 | start_handler : command_start | INFO | 7080735869 - @danya_danya23 : команда /start и не зарегистрирован
|
||||
2024-10-28T00:00:35.215099+0300 | start_handler : command_start | INFO | 193428034 - @s1lur : команда /start и не зарегистрирован
|
||||
2024-10-28T00:00:35.270428+0300 | start_handler : command_start | INFO | 402449803 - @danyadjan : команда /start и не зарегистрирован
|
||||
2024-10-28T00:01:50.305932+0300 | main : main | INFO | Starting bot
|
||||
2024-10-28T00:01:50.735100+0300 | start_handler : command_start | INFO | 402449803 - @danyadjan : команда /start и не зарегистрирован
|
||||
2024-10-28T00:02:04.042345+0300 | main : main | INFO | Starting bot
|
||||
2024-10-28T00:02:06.132110+0300 | start_handler : command_start | INFO | 402449803 - @danyadjan : команда /start и не зарегистрирован
|
15
bot/main.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import asyncio
|
||||
from loguru import logger
|
||||
from wrapper import run_bot
|
||||
|
||||
def main():
|
||||
try:
|
||||
logger.info("Starting bot")
|
||||
asyncio.run(run_bot())
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Interrupted by user, shutting down")
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
52
bot/main_api.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import os
|
||||
import secrets
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from create_bot import bot
|
||||
from config import on_startup, on_shutdown
|
||||
from routes import bot_api_router
|
||||
from back_send import send_message_router
|
||||
|
||||
def init_app():
|
||||
|
||||
app = FastAPI(
|
||||
title='Clicker Bot',
|
||||
description='',
|
||||
version='1',
|
||||
)
|
||||
|
||||
@app.on_event('startup')
|
||||
async def startup():
|
||||
await on_startup()
|
||||
|
||||
@app.on_event('shutdown')
|
||||
async def shutdown():
|
||||
await on_shutdown()
|
||||
|
||||
app.include_router(
|
||||
bot_api_router,
|
||||
prefix=''
|
||||
)
|
||||
|
||||
app.include_router(
|
||||
send_message_router,
|
||||
prefix=''
|
||||
)
|
||||
|
||||
origins = [
|
||||
'bot:7313',
|
||||
'localhost:7313',
|
||||
]
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=['*'],
|
||||
allow_headers=['*']
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
app = init_app()
|
11
bot/memcached_def.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
import os
|
||||
from pymemcache.client import base
|
||||
|
||||
client = base.Client((os.getenv('mem_host', 'localhost'), os.getenv('mem_port', 11211)))
|
||||
|
||||
def add_rec(key, value):
|
||||
client.set(str(key), value)
|
||||
|
||||
def get_rec(key):
|
||||
value = client.get(str(key))
|
||||
return (int(value))
|
6
bot/messages.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
def get_main_menu_message():
|
||||
msg = '🏠*ГЛАВНОЕ МЕНЮ*'
|
||||
msg1 = '👾 *Кликер* - Играй и соревнуйся с другими участниками!'
|
||||
msg2 = 'ℹ️ *Инструкция* - Читай, чтобы правильно использовать кликер!'
|
||||
msg3 = '🔥 *Кто мы?* - Узнай больше о нас и нашей компании!'
|
||||
return f'{msg}\n\n{msg1}\n{msg2}\n{msg3}'
|
BIN
bot/pictures/.DS_Store
vendored
Normal file
BIN
bot/pictures/1.png
Normal file
After Width: | Height: | Size: 614 KiB |
BIN
bot/pictures/2.png
Normal file
After Width: | Height: | Size: 666 KiB |
BIN
bot/pictures/3.png
Normal file
After Width: | Height: | Size: 561 KiB |
BIN
bot/pictures/4.png
Normal file
After Width: | Height: | Size: 642 KiB |
BIN
bot/pictures/5.png
Normal file
After Width: | Height: | Size: 571 KiB |
14
bot/req.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import json
|
||||
import re
|
||||
|
||||
import requests
|
||||
from loguru import logger
|
||||
from create_bot import request_url, api_token
|
||||
from operator import itemgetter
|
||||
from loguru import logger
|
||||
|
||||
def check_register(tg_id):
|
||||
return False
|
||||
|
||||
def check_admin(tg_id):
|
||||
return 0
|
17
bot/routes.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from fastapi import APIRouter
|
||||
from aiogram import types, Dispatcher, Bot
|
||||
from create_bot import bot, token
|
||||
from config import dp
|
||||
|
||||
|
||||
bot_api_router = APIRouter(
|
||||
prefix=f'/bot/wh',
|
||||
)
|
||||
|
||||
|
||||
@bot_api_router.post(f'/{token}', include_in_schema=False)
|
||||
async def bot_webhook(update: dict):
|
||||
telegram_update = types.Update(**update)
|
||||
Dispatcher.set_current(dp)
|
||||
Bot.set_current(bot)
|
||||
await dp.process_update(telegram_update)
|
7
bot/scripts/gunicorn.sh
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
gunicorn main_api:app -w 17 -b 0.0.0.0:7313 -k uvicorn.workers.UvicornWorker --timeout 600
|
8
bot/scripts/start.sh
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
set -o xtrace
|
||||
|
||||
uvicorn main_api:app --host 0.0.0.0 --port 7313 --log-config /app/log.ini
|
23
bot/wrapper.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from handlers.register_handlers import register_all_handlers
|
||||
from create_bot import bot
|
||||
from aiogram import Bot, Dispatcher
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from loguru import logger
|
||||
from aiogram import Router
|
||||
|
||||
logger.add("logs.log", format = "{time} | {module} : {function} | {level} | {message}", level = "INFO", rotation = "1 week", compression = "zip")#, serialize = True)
|
||||
|
||||
async def run_bot():
|
||||
storage = MemoryStorage()
|
||||
dp = Dispatcher(storage=storage)
|
||||
|
||||
# Create a router to register handlers
|
||||
router = Router()
|
||||
|
||||
# Register all handlers
|
||||
register_all_handlers(router)
|
||||
|
||||
# Mount the router into the dispatcher
|
||||
dp.include_router(router)
|
||||
|
||||
await dp.start_polling(bot)
|