Бот + прокси

This commit is contained in:
2026-04-30 16:34:57 +03:00
parent ddec6094c2
commit 5dc9c8f0d1
11 changed files with 129 additions and 19 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

0
bot/__init__.py Normal file
View File

29
bot/__main__.py Normal file
View File

@@ -0,0 +1,29 @@
import logging
import asyncio
import sys
from bot.commands import router as command_router
from bot.factory import bot, dp, init_bot_and_dp
from config import config
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(name)s:%(lineno)d %(levelname)s %(message)s',
handlers=[
logging.FileHandler('app.log', encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
async def main():
bot, dp = init_bot_and_dp(f"socks5://{config.PROXY_URL}", config.BOT_TOKEN)
dp.include_router(command_router)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())

30
bot/commands.py Normal file
View File

@@ -0,0 +1,30 @@
from argparse import Namespace
from aiogram import Router
from aiogram.filters.command import Command, CommandStart
from aiogram.types import Message
from bot.factory import bot
from tracker.commands import end_workday
router = Router()
@router.message(CommandStart())
async def start_command(message: Message):
await message.answer(f"Привет, {message.from_user.first_name}!")
@router.message(Command("track"))
async def track_command(message: Message):
await message.answer("Эта фича пока в разработке, но скоро она поможет стартовать и останавливать таймер.")
@router.message(Command("end"))
async def end_command(message: Message):
args = message.text.replace("/end", "").strip().split()
if "-i" in args or "--init-db" in args:
args = Namespace(init_db=True)
await message.answer("Начинаю процесс занесения трудочасов...")
await end_workday(args, bot, message.from_user.id)
await message.answer("Трудочасы занесены!")

12
bot/factory.py Normal file
View File

@@ -0,0 +1,12 @@
from aiogram import Bot, Dispatcher
from aiogram.client.session.aiohttp import AiohttpSession
bot: Bot = None # type: ignore
dp: Dispatcher = None
def init_bot_and_dp(proxy_url: str, token: str):
global bot, dp
bot = Bot(token=token, session=AiohttpSession(proxy=proxy_url) if proxy_url else None)
dp = Dispatcher()
return bot, dp

View File

@@ -16,6 +16,9 @@ class Config(BaseSettings):
REDMINE_TOKEN: str REDMINE_TOKEN: str
USER_ID: str = None USER_ID: str = None
WORKSPACE_ID: str = None WORKSPACE_ID: str = None
BOT_TOKEN: str
PROXY_URL: str
MODE: str = "prod" MODE: str = "prod"

View File

@@ -2,4 +2,7 @@ REDMINE_TOKEN=
CLOCKIFY_TOKEN= CLOCKIFY_TOKEN=
USER_ID= USER_ID=
WORKSPACE_ID= WORKSPACE_ID=
TRIAL_END_DATE= TRIAL_END_DATE=
BOT_TOKEN=
PROXY_URL=

18
main.py Normal file
View File

@@ -0,0 +1,18 @@
import asyncio
import logging
import sys
from tracker.commands import end_workday
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(name)s:%(lineno)d %(levelname)s %(message)s',
handlers=[
logging.FileHandler('app.log', encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
if __name__ == "__main__":
asyncio.run(end_workday())

View File

@@ -1,15 +1,28 @@
aiofiles==25.1.0
aiogram==3.27.0
aiohappyeyeballs==2.6.1
aiohttp==3.13.5
aiohttp_socks==0.11.0
aiosignal==1.4.0
annotated-types==0.7.0 annotated-types==0.7.0
asarPy==1.0.1 asarPy==1.0.1
attrs==26.1.0
certifi==2025.4.26 certifi==2025.4.26
charset-normalizer==3.4.2 charset-normalizer==3.4.2
colorama==0.4.6 colorama==0.4.6
frozenlist==1.8.0
idna==3.10 idna==3.10
magic-filter==1.0.12
multidict==6.7.1
propcache==0.4.1
pydantic==2.11.4 pydantic==2.11.4
pydantic-settings==2.9.1 pydantic-settings==2.9.1
pydantic_core==2.33.2 pydantic_core==2.33.2
python-dotenv==1.1.0 python-dotenv==1.1.0
python-socks==2.8.1
requests==2.32.3 requests==2.32.3
tqdm==4.67.1 tqdm==4.67.1
typing-inspection==0.4.0 typing-inspection==0.4.0
typing_extensions==4.13.2 typing_extensions==4.13.2
urllib3==2.4.0 urllib3==2.4.0
yarl==1.23.0

View File

@@ -1,24 +1,20 @@
import logging import logging
import sys from argparse import Namespace
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(name)s:%(lineno)d %(levelname)s %(message)s',
handlers=[
logging.FileHandler('app.log', encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
from aiogram import Bot
from colorama import Fore # noqa: E402 from colorama import Fore # noqa: E402
from bot.factory import bot
from config import arg_parser, clock, config, db, red # noqa: E402 from config import arg_parser, clock, config, db, red # noqa: E402
from utils import check_envs, db_update, format_date, get_start_end_dates # noqa: E402 from utils import check_envs, db_update, format_date, get_start_end_dates # noqa: E402
def main(): async def end_workday(
args = arg_parser.parse_args() args: Namespace = None,
bot: Bot = None,
user_id: int = None
):
args = args or arg_parser.parse_args()
if is_debug := args.debug: if is_debug := args.debug:
config.MODE = "debug" config.MODE = "debug"
@@ -47,7 +43,7 @@ def main():
} }
db.insert_user(**clock_user, **red_user) db.insert_user(**clock_user, **red_user)
if args.init_db: if args.init_db:
db_update() await db_update(bot)
activities = sorted(clock.get_activities( activities = sorted(clock.get_activities(
**{ **{
@@ -58,16 +54,19 @@ def main():
), key=lambda x: x.date_start) ), key=lambda x: x.date_start)
if not activities: if not activities:
logger.info(Fore.YELLOW + "Нет задач для занесения трудочасов" + Fore.RESET) logger.info(Fore.YELLOW + "Нет задач для занесения трудочасов" + Fore.RESET)
if bot:
await bot.send_message(user_id, "Нет задач для занесения трудочасов")
return return
db.insert_activities(activities) db.insert_activities(activities)
try: try:
tracked_activities = red.track_activities(activities) tracked_activities = red.track_activities(activities)
if bot:
await bot.send_message(user_id, f"Трудочасы занесены: {len(tracked_activities)}/{len(activities)}.")
clock.mark_tracked(tracked_activities) clock.mark_tracked(tracked_activities)
if not is_debug: if not is_debug:
db.insert_time_entries(tracked_activities) db.insert_time_entries(tracked_activities)
db.insert_activities(tracked_activities) db.insert_activities(tracked_activities)
except Exception as e: except Exception as e:
if bot:
await bot.send_message(user_id, f"Ошибка при трекинге трудочасов: {e}")
logger.error(e) logger.error(e)
if __name__ == "__main__":
main()

View File

@@ -5,6 +5,7 @@ import os
import re import re
from typing import Optional from typing import Optional
from aiogram import Bot
from colorama import Fore from colorama import Fore
from config import config from config import config
@@ -40,9 +41,11 @@ def format_date(date: datetime) -> datetime:
def parse_task_id(tag: str) -> int: def parse_task_id(tag: str) -> int:
return int(re.search(r"^(?P<task_id>\d{5})", tag).group("task_id")) return int(re.search(r"^(?P<task_id>\d{5})", tag).group("task_id"))
def db_update(): async def db_update(bot: Bot = None, user_id: int = None):
from config import clock, db, red from config import clock, db, red
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET) logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
if bot:
await bot.send_message(user_id, "Обновление базы данных...")
try: try:
# Обновление Тегов # Обновление Тегов