fix: handle PEP 668 env in /update; harden reminders and CSV import; add ptb job-queue extra
This commit is contained in:
+18
-12
@@ -418,8 +418,8 @@ async def check_and_send_reminders(context: CallbackContext):
|
||||
message += " 将会自动续费。"
|
||||
keyboard = None
|
||||
|
||||
elif renewal_type == 'manual' and sub['reminder_days'] > 0:
|
||||
reminder_date = due_date - datetime.timedelta(days=sub['reminder_days'])
|
||||
elif renewal_type == 'manual' and int(sub['reminder_days'] or 0) > 0:
|
||||
reminder_date = due_date - datetime.timedelta(days=int(sub['reminder_days']))
|
||||
if reminder_date == today:
|
||||
days_left = (due_date - today).days
|
||||
days_text = f"<b>{days_left}天后</b>" if days_left > 0 else "<b>今天</b>"
|
||||
@@ -440,7 +440,7 @@ async def check_and_send_reminders(context: CallbackContext):
|
||||
logger.info(f"Reminder sent for sub_id {sub['id']}")
|
||||
|
||||
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['id']}: {e}")
|
||||
# --- 命令处理器 ---
|
||||
async def start(update: Update, context: CallbackContext):
|
||||
user_id = update.effective_user.id
|
||||
@@ -746,7 +746,7 @@ async def import_upload_received(update: Update, context: CallbackContext):
|
||||
renewal_base = str(row['renewal_base']).lower().strip()
|
||||
if renewal_base not in valid_renewal_bases:
|
||||
raise ValueError(f"无效续订起算方式: {renewal_base}")
|
||||
notes = str(row['notes']).strip() if pd.notna(row['notes']) else None
|
||||
notes = str(row['notes']).strip() if ('notes' in df.columns and pd.notna(row['notes'])) else None
|
||||
if notes and len(notes) > MAX_NOTES_LEN:
|
||||
raise ValueError(f"备注过长(>{MAX_NOTES_LEN})")
|
||||
name = str(row['name']).strip()
|
||||
@@ -1804,15 +1804,18 @@ async def update_bot(update: Update, context: CallbackContext):
|
||||
await update.message.reply_text(f"更新失败(reset):\n<code>{escape_html(err)}</code>", parse_mode='HTML')
|
||||
return
|
||||
|
||||
pip_proc = await asyncio.to_thread(
|
||||
_run_cmd,
|
||||
[sys.executable, "-m", "pip", "install", "-r", "requirements.txt"],
|
||||
repo_dir
|
||||
)
|
||||
pip_cmd = [sys.executable, "-m", "pip", "install", "-r", "requirements.txt"]
|
||||
pip_proc = await asyncio.to_thread(_run_cmd, pip_cmd, repo_dir)
|
||||
if pip_proc.returncode != 0:
|
||||
err = (pip_proc.stderr or pip_proc.stdout or "未知错误").strip()
|
||||
await update.message.reply_text(f"依赖安装失败:\n<code>{escape_html(err[-1800:])}</code>", parse_mode='HTML')
|
||||
return
|
||||
pip_output = (pip_proc.stderr or "") + (pip_proc.stdout or "")
|
||||
# Debian/Ubuntu 的系统托管 Python(PEP 668)会拒绝直接安装,需加 --break-system-packages
|
||||
if "externally-managed-environment" in pip_output:
|
||||
await update.message.reply_text("检测到系统托管的 Python 环境(PEP 668),改用 --break-system-packages 重试…")
|
||||
pip_proc = await asyncio.to_thread(_run_cmd, pip_cmd + ["--break-system-packages"], repo_dir)
|
||||
if pip_proc.returncode != 0:
|
||||
err = (pip_proc.stderr or pip_proc.stdout or "未知错误").strip()
|
||||
await update.message.reply_text(f"依赖安装失败:\n<code>{escape_html(err[-1800:])}</code>", parse_mode='HTML')
|
||||
return
|
||||
|
||||
await update.message.reply_text(
|
||||
f"更新完成({escape_html(remote_name)} {escape_html(branch_name)}),正在重启机器人…",
|
||||
@@ -1870,6 +1873,9 @@ def main():
|
||||
time=datetime.time(hour=9, minute=0, tzinfo=datetime.timezone(datetime.timedelta(hours=8))),
|
||||
name='daily_reminders'
|
||||
)
|
||||
# 启动后稍作等待补跑一次,避免重启导致当天的提醒被跳过(函数内部按 last_reminded_date 去重)
|
||||
app.job_queue.run_once(check_and_send_reminders, when=datetime.timedelta(seconds=15),
|
||||
name='startup_reminder_catchup')
|
||||
logger.info("Daily reminder job scheduled.")
|
||||
|
||||
application.post_init = post_init
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
python-telegram-bot>=20.0
|
||||
python-telegram-bot[job-queue]>=20.0
|
||||
pandas
|
||||
matplotlib
|
||||
python-dateutil
|
||||
|
||||
Reference in New Issue
Block a user