Skip to content

Commit 4847f8a

Browse files
committed
fix: Fetch channel title in real-time
1 parent 7c5a77f commit 4847f8a

File tree

2 files changed

+113
-39
lines changed

2 files changed

+113
-39
lines changed
+98-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import sqlite3
3+
import os
34

45
logger = logging.getLogger(__name__)
56

@@ -8,59 +9,124 @@ class DatabaseManager:
89
def __init__(self, db_path="data/bot_data.sqlite"):
910
"""Initialize database connection and create tables if not exist"""
1011
self.db_path = db_path
12+
self._ensure_db_directory()
1113
self._create_tables()
14+
self._migrate_schema()
15+
16+
def _ensure_db_directory(self):
17+
"""Ensure the database directory exists and has proper permissions"""
18+
db_dir = os.path.dirname(self.db_path)
19+
if not os.path.exists(db_dir):
20+
try:
21+
os.makedirs(db_dir, mode=0o755)
22+
except OSError as e:
23+
logger.error(f"Failed to create database directory: {e}")
24+
raise
25+
elif not os.access(db_dir, os.W_OK):
26+
logger.error(f"Database directory {db_dir} is not writable")
27+
raise PermissionError(f"Database directory {db_dir} is not writable")
1228

1329
def _get_connection(self):
14-
"""Create and return a database connection"""
15-
return sqlite3.connect(self.db_path)
30+
"""Create and return a database connection with proper error handling"""
31+
try:
32+
conn = sqlite3.connect(self.db_path, timeout=20)
33+
# Enable foreign keys and WAL mode for better concurrency
34+
conn.execute("PRAGMA foreign_keys = ON")
35+
conn.execute("PRAGMA journal_mode = WAL")
36+
return conn
37+
except sqlite3.Error as e:
38+
logger.error(f"Failed to connect to database: {e}")
39+
raise
1640

