Skip to main content

日历提示

2024-6-18


日历提示是指像手机日历或者QQ提醒一样,设置在某个时间进行提示,例如在2024-6-18 12:00提醒吃午饭

功能设计

用户操作分为:添加提示消息、删除提示消息、查看提示消息

脚本还需做到:在指定时间发送提示消息、由于是每秒检测,不会在同一分钟内一直发送提示消息

因此在建库的时候,需要建多个字段来保证可以正常进行业务

main.py

首先需要修改的就是main.py中的schedule_tasks,之前的schedule_tasks是由于词云需要23:59发消息,这次还要添加一条检测日历提示,因此需修改为:

def schedule_tasks():
schedule.every(1).seconds.do(lambda: check_reminders(send_group_message))
schedule.every().day.at("23:59").do(generate_daily_wordcloud)

while True:
schedule.run_pending()
time.sleep(1)

init_ts_db.py

为了用户方便操作,这里使用一个id来进行删除

last_triggered即最后一次发送的时间,repeat代表的是重复的星期,因为用户可能会添加每周x的xx:xx做提醒某事

import sqlite3
import os

DATABASE_PATH = os.path.join(os.path.dirname(__file__), 'ts.db')

def create_db():
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS reminders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
group_id TEXT NOT NULL,
date TEXT,
time TEXT NOT NULL,
message TEXT NOT NULL,
repeat TEXT,
last_triggered TEXT
)
''')
conn.commit()
conn.close()

if __name__ == '__main__':
create_db()

ts.py

添加包括三种添加方式:

添加当天的xx:xx进行提示:/ts xx:xx message

添加今年的某月某日xx:xx进行提示:/ts xx-xx xx:xx message

添加重复的周几的xx:xx进行提示:/ts [1-7] xx:xx message

删除部分和查询部分跟其他的差不多,看代码

import re
import sqlite3
import logging
from datetime import datetime, timedelta
import os

DATABASE_PATH = os.path.join(os.path.dirname(__file__), 'ts.db')

def connect_db():
return sqlite3.connect(DATABASE_PATH)

def handle_ts_command(message, user_id, group_id, send_group_message):
try:
parts = message.split(maxsplit=2)
if len(parts) < 2:
send_group_message(group_id, "命令格式错误,请输入 /help ts查看帮助")
return

command = parts[1].lower()
if command == "info":
reminders = get_user_reminders(user_id, group_id)
if reminders:
reminders_text = "\n".join([f"{i+1}. {reminder['datetime']} {reminder['message']}" for i, reminder in enumerate(reminders)])
send_group_message(group_id, f"你的提醒:\n{reminders_text}")
else:
send_group_message(group_id, "你没有设置任何提醒。")
elif command == "del" and len(parts) == 3:
reminder_index = int(parts[2]) - 1
success = delete_user_reminder(user_id, group_id, reminder_index)
if success:
send_group_message(group_id, f"已删除提醒,序号为{reminder_index + 1}")
else:
send_group_message(group_id, f"未找到序号为{reminder_index + 1}的提醒。")
else:
match = re.match(r'^/ts (\d{1,2}-\d{1,2} \d{1,2}:\d{2}) (.+)$', message)
if match:
datetime_str = match.group(1)
reminder_message = match.group(2)
try:
date_time_obj = datetime.strptime(datetime_str, '%m-%d %H:%M')
if date_time_obj < datetime.now():
send_group_message(group_id, "不能设置过去的时间,请重新输入。")
return
date_str = f"{datetime.now().year}-{datetime_str.split()[0]}"
time_str = datetime_str.split()[1]
insert_reminder(user_id, group_id, date_str, time_str, reminder_message, None)
send_group_message(group_id, f"提醒已设置:{datetime_str} {reminder_message}")
except ValueError:
send_group_message(group_id, "日期时间格式错误,请使用 MM-DD HH:MM 格式")
else:
match = re.match(r'^/ts (\d{1,2}:\d{2}) (.+)$', message)
if match:
time_str = match.group(1)
reminder_message = match.group(2)
try:
time_obj = datetime.strptime(time_str, '%H:%M').time()
if time_obj.hour >= 24 or time_obj.minute >= 60:
send_group_message(group_id, "时间格式错误,请使用 HH:MM 格式")
return
if datetime.combine(datetime.now().date(), time_obj) < datetime.now():
send_group_message(group_id, "不能设置过去的时间,请重新输入。")
return
insert_reminder(user_id, group_id, datetime.now().strftime('%Y-%m-%d'), time_str, reminder_message, None)
send_group_message(group_id, f"提醒已设置:{time_str} {reminder_message}")
except ValueError:
send_group_message(group_id, "时间格式错误,请使用 HH:MM 格式")
else:
match = re.match(r'^/ts ([1-7]+) (\d{1,2}:\d{2}) (.+)$', message)
if match:
repeat_days = match.group(1)
time_str = match.group(2)
reminder_message = match.group(3)
if not all(day in '1234567' for day in repeat_days):
send_group_message(group_id, "重复日期格式错误,请使用1-7表示周一到周日。")
return
insert_reminder(user_id, group_id, None, time_str, reminder_message, repeat_days)
send_group_message(group_id, f"重复提醒已设置:每周{repeat_days}{time_str} {reminder_message}")
else:
send_group_message(group_id, "时间格式错误,请使用 HH:MM 格式或 MM-DD HH:MM 格式")
except Exception as e:
logging.error(f"Error processing /ts command: {e}")
send_group_message(group_id, "命令处理过程中发生错误,请重试。")

def get_user_reminders(user_id, group_id):
conn = connect_db()
cursor = conn.cursor()
cursor.execute('''
SELECT id, date, time, message, repeat
FROM reminders
WHERE user_id = ? AND group_id = ?
''', (user_id, group_id))
rows = cursor.fetchall()
conn.close()
reminders = []
for row in rows:
reminder_id, date, time, message, repeat = row
datetime_str = f"{date} {time}" if date else f"每周{repeat}{time}"
reminders.append({
'id': reminder_id,
'datetime': datetime_str,
'message': message,
'repeat': repeat
})
return reminders

def delete_user_reminder(user_id, group_id, reminder_index):
conn = connect_db()
cursor = conn.cursor()
cursor.execute('''
SELECT id FROM reminders
WHERE user_id = ? AND group_id = ?
''', (user_id, group_id))
rows = cursor.fetchall()
if reminder_index < 0 or reminder_index >= len(rows):
return False
reminder_id = rows[reminder_index][0]
cursor.execute('''
DELETE FROM reminders
WHERE id = ?
''', (reminder_id,))
conn.commit()
conn.close()
return True

def insert_reminder(user_id, group_id, date, time, message, repeat):
conn = connect_db()
cursor = conn.cursor()
cursor.execute('''
INSERT INTO reminders (user_id, group_id, date, time, message, repeat, last_triggered)
VALUES (?, ?, ?, ?, ?, ?, NULL)
''', (user_id, group_id, date, time, message, repeat))
conn.commit()
conn.close()

def check_reminders(send_group_message):
now = datetime.now()
now_str = now.strftime('%Y-%m-%d %H:%M')
one_minute_ago_str = (now - timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M')
conn = connect_db()
cursor = conn.cursor()
cursor.execute('''
SELECT id, user_id, group_id, message, repeat, last_triggered
FROM reminders
WHERE (datetime(date || ' ' || time) <= ? OR (repeat IS NOT NULL AND time = ?))
AND (last_triggered IS NULL OR last_triggered < ?)
''', (now_str, now.strftime('%H:%M'), one_minute_ago_str))
rows = cursor.fetchall()

for row in rows:
reminder_id, user_id, group_id, message, repeat, last_triggered = row
logging.info(f"Sending reminder for user_id: {user_id}, group_id: {group_id}, message: {message}")
send_group_message(group_id, f"[CQ:at,qq={user_id}] {message}")

now_str_for_update = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

if not repeat:
cursor.execute('DELETE FROM reminders WHERE id = ?', (reminder_id,))
else:
next_date = get_next_date(repeat)
cursor.execute('UPDATE reminders SET last_triggered = ?, date = ? WHERE id = ?',
(now_str_for_update, next_date, reminder_id))

conn.commit()
conn.close()

def get_next_date(repeat, current_date=None):
if not current_date:
current_date = datetime.now().strftime('%Y-%m-%d')
current_day = datetime.strptime(current_date, '%Y-%m-%d').weekday() + 1 # Monday is 1 and Sunday is 7
repeat_days = [int(day) for day in repeat]
next_day = min(
[day for day in repeat_days if day > current_day] + [day + 7 for day in repeat_days if day <= current_day])
delta_days = next_day - current_day
return (datetime.strptime(current_date, '%Y-%m-%d') + timedelta(days=delta_days)).strftime('%Y-%m-%d')