import schedule import time import logging import random import os from datetime import datetime from update_lottery import LotteryUpdater from app.services.prediction_service import PredictionService from app.services.telegram_bot import send_message from app.core.database import SessionLocal from app.models.lottery import SSQLotteryBetRecord, DLTLotteryBetRecord, SSQLottery, DLTLottery # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filename='lottery_scheduler.log' ) logger = logging.getLogger(__name__) class LotteryScheduler: def __init__(self): self.updater = LotteryUpdater() def update_lottery_data_job(self): """每天早上6点更新开奖数据任务""" try: logger.info("开始执行早上6点更新开奖数据任务...") # 更新双色球数据 logger.info("开始更新双色球数据...") ssq_result = self.updater.update_lottery_data('ssq') logger.info(f"双色球数据更新完成: {ssq_result}") # 更新大乐透数据 logger.info("开始更新大乐透数据...") dlt_result = self.updater.update_lottery_data('dlt') logger.info(f"大乐透数据更新完成: {dlt_result}") # 检查中奖情况 db = SessionLocal() try: logger.info("开始检查双色球中奖情况...") self.updater.check_and_update_bet_wins('ssq', db) logger.info("双色球中奖检查完成") logger.info("开始检查大乐透中奖情况...") self.updater.check_and_update_bet_wins('dlt', db) logger.info("大乐透中奖检查完成") finally: db.close() logger.info("早上6点更新开奖数据任务完成") except Exception as e: logger.error(f"早上6点更新开奖数据任务失败: {str(e)}") def generate_daily_recommendations_job(self): """每天下午5点生成拼盘推荐任务,推送内容与prediction.py recommend_today接口一致""" try: logger.info("开始执行下午5点生成拼盘推荐任务...") db = SessionLocal() try: # 判断彩种 weekday = datetime.datetime.now().isoweekday() if weekday == 5: logger.info("周五休息,不推送推荐") return FIXED_SSQ = {'red': [4, 6, 7, 12, 18, 19], 'blue': [9]} FIXED_DLT = {'red': [4, 6, 9, 18, 19], 'blue': [7, 12]} if weekday in [1, 3, 6]: lottery_type = 'dlt' fixed = FIXED_DLT title = "你好,帮忙买下大乐透。" dlt_append = True else: lottery_type = 'ssq' fixed = FIXED_SSQ title = "你好,帮忙买下双色球。" dlt_append = False # 生成batch_id today = datetime.datetime.now().strftime('%Y%m%d') batch_id = f"{today}-{random.randint(1000, 9999)}" # 推荐4注(集成预测+智能选号补足) service = PredictionService(db) pred = service.get_ensemble_prediction( lottery_type, periods=200) recs = pred.get('recommendations', []) if pred.get( 'success') else [] results = [] used_numbers = set() # 确定模型和推荐类型 if weekday in [1, 3, 6]: # 周一、三、六 BetModel = DLTLotteryBetRecord LotteryModel = DLTLottery recommend_type = '集成预测-每日推荐' else: # 周二、四、日 BetModel = SSQLotteryBetRecord LotteryModel = SSQLottery recommend_type = '集成预测-每日推荐' # 先取集成预测推荐 for rec in recs: if len(results) >= 4: break red = rec.get('numbers') blue = [rec.get('blue')] if rec.get( 'blue') is not None else rec.get('blues', []) if not red or not blue: continue numbers = ','.join( f"{n:02d}" for n in red) + '|' + ','.join(f"{n:02d}" for n in blue) if numbers in used_numbers: continue used_numbers.add(numbers) # 保存到数据库 bet = BetModel( batch_id=batch_id, issue='PENDING', # 投注时不设置期号,等开奖后匹配 numbers=numbers, recommend_type=rec.get('method', recommend_type) ) db.add(bet) db.commit() db.refresh(bet) results.append({ 'id': bet.id, 'batch_id': batch_id, 'issue': 'PENDING', # 期号待定 'numbers': numbers, 'red': red, 'blue': blue, 'recommend_type': rec.get('method', recommend_type) }) # 补足到4注 from app.services.analysis_service import LotteryAnalysisService analysis_service = LotteryAnalysisService(db) while len(results) < 4: smart = analysis_service.generate_smart_numbers( lottery_type, strategy='balanced', count=1) if not smart: break red = smart[0].get('red_numbers') blue = smart[0].get('blue_numbers') numbers = ','.join( f"{n:02d}" for n in red) + '|' + ','.join(f"{n:02d}" for n in blue) if numbers in used_numbers: continue used_numbers.add(numbers) # 保存到数据库 bet = BetModel( batch_id=batch_id, issue='PENDING', # 投注时不设置期号,等开奖后匹配 numbers=numbers, recommend_type='智能选号补足' ) db.add(bet) db.commit() db.refresh(bet) results.append({ 'id': bet.id, 'batch_id': batch_id, 'issue': 'PENDING', # 期号待定 'numbers': numbers, 'red': red, 'blue': blue, 'recommend_type': '智能选号补足' }) # 组装推送内容 msg_lines = [title] red_str = ' '.join(f"{n:02d}" for n in fixed['red']) blue_str = ' '.join(f"{n:02d}" for n in fixed['blue']) msg_lines.append(f"红球:{red_str} 蓝球:{blue_str}") for rec in results: red_str = ' '.join(f"{n:02d}" for n in rec['red']) blue_str = ' '.join(f"{n:02d}" for n in rec['blue']) msg_lines.append(f"红球:{red_str} 蓝球:{blue_str}") if dlt_append: msg_lines.append("都追加,谢谢。") msg_lines.append("\n快乐8,单式,选十") for _ in range(3): nums = sorted(random.sample(range(1, 81), 10)) msg_lines.append(' '.join(f"{n:02d}" for n in nums)) # 推送到Telegram try: logger.info("开始推送到Telegram...") token = os.getenv("TELEGRAM_BOT_TOKEN") chat_id = os.getenv("TELEGRAM_CHAT_ID") result = send_message( '\n'.join(msg_lines), token=token, chat_id=chat_id) if result: logger.info("Telegram推送成功") logger.info(f"Telegram返回: {result}") else: logger.warning("Telegram推送失败") except Exception as e: logger.error(f"Telegram推送失败: {str(e)}") logger.info("下午5点生成拼盘推荐任务完成") finally: db.close() except Exception as e: logger.error(f"下午5点生成拼盘推荐任务失败: {str(e)}") def check_previous_day_wins_job(self): """每天早上9点半幽默播报昨日号码命运""" try: logger.info("开始执行早上9点半幽默播报任务...") from datetime import timedelta yesterday = datetime.now() - timedelta(days=1) target_date = yesterday.strftime('%Y-%m-%d') current_weekday = datetime.now().isoweekday() if current_weekday == 6: # 周六 logger.info("周六休息,不推送中奖检查") return if current_weekday in [1, 3, 5, 7]: lottery_type = 'ssq' BetModel = SSQLotteryBetRecord LotteryModel = SSQLottery fixed_numbers = {'red': [4, 6, 7, 12, 18, 19], 'blue': [9]} else: lottery_type = 'dlt' BetModel = DLTLotteryBetRecord LotteryModel = DLTLottery fixed_numbers = {'red': [4, 6, 9, 18, 19], 'blue': [7, 12]} db = SessionLocal() try: target_batch_id_pattern = f"{yesterday.strftime('%Y%m%d')}%" bet_records = db.query(BetModel).filter( BetModel.batch_id.like(target_batch_id_pattern) ).all() self.updater.check_and_update_bet_wins(lottery_type, db) updated_records = db.query(BetModel).filter( BetModel.batch_id.like(target_batch_id_pattern) ).all() last_draw = db.query(LotteryModel).filter( LotteryModel.open_time == yesterday.date()).first() open_code_str = "" if last_draw: if lottery_type == 'ssq': open_red = [last_draw.red_ball_1, last_draw.red_ball_2, last_draw.red_ball_3, last_draw.red_ball_4, last_draw.red_ball_5, last_draw.red_ball_6] open_blue = [last_draw.blue_ball] red_str = ' '.join(f"{n:02d}" for n in open_red) blue_str = ' '.join(f"{n:02d}" for n in open_blue) open_code_str = f"{red_str} | {blue_str}" else: open_red = [last_draw.front_ball_1, last_draw.front_ball_2, last_draw.front_ball_3, last_draw.front_ball_4, last_draw.front_ball_5] open_blue = [last_draw.back_ball_1, last_draw.back_ball_2] red_str = ' '.join(f"{n:02d}" for n in open_red) blue_str = ' '.join(f"{n:02d}" for n in open_blue) open_code_str = f"{red_str} | {blue_str}" # 固定号码开奖比对 fixed_result = None if last_draw: bet_red = fixed_numbers['red'] bet_blue = fixed_numbers['blue'] red_hit = len(set(bet_red) & set(open_red)) blue_hit = len(set(bet_blue) & set(open_blue)) win_level, win_amount = self.updater.calc_prize( lottery_type, red_hit, blue_hit, bet_red, bet_blue, open_red, open_blue) fixed_result = { 'red': bet_red, 'blue': bet_blue, 'win_level': win_level, 'win_amount': win_amount } # 幽默短语 miss_phrases = [ "擦肩而过", "与大奖无缘", "继续努力", "还差亿点点", "中奖是种信仰", "大奖说:明天见!", "陪跑小能手上线", "差点就中啦!", "梦想还在路上", "运气在加载中..." ] win_phrases = [ "欧气爆棚!", "今晚加鸡腿!", "终于等到你!", "天选之子!", "请我吃饭吧!", "这波可以吹一年!" ] # 组装推送消息 msg_lines = [ random.choice([ "昨晚的梦想,今早的现实播报!", "新鲜出炉的号码命运播报来啦!", "昨夜许愿,今晨揭晓!", "号码的奇幻漂流记:", "昨晚的神秘数字,今早的答案!" ]) ] msg_lines.append( f"昨晚的神秘数字是:{open_code_str if open_code_str else '(暂无)'}\n") msg_lines.append(random.choice([ "我悄悄许下的愿望号码:", "我的小目标们:", "昨夜的希望清单:", "这些号码陪我走过了一个夜晚:" ])) # 固定号码 red_str = ' '.join(f"{n:02d}" for n in fixed_numbers['red']) blue_str = ' '.join(f"{n:02d}" for n in fixed_numbers['blue']) if fixed_result: if fixed_result['win_level']: win_text = f"{fixed_result['win_level']},奖金{fixed_result['win_amount']}元!{random.choice(win_phrases)}" else: win_text = random.choice(miss_phrases) msg_lines.append(f"{red_str} | {blue_str} → {win_text}") else: msg_lines.append(f"{red_str} | {blue_str} → 暂无开奖数据") # 推荐号码 win_count = 0 for rec in updated_records: numbers_parts = rec.numbers.split('|') red_numbers = [int(n) for n in numbers_parts[0].split( ',')] if numbers_parts[0] else [] blue_numbers = [int(n) for n in numbers_parts[1].split(',')] if len( numbers_parts) > 1 and numbers_parts[1] else [] red_str = ' '.join(f"{n:02d}" for n in red_numbers) blue_str = ' '.join(f"{n:02d}" for n in blue_numbers) if rec.is_winner == 1: win_count += 1 win_text = f"{rec.win_level},奖金{rec.win_amount}元!{random.choice(win_phrases)}" else: win_text = random.choice(miss_phrases) msg_lines.append(f"{red_str} | {blue_str} → {win_text}") # 结尾心情 if (fixed_result and fixed_result['win_level']) or win_count > 0: mood = random.choice([ "🎉 好运终于眷顾了我,今晚加鸡腿!", "🥳 好运爆棚,今晚请我吃饭!", "😎 中奖的感觉真不错!", "🍻 好运挡不住,继续冲!" ]) else: mood = random.choice([ "😅 今天又是陪跑小能手,大奖说'明天见'!", "😂 全军覆没,明天继续做梦!", "😭 梦想还在,大奖还远!", "🤡 继续修炼欧气,明天再战!" ]) msg_lines.append("") msg_lines.append(mood) # 推送到Telegram try: logger.info("开始推送幽默中奖播报到Telegram...") message = '\n'.join(msg_lines) result = send_message(message) if result: logger.info("幽默中奖播报推送成功") else: logger.warning("幽默中奖播报推送失败") except Exception as e: logger.error(f"幽默中奖播报推送失败: {str(e)}") logger.info(f"早上9点半幽默播报任务完成") finally: db.close() except Exception as e: logger.error(f"早上9点半幽默播报任务失败: {str(e)}") def start_scheduler(self): """启动定时任务调度器""" # 每天早上6点更新开奖数据 schedule.every().day.at("06:00").do(self.update_lottery_data_job) # 每天早上9点半检查前天中奖情况 schedule.every().day.at("09:30").do(self.check_previous_day_wins_job) # 每天下午5点生成拼盘推荐 schedule.every().day.at("17:00").do(self.generate_daily_recommendations_job) logger.info("定时任务调度器已启动") logger.info("已设置任务:") logger.info("- 每天早上6点: 更新开奖数据") logger.info("- 每天早上9点半: 检查前天中奖情况") logger.info("- 每天下午5点: 生成拼盘推荐") # 运行调度器 while True: schedule.run_pending() time.sleep(60) # 每分钟检查一次 def main(): """主函数""" scheduler = LotteryScheduler() scheduler.start_scheduler() if __name__ == "__main__": main()