Бот + прокси
This commit is contained in:
0
bot/__init__.py
Normal file
0
bot/__init__.py
Normal file
29
bot/__main__.py
Normal file
29
bot/__main__.py
Normal 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
30
bot/commands.py
Normal 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
12
bot/factory.py
Normal 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
|
||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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
18
main.py
Normal 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())
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
|
||||||
5
utils.py
5
utils.py
@@ -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:
|
||||||
# Обновление Тегов
|
# Обновление Тегов
|
||||||
|
|||||||
Reference in New Issue
Block a user