Compare commits

..

4 Commits
bot ... main

Author SHA1 Message Date
Arseniy Sitnikov
44e2d34be8
Add files via upload 2024-12-17 15:09:24 +03:00
Arseniy Sitnikov
ed66b2a3d8
Update .gitignore 2024-12-07 10:01:09 +03:00
Даня Вакуленков
c1869e90c2 Add .DS_Store to .gitignore 2024-10-28 00:12:24 +03:00
Даня Вакуленков
faa240dff0 Add .DS_Store to .gitignore 2024-10-28 00:11:34 +03:00
39 changed files with 169 additions and 522 deletions

BIN
.DS_Store vendored

Binary file not shown.

169
.gitignore vendored Normal file
View File

@ -0,0 +1,169 @@
.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 Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
bot/.DS_Store vendored

Binary file not shown.

View File

@ -1,21 +0,0 @@
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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -1,64 +0,0 @@
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}

View File

@ -1,27 +0,0 @@
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()

View File

@ -1,24 +0,0 @@
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 = {}

View File

@ -1 +0,0 @@
from cgitb import handler

View File

@ -1,103 +0,0 @@
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()

View File

@ -1,27 +0,0 @@
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_"))

View File

@ -1,73 +0,0 @@
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)

View File

@ -1,21 +0,0 @@
[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

View File

@ -1,8 +0,0 @@
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 и не зарегистрирован

View File

@ -1,15 +0,0 @@
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()

View File

@ -1,52 +0,0 @@
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()

View File

@ -1,11 +0,0 @@
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))

View File

@ -1,6 +0,0 @@
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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 KiB

View File

@ -1,14 +0,0 @@
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

View File

@ -1,17 +0,0 @@
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)

View File

@ -1,7 +0,0 @@
#!/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

View File

@ -1,8 +0,0 @@
#!/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

View File

@ -1,23 +0,0 @@
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)