我宣布了自己死亡–github生命检测

前一段时间死了么app火了一阵,没想到这么快我就要用上了。作者也得了绝症,也将不久人世,再见了~(无需过问)
自己简单搓了一个非app的,使用github action每天更新状态,action workflowk可手动签到或死亡,死亡后自动更新README.md在自己的主页上。
我宣布了自己死亡--github生命检测
存活判定方式:

  • workflowk 手动签到;
  • 任务每天执行,7天内没签到默认存活;

我宣布了自己死亡--github生命检测
死亡判定方式:
1.超过7天未手动签到即宣布死亡。
2.手动执行 workflowk 立即死亡。
我宣布了自己死亡--github生命检测
死亡后:
更新首页README,宣布死亡消息(没了)。
因每个人的信息不同,需要修改成自己的,项目名用自己的用户名(这样可以显示在自己主页上)
https://github.com/Zhu-junwei/Zhu-junwei/
自动任务 life-monitor.yml

  1. name: Life Monitor
  2. on:
  3.   schedule:
  4.     - cron: '00 19 * * *'
  5.   workflow_dispatch:
  6.     inputs:
  7.       mode:
  8.         description: '选择运行模式'
  9.         required: true
  10.         type: choice
  11.         options:
  12.           - 签到
  13.           - 死亡
  14. jobs:
  15.   monitor:
  16.     runs-on: ubuntu-24.04
  17.     permissions:
  18.       contents: write
  19.     steps:
  20.       - name: Checkout
  21.         uses: actions/checkout@v6
  22.       - name: Setup Python
  23.         uses: actions/setup-python@v7.1.0
  24.         with:
  25.           python-version: '3.13'
  26.       - name: Run life monitor
  27.         run: |
  28.           MODE="${{ github.event.inputs.mode }}"
  29.           if [ "$MODE" = "签到" ]; then
  30.             python life_monitor.py
  31.           elif [ "$MODE" = "死亡" ]; then
  32.             python life_monitor.py --force-death
  33.           else
  34.             # 定时触发:只检查不签到,超过7天自动宣告死亡
  35.             python life_monitor.py --auto
  36.           fi
  37.       - name: Commit and push
  38.         run: |
  39.           MODE="${{ github.event.inputs.mode }}"
  40.           MSG="${MODE:-自动签到}"
  41.           git config user.name "github-actions[bot]"
  42.           git config user.email "github-actions[bot]@users.noreply.github.com"
  43.           git add README.md .last_run
  44.           git diff --cached --quiet || git commit -m "life monitor: $MSG"
  45.           git push

