fix(security): sanitize DB field formatting and fix cron job duplication

This commit is contained in:
Xiaolan Bot
2026-02-22 23:52:50 +08:00
parent 81840dfa31
commit 3711dd362b

View File

@@ -126,6 +126,8 @@ def init_db():
cursor.execute("ALTER TABLE subscriptions ADD COLUMN reminder_on_due_date BOOLEAN DEFAULT TRUE") cursor.execute("ALTER TABLE subscriptions ADD COLUMN reminder_on_due_date BOOLEAN DEFAULT TRUE")
if 'notes' not in columns: if 'notes' not in columns:
cursor.execute("ALTER TABLE subscriptions ADD COLUMN notes TEXT") cursor.execute("ALTER TABLE subscriptions ADD COLUMN notes TEXT")
if 'last_reminded_date' not in columns:
cursor.execute("ALTER TABLE subscriptions ADD COLUMN last_reminded_date DATE")
cursor.execute(''' cursor.execute('''
CREATE TABLE IF NOT EXISTS categories ( CREATE TABLE IF NOT EXISTS categories (
@@ -346,9 +348,11 @@ def update_past_due_dates():
async def check_and_send_reminders(context: CallbackContext): async def check_and_send_reminders(context: CallbackContext):
logger.info("Running job: Checking for subscription reminders...") logger.info("Running job: Checking for subscription reminders...")
today = datetime.date.today() today = datetime.date.today()
today_str = today.strftime('%Y-%m-%d')
with get_db_connection() as conn: with get_db_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute("SELECT * FROM subscriptions WHERE reminders_enabled = TRUE AND next_due IS NOT NULL") # 过滤掉今天已经提醒过的订阅
cursor.execute("SELECT * FROM subscriptions WHERE reminders_enabled = TRUE AND next_due IS NOT NULL AND (last_reminded_date IS NULL OR last_reminded_date != ?)", (today_str,))
subs_to_check = cursor.fetchall() subs_to_check = cursor.fetchall()
for sub in subs_to_check: for sub in subs_to_check:
@@ -388,11 +392,15 @@ async def check_and_send_reminders(context: CallbackContext):
parse_mode='MarkdownV2', parse_mode='MarkdownV2',
reply_markup=keyboard reply_markup=keyboard
) )
# 记录今天已发送提醒
with get_db_connection() as update_conn:
update_cursor = update_conn.cursor()
update_cursor.execute("UPDATE subscriptions SET last_reminded_date = ? WHERE id = ?", (today_str, sub['id']))
update_conn.commit()
logger.info(f"Reminder sent for sub_id {sub['id']}")
except Exception as e: except Exception as e:
logger.error(f"Failed to process reminder for sub_id {sub.get('id', 'N/A')}: {e}") logger.error(f"Failed to process reminder for sub_id {sub.get('id', 'N/A')}: {e}")
# --- 命令处理器 --- # --- 命令处理器 ---
async def start(update: Update, context: CallbackContext): async def start(update: Update, context: CallbackContext):
user_id = update.effective_user.id user_id = update.effective_user.id
@@ -1311,7 +1319,7 @@ async def edit_new_value_received(update: Update, context: CallbackContext):
await update.effective_message.reply_text("错误:未选择要编辑的字段。") await update.effective_message.reply_text("错误:未选择要编辑的字段。")
return ConversationHandler.END return ConversationHandler.END
db_field = EDITABLE_SUB_FIELDS.get(field) db_field = EDITABLE_SUB_FIELDS.get(field)
if not db_field: if not db_field or not db_field.isidentifier():
if update.effective_message: if update.effective_message:
await update.effective_message.reply_text("错误:不允许编辑该字段。") await update.effective_message.reply_text("错误:不允许编辑该字段。")
logger.warning(f"Blocked unsafe field update attempt: {field}") logger.warning(f"Blocked unsafe field update attempt: {field}")