1741
def _create_tables(self):
1842
"""Create necessary tables if they don't exist"""
19-
with self._get_connection() as conn:
20-
cursor = conn.cursor()
21-
cursor.execute(
43+
try:
44+
with self._get_connection() as conn:
45+
cursor = conn.cursor()
46+
cursor.execute(
47+
"""
48+
CREATE TABLE IF NOT EXISTS channels (
49+
channel_id INTEGER PRIMARY KEY,
50+
added_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
51+
)
2252
"""
23-
CREATE TABLE IF NOT EXISTS channels (
24-
channel_id INTEGER PRIMARY KEY,
25-
channel_title TEXT,
26-
added_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
2753
)
28-
"""
29-
)
30-
conn.commit()
54+
conn.commit()
55+
except sqlite3.Error as e:
56+
logger.error(f"Failed to create tables: {e}")
57+
raise
58+
59+
def _migrate_schema(self):
60+
"""Migrate the database schema if needed"""
61+
try:
62+
with self._get_connection() as conn:
63+
cursor = conn.cursor()
64+
65+
# Check if old schema exists (with channel_title column)
66+
cursor.execute("PRAGMA table_info(channels)")
67+
columns = [column[1] for column in cursor.fetchall()]
68+
69+
if "channel_title" in columns:
70+
logger.info("Migrating database schema...")
71+
# Create temporary table with new schema
72+
cursor.execute(
73+
"""
74+
CREATE TABLE channels_new (
75+
channel_id INTEGER PRIMARY KEY,
76+
added_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
77+
)
78+
"""
79+
)
3180

32-
def add_channel(self, channel_id, channel_title):
81+
# Copy data from old table to new table
82+
cursor.execute(
83+
"INSERT INTO channels_new (channel_id, added_timestamp) SELECT channel_id, added_timestamp FROM channels"
84+
)
85+
86+
# Drop old table and rename new table
87+
cursor.execute("DROP TABLE channels")
88+
cursor.execute("ALTER TABLE channels_new RENAME TO channels")
89+
90+
conn.commit()
91+
logger.info("Database schema migration completed successfully")
92+
except sqlite3.Error as e:
93+
logger.error(f"Error during schema migration: {e}")
94+
raise
95+
96+
def add_channel(self, channel_id):
3397
"""Add a channel to the database"""
34-
with self._get_connection() as conn:
35-
cursor = conn.cursor()
36-
try:
98+
try:
99+
with self._get_connection() as conn:
100+
cursor = conn.cursor()
37101
cursor.execute(
38-
"INSERT OR REPLACE INTO channels (channel_id, channel_title) VALUES (?, ?)",
39-
(channel_id, channel_title),
102+
"INSERT OR REPLACE INTO channels (channel_id) VALUES (?)",
103+
(channel_id,),
40104
)
41105
conn.commit()
42-
except sqlite3.Error as e:
43-
logger.error(f"Error adding channel: {e}")
106+
except sqlite3.Error as e:
107+
logger.error(f"Error adding channel: {e}")
108+
raise
44109

45110
def remove_channel(self, channel_id):
46111
"""Remove a channel from the database"""
47-
with self._get_connection() as conn:
48-
cursor = conn.cursor()
49-
try:
112+
try:
113+
with self._get_connection() as conn:
114+
cursor = conn.cursor()
50115
cursor.execute(
51116
"DELETE FROM channels WHERE channel_id = ?", (channel_id,)
52117
)
53118
conn.commit()
54-
except sqlite3.Error as e:
55-
logger.error(f"Error removing channel: {e}")
119+
except sqlite3.Error as e:
120+
logger.error(f"Error removing channel: {e}")
121+
raise
56122

57123
def get_all_channels(self):
58124
"""Retrieve all channels from the database"""
59-
with self._get_connection() as conn:
60-
cursor = conn.cursor()
61-
try:
62-
cursor.execute("SELECT channel_id, channel_title FROM channels")
125+
try:
126+
with self._get_connection() as conn:
127+
cursor = conn.cursor()
128+
cursor.execute("SELECT channel_id FROM channels")
63129
return cursor.fetchall()
64-
except sqlite3.Error as e:
65-
logger.error(f"Error retrieving channels: {e}")
66-
return []
130+
except sqlite3.Error as e:
131+
logger.error(f"Error retrieving channels: {e}")
132+
raise

src/inline_post_bot/inline_telegram_bot.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ async def track_chats(
115115
if chat.type == Chat.CHANNEL:
116116
if not was_member and is_member:
117117
logger.info("Bot added to channel: %s", chat.title)
118-
self.db_manager.add_channel(chat.id, chat.title or "Unnamed Channel")
118+
self.db_manager.add_channel(chat.id)
119119
elif was_member and not is_member:
120120
logger.info("Bot removed from channel: %s", chat.title)
121121
self.db_manager.remove_channel(chat.id)
@@ -127,23 +127,31 @@ async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
127127
return ConversationHandler.END
128128

129129
try:
130-
db_channels = self.db_manager.get_all_channels()
130+
try:
131+
db_channels = self.db_manager.get_all_channels()
132+
except Exception as db_error:
133+
logger.error(f"Database error: {db_error}")
134+
await update.message.reply_text(
135+
"Sorry, there was an error accessing the database. Please try again later."
136+
)
137+
return ConversationHandler.END
131138

132139
admin_channels = []
133-
for channel_id, channel_title in db_channels:
140+
for (channel_id,) in db_channels:
134141
try:
142+
chat = await context.bot.get_chat(channel_id)
135143
admins = await context.bot.get_chat_administrators(channel_id)
136-
137144
is_admin = any(admin.user.id == user.id for admin in admins)
138145

139146
if is_admin:
140147
admin_channels.append(
141-
{"id": channel_id, "title": channel_title}
148+
{"id": channel_id, "title": chat.title or "Unnamed Channel"}
142149
)
143150
except Exception as admin_check_error:
144151
logger.error(
145152
f"Error checking admins for {channel_id}: {admin_check_error}"
146153
)
154+
continue
147155

148156
if not admin_channels:
149157
await update.message.reply_text(
@@ -170,9 +178,9 @@ async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
170178
return CHANNEL_SELECTION
171179

172180
except Exception as e:
173-
logger.error(f"Error fetching admin channels: {e}")
181+
logger.error(f"Error in start command: {e}")
174182
await update.message.reply_text(
175-
"An error occurred while fetching your channels. Please try again."
183+
"An unexpected error occurred. Please try again later."
176184
)
177185
return ConversationHandler.END
178186

0 commit comments

Comments
 (0)