死亡逻辑life_monitor.py

  1. #!/usr/bin/env python3
  2. """生命监测系统"""
  3. import os
  4. import datetime
  5. BASE_DIR = os.path.dirname(os.path.abspath(__file__))
  6. STATE_FILE = os.path.join(BASE_DIR, ".last_run")
  7. README_PATH = os.path.join(BASE_DIR, "README.md")
  8. MAX_DAYS = 7
  9. BIRTH_DATE = datetime.date(1995, 4, 23)
  10. BJ = datetime.timezone(datetime.timedelta(hours=8))
  11. def read_last_run():
  12.     if not os.path.exists(STATE_FILE):
  13.         return None
  14.     try:
  15.         with open(STATE_FILE, "r", encoding="utf-8") as f:
  16.             raw = f.read().strip()
  17.         dt = datetime.datetime.fromisoformat(raw)
  18.         if dt.tzinfo is None:
  19.             dt = dt.replace(tzinfo=BJ)
  20.         return dt
  21.     except Exception:
  22.         return None
  23. def write_last_run(dt):
  24.     with open(STATE_FILE, "w", encoding="utf-8") as f:
  25.         f.write(dt.isoformat())
  26. def now():
  27.     return datetime.datetime.now(BJ)
  28. def generate_alive_content(last_run, days, scan_time):
  29.     lines = [
  30.         f"🟢 上次存活时间: {last_run.strftime('%Y-%m-%d %H:%M:%S')} (UTC+8)",
  31.         "",
  32.         f"更新时间: {scan_time.strftime('%Y-%m-%d %H:%M:%S')} (UTC+8)",
  33.     ]
  34.     return "\n".join(lines)
  35. def generate_obituary_content(last_run, days, scan_time, force_death=False):
  36.     birth = BIRTH_DATE
  37.     if force_death:
  38.         # 手动确认死亡:死亡日期为当前扫描日期,保留真实最后存活时间
  39.         death_date = scan_time.date()
  40.         death_detail = ""
  41.         death_reason = "手动确认死亡。"
  42.         days_line = f"> **距上次执行**: {days} 天"
  43.     else:
  44.         # 自动判定死亡:超过阈值,估算死亡日期
  45.         death_date = (last_run + datetime.timedelta(days=MAX_DAYS)).date()
  46.         death_detail = f"(最后手动执行后第 {MAX_DAYS} 天(估算))"
  47.         death_reason = f"超过 {MAX_DAYS} 天未检测到生命体征,按协议发布讣告。"
  48.         days_line = f"> **距上次执行**: {days} 天"
  49.     age = death_date.year - birth.year - ((death_date.month, death_date.day) < (birth.month, birth.day))
  50.     with open(os.path.join(BASE_DIR, "obituary.md"), "r", encoding="utf-8") as f:
  51.         content = f.read()
  52.     replacements = {
  53.         "{{BIRTH_DATE}}": birth.strftime('%Y-%m-%d'),
  54.         "{{BIRTH_LUNAR}}": "农历一九九五年三月廿四",
  55.         "{{NAME}}": "朱俊伟",
  56.         "{{DEATH_DATE}}": death_date.strftime('%Y-%m-%d'),
  57.         "{{AGE}}": str(age),
  58.         "{{MAX_DAYS}}": str(MAX_DAYS),
  59.         "{{LAST_RUN}}": last_run.strftime('%Y-%m-%d %H:%M:%S'),
  60.         "{{SCAN_TIME}}": scan_time.strftime('%Y-%m-%d %H:%M:%S'),
  61.         "{{DEATH_DETAIL}}": death_detail,
  62.         "{{DEATH_REASON}}": death_reason,
  63.         "{{DAYS_LINE}}": days_line,
  64.     }
  65.     for key, value in replacements.items():
  66.         content = content.replace(key, value)
  67.     return content
  68. def run():
  69.     import sys
  70.     auto_mode = "--auto" in sys.argv
  71.     force_death = "--force-death" in sys.argv
  72.     scan_time = now()
  73.     last_run = read_last_run()
  74.     if force_death:
  75.         # 死亡模式:不修改 .last_run,保留真实的上次存活时间
  76.         # 如果没有历史记录,用当前时间兜底
  77.         if last_run is None:
  78.             last_run = scan_time
  79.     elif not auto_mode:
  80.         # 手动签到:更新 .last_run 为当前时间
  81.         write_last_run(scan_time)
  82.         last_run = scan_time
  83.     if last_run is None:
  84.         days = 0
  85.         if force_death:
  86.             # 没有历史记录但手动确认死亡
  87.             content = generate_obituary_content(scan_time, days, scan_time, force_death)
  88.         else:
  89.             content = generate_alive_content(scan_time, days, scan_time)
  90.     else:
  91.         days = (scan_time - last_run).days
  92.         if force_death:
  93.             # 手动确认死亡:直接生成讣告,不经过阈值判断
  94.             print(f"💀 手动确认死亡。最后存活时间: {last_run.strftime('%Y-%m-%d %H:%M:%S')}")
  95.             content = generate_obituary_content(last_run, days, scan_time, force_death)
  96.         elif days > MAX_DAYS:
  97.             print(f"⚠️  距上次手动执行已过去 {days} 天,超过 {MAX_DAYS} 天阈值!")
  98.             content = generate_obituary_content(last_run, days, scan_time, force_death)
  99.         else:
  100.             print(f"✅ 距上次手动执行 {days} 天,在 {MAX_DAYS} 天阈值内。")
  101.             content = generate_alive_content(last_run, days, scan_time)
  102.     with open(README_PATH, "w", encoding="utf-8") as f:
  103.         f.write(content)
  104.     print(f"📝 README.md 已更新")
  105.     print(f"   间隔: {days} 天 | 模式: {'自动检查' if auto_mode else ('强制死亡' if force_death else '手动打卡')}")
  106.     print(f"   状态: {'讣告' if last_run and days > MAX_DAYS else '正常'}")
  107. if __name__ == "__main__":
  108.     run()

» 转载保留版权:技术爱好者 » 《我宣布了自己死亡–github生命检测》

» 本文链接地址:https://www.jsahz.com/15745.html

评论 0

还没有评论,来说两句吧~

发表评论

下一篇

已是最新文章

作者:胖子