-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
executable file
·160 lines (126 loc) · 4.56 KB
/
main.py
File metadata and controls
executable file
·160 lines (126 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/env python3
"""
News Hack Bot - Agregador de Notícias de Hacking e Cibersegurança
Main entry point for the bot
"""
import asyncio
import logging
import os
import sys
import signal
from pathlib import Path
from dotenv import load_dotenv
# Add src to path
sys.path.insert(0, str(Path(__file__).parent))
from src.database import Database
from src.rss_parser import RSSParser
from src.telegram_bot import TelegramBot
from src.scheduler import FeedScheduler
# Load environment variables
load_dotenv()
# Configure logging
LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')
logging.basicConfig(
level=getattr(logging, LOG_LEVEL),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('logs/newshack.log'),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
# Global flag for graceful shutdown
shutdown_event = asyncio.Event()
async def main():
"""Main function to run the bot"""
logger.info("=" * 60)
logger.info("Starting News Hack Bot")
logger.info("=" * 60)
# Get configuration from environment
bot_token = os.getenv('TELEGRAM_BOT_TOKEN')
chat_id = os.getenv('TELEGRAM_CHAT_ID')
check_interval = int(os.getenv('CHECK_INTERVAL', '30'))
db_path = os.getenv('DATABASE_PATH', './data/news.db')
if not bot_token:
logger.error("TELEGRAM_BOT_TOKEN not found in environment variables!")
sys.exit(1)
if not chat_id:
logger.warning("TELEGRAM_CHAT_ID not set - automatic sending disabled")
# Ensure logs directory exists
Path('logs').mkdir(exist_ok=True)
# Initialize components
logger.info("Initializing components...")
try:
# Database
db = Database(db_path)
logger.info("✓ Database initialized")
# RSS Parser
parser = RSSParser(timeout=30, max_retries=3)
logger.info("✓ RSS Parser initialized")
# Telegram Bot
bot = TelegramBot(bot_token, db, parser)
await bot.initialize()
logger.info("✓ Telegram Bot initialized")
# Scheduler
if chat_id:
scheduler = FeedScheduler(db, parser, bot, chat_id, check_interval)
logger.info("✓ Scheduler initialized")
else:
scheduler = None
logger.warning("⚠ Scheduler disabled (no CHAT_ID)")
logger.info("=" * 60)
logger.info("News Hack Bot is running!")
logger.info("=" * 60)
# Setup signal handlers for graceful shutdown
def signal_handler(signum, frame):
logger.info(f"Received signal {signum}, initiating shutdown...")
shutdown_event.set()
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
# Start polling and scheduler
tasks = []
# Start bot polling
tasks.append(asyncio.create_task(bot.application.updater.start_polling()))
# Start scheduler if enabled
if scheduler:
tasks.append(asyncio.create_task(scheduler.run()))
# Wait for shutdown signal
await shutdown_event.wait()
logger.info("Shutdown signal received, stopping tasks...")
# Stop polling
await bot.application.updater.stop()
# Stop scheduler
if scheduler:
scheduler.stop()
# Cancel all tasks
for task in tasks:
if not task.done():
task.cancel()
# Wait for tasks to complete
await asyncio.gather(*tasks, return_exceptions=True)
except KeyboardInterrupt:
logger.info("Received interrupt signal, shutting down...")
except Exception as e:
logger.error(f"Fatal error: {e}", exc_info=True)
finally:
# Cleanup
logger.info("Cleaning up...")
try:
if 'bot' in locals() and bot:
await bot.shutdown()
except Exception as e:
logger.warning(f"Error during bot shutdown: {e}")
try:
if 'db' in locals() and db:
db.close()
except Exception as e:
logger.warning(f"Error closing database: {e}")
logger.info("News Hack Bot stopped")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
logger.info("Bot stopped by user")
except Exception as e:
logger.error(f"Unexpected error: {e}", exc_info=True)
sys.exit(1)