Repository: yusancky/AllUp-Satwiki
Pull request #135: Use X-authkey to interact with Satwiki
Author: login: yusancky
Labels: name: size/L
Created: 2025-05-31T12:57:23Z | Merged: 2025-05-31T13:49:08Z

Enhance authenticated interactions with Satwiki by injecting X-authkey into HTTP sessions, refactor `wiki` utility logic and environment flag checks, bump CI Python version, and update documentation and Dependabot schedules

New Features:
- Include X-authkey header in all HTTP sessions for authenticated Satwiki interactions

Enhancements:
- Refactor `wiki` utilities to conditionally instantiate the Wiki client based on main branch, workflow dispatch, or pull request contexts
- Streamline and reformat code across modules, including consolidating Selenium Chrome options and adjusting function formatting

CI:
- Bump GitHub Actions Python version from 3.12 to 3.13 and inject `BOT_PASSWORD` and `X_AUTHKEY` secrets into the workflow

Documentation:
- Update README to reflect project rename to AllUp-Satwiki and simplify the schedule footnote

Chores:
- Align Dependabot update schedule to use `cron` syntax matching the CI schedule


Diff:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index dadb125..af4d238 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
+      interval: "cron"
+      cronjob: "0 16 * * 5"
       timezone: "Asia/Shanghai"
     reviewers:
       - "yusancky"
@@ -13,8 +13,8 @@ updates:
   - package-ecosystem: "pip"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
+      interval: "cron"
+      cronjob: "0 16 * * 5"
       timezone: "Asia/Shanghai"
     reviewers:
       - "yusancky"
diff --git a/.github/workflows/AllUp.yml b/.github/workflows/AllUp.yml
index 222a57d..ec8a46c 100644
--- a/.github/workflows/AllUp.yml
+++ b/.github/workflows/AllUp.yml
@@ -1,5 +1,4 @@
 name: AllUp
-
 on:
   push:
     branches: [ main ]
@@ -9,32 +8,27 @@ on:
       - synchronize
       - reopened
   schedule:
-    - cron: '26 1 * * 5'
+    - cron: '26 1 * * *'
   workflow_dispatch:
-
 permissions:
   contents: write
   pull-requests: write
-
 env:
   TZ: Asia/Shanghai
-
 jobs:
   AllUp:
     runs-on: ubuntu-latest
     steps:
-      - name: Checkout
-        uses: actions/checkout@v4.2.2
-      - name: Setup Python
-        uses: actions/setup-python@v5.6.0
+      - uses: actions/checkout@v4.2.2
+      - uses: actions/setup-python@v5.6.0
         with:
-          python-version: '3.12'
+          python-version: '3.13'
           cache: 'pip'
-      - name: Install Python Dependencies
-        run: pip install -r requirements.txt
-      - name: Main
-        run: python main.py
+      - run: pip install -r requirements.txt
+      - run: python main.py
         env:
+          BOT_PASSWORD: ${{ secrets.BOT_PASSWORD }}
+          X_AUTHKEY: ${{ secrets.X_AUTHKEY }}
           GITHUB_EVENT_NAME: ${{ github.event_name }}
           GITHUB_REF: ${{ github.ref }}
           GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
diff --git a/AllUp_utils/web.py b/AllUp_utils/web.py
index 47b0f47..f3f32db 100644
--- a/AllUp_utils/web.py
+++ b/AllUp_utils/web.py
@@ -1,17 +1,27 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from requests import get
 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options
 
+
 def configure_chromedriver():
     chrome_options = Options()
-    for option in ['--headless','--disable-gpu','--window-size=1920,1200','--ignore-certificate-errors','--disable-extensions','--no-sandbox','--disable-dev-shm-usage']:
+    for option in [
+        "--headless",
+        "--disable-gpu",
+        "--window-size=1920,1200",
+        "--ignore-certificate-errors",
+        "--disable-extensions",
+        "--no-sandbox",
+        "--disable-dev-shm-usage",
+    ]:
         chrome_options.add_argument(option)
-    return webdriver.Chrome(options = chrome_options)
+    return webdriver.Chrome(options=chrome_options)
+
 
-def fetch_data(url : str,need_selenium = False):
+def fetch_data(url: str, need_selenium=False):
     if need_selenium:
         need_selenium.get(url)
         return need_selenium.page_source
diff --git a/AllUp_utils/wiki.py b/AllUp_utils/wiki.py
index d04b0e9..8c5db25 100644
--- a/AllUp_utils/wiki.py
+++ b/AllUp_utils/wiki.py
@@ -1,31 +1,50 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
+    TEST_PR = environ["GITHUB_EVENT_NAME"] == "pull_request"
+except Exception:
+    MAIN_REPO_BRANCH, TEST_DISPATCH, TEST_PR = False, False, False
+
+_original_session_init = requests.Session.__init__
+
+
+def _patched_session_init(self, *args, **kwargs):
+    _original_session_init(self, *args, **kwargs)
+    self.headers["X-authkey"] = environ["X_AUTHKEY"]
+
+
+requests.Session.__init__ = _patched_session_init
+
+if MAIN_REPO_BRANCH or TEST_DISPATCH or TEST_PR:
+    wiki = Wiki("sat.huijiwiki.com", "雨伞CKY", environ["BOT_PASSWORD"])
+
+
+def pull(title: str, split_line=False):
+    if MAIN_REPO_BRANCH or TEST_DISPATCH or TEST_PR:
+        return wiki.page_text(title)
     else:
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
-
-def push(title : str,content_id : str,content : str):
-    open(f'{title}.wikitext', 'w').write(content)
-    if PR_TEST():
-        print(f'### {content_id}\n\n```go\n{content}\n```\n\n',file = open('PR_preview.md','a'))
+        return ""
+
+
+def push(title: str, content_id: str, content: str):
+    open(f"{title}.wikitext", "w").write(content)
+    if MAIN_REPO_BRANCH or TEST_DISPATCH:
+        wiki.edit(title, content, "Edit via AllUp-Satwiki")
+    if TEST_PR:
+        print(
+            f"### {content_id}\n\n```go\n{content}\n```\n\n",
+            file=open("PR_preview.md", "a"),
+        )
diff --git a/AllUp_utils/wikitext.py b/AllUp_utils/wikitext.py
index 52b7034..7b39be7 100644
--- a/AllUp_utils/wikitext.py
+++ b/AllUp_utils/wikitext.py
@@ -1,16 +1,19 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
+
 
 def build_switch(data_map):
-    result = '{{#switch:{{{' + data_map['switch_key'] + '|}}}'
-    for data_key,data_value in data_map.items():
-        if data_key == 'switch_key':
+    result = "{{#switch:{{{" + data_map["switch_key"] + "|}}}"
+    for data_key, data_value in data_map.items():
+        if data_key == "switch_key":
             continue
-        if isinstance(data_value,str):
-            result += f'|{data_key}={data_value}'
-        elif isinstance(data_value,dict):
-            result += f'|{data_key}={build_switch(data_value)}'
+        if isinstance(data_value, str):
+            result += f"|{data_key}={data_value}"
+        elif isinstance(data_value, dict):
+            result += f"|{data_key}={build_switch(data_value)}"
         else:
-            raise TypeError(f"A string or a dictionary is required, not '{type(data_value)}'.")
-    result += '}}'
+            raise TypeError(
+                f"A string or a dictionary is required, not '{type(data_value)}'."
+            )
+    result += "}}"
     return result
diff --git a/README.md b/README.md
index 2ac4d00..292a3f1 100644
--- a/README.md
+++ b/README.md
@@ -2,16 +2,8 @@
 
 ![Python: 3.12 | 3.13 | 3.14](https://img.shields.io/badge/Python-3.12%20%7C%203.13%20%7C%203.14-python?style=social&logo=python&logoColor=blue) ![License: Apache-2.0](https://img.shields.io/github/license/yusancky/AllUp-Satwiki?style=social)
 
-AllUp 项目是由 [雨伞CKY](https://github.com/yusancky) 维护的、自动化爬取并集合数据以便动态更新的项目。<!--AllUp 项目的数据将于每日北京时间 9 时 26 分爬取数据并修改。[^1]-->由于近日 GitHub Actions 运行器未能与灰机 wiki 服务器进行成功连接，近期无法推送内容至卫星百科。
+AllUp-Satwiki 项目是由 [雨伞CKY](https://github.com/yusancky) 维护的、自动化爬取并集合数据以便动态更新的项目，其于北京时间每天 9 时 26 分获取数据并同步到卫星百科。[^1]
 
 ![Contributions in the Last 30 Days](https://repobeats.axiom.co/api/embed/3c013245586cfcc386dd553450db134d7617991c.svg)
 
-# 使用
-
-克隆或下载本存储库后，（切换到本项目根目录后）使用 `pip install -r requirements.txt` 安装所有依赖。之后，你可以分别通过运行 `main.py` 和 `TSS/main.py` 生成主模板内容、天宫空间站任务列表的 Apache ECharts 模板内容。生成的内容不会主动输出。
-
-# 贡献
-
-请前往 [贡献文档](/.github/CONTRIBUTING.md) 查看贡献相关内容。
-
-[^1]: 定时进行任务基于 GitHub Action 的 `schedule` 事件。但 `schedule` 事件在 Actions 工作流运行期间负载过高时可能会延迟。据以往经历，一般延迟在 30 分钟至 45 分钟。
+[^1]: 定时任务基于 GitHub Actions 的 `schedule` 事件，但其在 Actions 工作流运行负载过高时可能会延迟。
diff --git a/main.py b/main.py
index db7098b..ec4dd7b 100644
--- a/main.py
+++ b/main.py
@@ -1,5 +1,5 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 import AllUp_utils.wiki
 import AllUp_utils.web
@@ -8,63 +8,96 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    with open("TSS-data/TSS-data.wikitext", encoding="utf-8") as f:
+        dataset = [line.strip() for line in f]
+    for row in dataset:
+        data = row.split(",")
+        start_date = date.fromisoformat(data[2])
+        end_date = (
+            date.fromisoformat(data[3]) if data[3] != "future" else today
+        )
+        delta_days = (end_date - start_date).days
+        missions.append(
+            [
+                data[0],
+                start_date,
+                delta_days,
+                (
+                    "#fdba74"
+                    if data[1] == "main"
+                    else ("#6ee7b7" if data[3] != "future" else "#fcd34d")
+                ),
+            ]
+        )
+    data_name, start_date, delta_days_with_data_color = [], [], ""
+    for mission in missions:
+        data_name.insert(0, mission[0])
+        start_date.insert(
+            0, (mission[1] - date.fromisoformat("20210429")).days
+        )
+        delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
+    delta_days_with_data_color = delta_days_with_data_color[:-1]
+    return f"""{{{{#echarts:option={{
   "title": {{
     "text": "天宫空间站任务列表",
     "subtext": "上次更新：{date.today().year}年{date.today().month}月{date.today().day}日（{(date.today() - date.fromisoformat('20210429')).days}）"
@@ -122,48 +155,85 @@ def build_tiangong_chart():
     }}
   ]
 }}
-|style=min-height:380px}}}}'''
+|style=min-height:380px}}}}"""
+
 
 def fetch_satellite_data():
-  """Fetch data for multiple satellites."""
-  data = {'switch_key': 'sat'}
-  for sat in ['star', 'ow', 'kp', 'stsh', 'xw', 'qf', 'ynh', 'lynk', 'esp', 's1m', 'pln', 'iri', 'gbl', 'jil', 'slog', 'asts', 'swa', 'glo', 'spr', 'st3', 'par', 'gps', 'bei', 'oco', 'hwk', 'kep', 'int', 'ses']:
-    web_data = AllUp_utils.web.fetch_data(f'https://planet4589.org/space/con/{sat}/stats.html')
-    data_inner = {'switch_key': 'section'}
-    dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-    for section in range(4):
-      try:
-        data_inner[str(section + 1)] = dataset[0][section]
-      except Exception as e:
-        data_inner[str(section + 1)] = str(e)
-    data_inner['#default'] = '请输入正确的选项名！'
-    data[sat] = AllUp_utils.wikitext.build_switch(data_inner)
-  data['#default'] = '请输入正确的卫星名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch data for multiple satellites."""
+    data = {"switch_key": "sat"}
+    for sat in [
+        "star",
+        "ow",
+        "kp",
+        "stsh",
+        "xw",
+        "qf",
+        "ynh",
+        "lynk",
+        "esp",
+        "s1m",
+        "pln",
+        "iri",
+        "gbl",
+        "jil",
+        "slog",
+        "asts",
+        "swa",
+        "glo",
+        "spr",
+        "st3",
+        "par",
+        "gps",
+        "bei",
+        "oco",
+        "hwk",
+        "kep",
+        "int",
+        "ses",
+    ]:
+        web_data = AllUp_utils.web.fetch_data(
+            f"https://planet4589.org/space/con/{sat}/stats.html"
+        )
+        data_inner = {"switch_key": "section"}
+        dataset = findall(
+            r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+            web_data,
+        )
+        for section in range(4):
+            try:
+                data_inner[str(section + 1)] = dataset[0][section]
+            except Exception as e:
+                data_inner[str(section + 1)] = str(e)
+        data_inner["#default"] = "请输入正确的选项名！"
+        data[sat] = AllUp_utils.wikitext.build_switch(data_inner)
+    data["#default"] = "请输入正确的卫星名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def make(id):
-  """Main switch function."""
-  match id:
-    case 't':
-      return strftime('%Y年%m月%d日%H时', localtime())
-    case '1':
-      return '因上游数据进行格式调整，<code><nowiki>{{AllUp|1}}</nowiki></code> 暂时停用！{{需要更新}}'
-      # return fetch_voyager_data()
-    case '2':
-      return fetch_orbital_data()
-    case '3':
-      return fetch_starlink_data()
-    case '4':
-      return build_tiangong_chart()
-    case '5':
-      return fetch_satellite_data()
-    case _:
-      return '请输入正确的AllUp编号！'
+    """Main switch function."""
+    match id:
+        case "t":
+            return strftime("%Y年%m月%d日%H时", localtime())
+        case "1":
+            return "因上游数据进行格式调整，<code><nowiki>{{AllUp|1}}</nowiki></code> 暂时停用！{{需要更新}}"
+            # return fetch_voyager_data()
+        case "2":
+            return fetch_orbital_data()
+        case "3":
+            return fetch_starlink_data()
+        case "4":
+            return build_tiangong_chart()
+        case "5":
+            return fetch_satellite_data()
+        case _:
+            return "请输入正确的AllUp编号！"
+
 
-if __name__ == '__main__':
-  chromedriver = AllUp_utils.web.configure_chromedriver()
-  AllUp_data = {'switch_key': '1'}
-  for dataset in ['t'] + [str(i + 1) for i in range(5)] + ['#default']:
-    AllUp_data[dataset] = make(dataset)
-  AllUp_content = f'<includeonly>{AllUp_utils.wikitext.build_switch(AllUp_data)}</includeonly><noinclude>[[Category:模板]]{{{{documentation}}}}</noinclude>'
-  AllUp_utils.wiki.push('AllUp', 'MAIN', AllUp_content)
+if __name__ == "__main__":
+    chromedriver = AllUp_utils.web.configure_chromedriver()
+    AllUp_data = {"switch_key": "1"}
+    for dataset in ["t"] + [str(i + 1) for i in range(5)] + ["#default"]:
+        AllUp_data[dataset] = make(dataset)
+    AllUp_content = f"<includeonly>{AllUp_utils.wikitext.build_switch(AllUp_data)}</includeonly><noinclude>[[Category:模板]]{{{{documentation}}}}</noinclude>"
+    AllUp_utils.wiki.push("Template:AllUp", "MAIN", AllUp_content)


Reviews:
user: login: sourcery-ai[bot]
body: 嘿 @yusancky - 我已经查看了你的更改，发现了一些需要解决的问题。

**阻塞问题**：
- 未定义的 PR_TEST 变量 ([link](https://github.com/yusancky/AllUp-Satwiki/pull/135/files#diff-cb3079f73dd563f90ccb6c52470068952e0b5491d172a2201e58b7aeb95f13a8R31))

**一般评论**：

- 在 AllUp_utils/wiki.py 中，你在 `if MAIN_REPO_BRANCH or PR_TEST:` 检查中使用 `PR_TEST`，但你定义了 `TEST_PR`，因此这将导致 NameError—重命名或更正变量引用。
- 考虑构造和重用自定义 `requests.Session`（或使用 requests 身份验证机制），而不是全局 monkey-patching `requests.Session.__init__` 以注入 X-authkey 标头，以避免意外的副作用。
- `fetch_data` 函数的 `need_selenium` 参数具有误导性（你将其视为布尔值，但在其上调用 `.get`）；重构为显式接受驱动程序实例，或拆分 Selenium 与简单提取逻辑。

<details>
<summary>以下是我在审查期间查看的内容</summary>

- 🔴 **一般问题**：1 个阻塞问题，3 个其他问题
- 🟢 **安全性**：一切看起来都不错
- 🟢 **测试**：一切看起来都不错
- 🟡 **复杂性**：发现 1 个问题
- 🟢 **文档**：一切看起来都不错
</details>

***

<details>
<summary>Sourcery 对开源是免费的 - 如果你喜欢我们的评论，请考虑分享它们 ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
帮助我更有用！请点击每个评论上的 👍 或 👎，我将使用反馈来改进你的评论。
</sub>

<details>
<summary>Original comment in English</summary>

Hey @yusancky - I've reviewed your changes and found some issues that need to be addressed.

**Blocking issues**:
- Undefined PR_TEST variable ([link](https://github.com/yusancky/AllUp-Satwiki/pull/135/files#diff-cb3079f73dd563f90ccb6c52470068952e0b5491d172a2201e58b7aeb95f13a8R31))

**General comments**:

- In AllUp_utils/wiki.py you use `PR_TEST` in the `if MAIN_REPO_BRANCH or PR_TEST:` check, but you defined `TEST_PR`, so this will cause a NameError—rename or correct the variable reference.
- Rather than monkey-patching `requests.Session.__init__` globally to inject X-authkey headers, consider constructing and reusing a custom `requests.Session` (or using a requests auth mechanism) to avoid unintended side effects.
- The `fetch_data` function’s `need_selenium` parameter is misleading (you treat it as a boolean but call `.get` on it); refactor to accept a driver instance explicitly or split Selenium vs. simple fetch logic.

<details>
<summary>Here's what I looked at during the review</summary>

- 🔴 **General issues**: 1 blocking issue, 3 other issues
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 1 issue found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>

</details>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:00:05Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:09:29Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:09:45Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:12:22Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:14:17Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:14:36Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:18:17Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:18:29Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:21:22Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:21:33Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:26:31Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:26:52Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:28:24Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:28:43Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:30:45Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:31:30Z
user: login: sourcery-ai[bot]
body: 嘿 @yusancky - 我已经查看了你的更改 - 这里有一些反馈：

- 考虑使用自定义 Session 子类或请求钩子来更安全地注入 X-authkey 标头，而不是全局 monkey-patching requests.Session.__init__。
- dependabot.yml 更改使用 `interval: "cron"` 和 `cronjob`，这些不是 Dependabot 计划的有效键 - 请恢复为支持的计划语法。
- 使用上下文管理器替换裸文件打开（例如 `open(...).write` 和 `open(..., 'a')`）以确保文件已正确关闭。

<details>
<summary>这是我在审查期间查看的内容</summary>

- 🟡 **一般问题**：发现 1 个问题
- 🟢 **安全性**：一切看起来都不错
- 🟢 **测试**：一切看起来都不错
- 🟡 **复杂性**：发现 1 个问题
- 🟢 **文档**：一切看起来都不错
</details>

***

<details>
<summary>Sourcery 对开源是免费的 - 如果你喜欢我们的评论，请考虑分享它们✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
帮助我更有用！请点击每个评论上的👍或👎，我将使用反馈来改进你的评论。
</sub>

<details>
<summary>Original comment in English</summary>

Hey @yusancky - I've reviewed your changes - here's some feedback:

- Instead of globally monkey-patching requests.Session.__init__, consider using a custom Session subclass or request hooks to inject the X-authkey header more safely.
- The dependabot.yml changes use `interval: "cron"` and `cronjob`, which are not valid keys for Dependabot schedules—please revert to a supported schedule syntax.
- Replace bare file opens (e.g. `open(...).write` and `open(..., 'a')`) with context managers to ensure files are properly closed.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 1 issue found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>

</details>
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T13:36:16Z
user: login: yusancky
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-31T13:44:20Z

Review comments:
diff_hunk: @@ -1,31 +1,50 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
+    TEST_PR = environ["GITHUB_EVENT_NAME"] == "pull_request"
+except Exception:
+    MAIN_REPO_BRANCH, TEST_DISPATCH, TEST_PR = False, False, False
+
+_original_session_init = requests.Session.__init__
+
+
+def _patched_session_init(self, *args, **kwargs):
+    _original_session_init(self, *args, **kwargs)
+    self.headers["X-authkey"] = environ["X_AUTHKEY"]
+
+
+requests.Session.__init__ = _patched_session_init
+
+if MAIN_REPO_BRANCH or PR_TEST:
path: AllUp_utils/wiki.py
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** 未定义的 PR_TEST 变量

PR_TEST 未定义；请改用 TEST_PR，以避免在运行时出现 NameError。

<details>
<summary>Original comment in English</summary>

**issue (bug_risk):** Undefined PR_TEST variable

PR_TEST is undefined; use TEST_PR instead to avoid a NameError at runtime.

</details>
created_at: 2025-05-31T13:00:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,17 +1,27 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from requests import get
 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options
 
+
 def configure_chromedriver():
     chrome_options = Options()
-    for option in ['--headless','--disable-gpu','--window-size=1920,1200','--ignore-certificate-errors','--disable-extensions','--no-sandbox','--disable-dev-shm-usage']:
+    for option in [
+        "--headless",
+        "--disable-gpu",
+        "--window-size=1920,1200",
+        "--ignore-certificate-errors",
+        "--disable-extensions",
+        "--no-sandbox",
+        "--disable-dev-shm-usage",
+    ]:
         chrome_options.add_argument(option)
-    return webdriver.Chrome(options = chrome_options)
+    return webdriver.Chrome(options=chrome_options)
+
 
-def fetch_data(url : str,need_selenium = False):
+def fetch_data(url: str, need_selenium=False):
     if need_selenium:
         need_selenium.get(url)
         return need_selenium.page_source
path: AllUp_utils/web.py
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** need_selenium 参数使用不正确

`need_selenium` 是一个布尔值，但被用作 WebDriver 对象。如果传递驱动程序，请将其重命名为 `driver`，或者分离布尔标志和驱动程序参数。

<details>
<summary>Original comment in English</summary>

**issue (bug_risk):** Incorrect use of need_selenium parameter

`need_selenium` is a boolean but used as a WebDriver object. Rename it to `driver` if passing a driver, or separate the boolean flag and driver parameter.

</details>
created_at: 2025-05-31T13:00:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
+      interval: "cron"
+      cronjob: "26 1 * * 5"
path: .github/dependabot.yml
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** 无效的 dependabot 计划键

`interval` 必须设置为 `daily`、`weekly` 或 `monthly`；不支持 `cron` 和 `cronjob`，并且会阻止更新。

<details>
<summary>Original comment in English</summary>

**issue (bug_risk):** Invalid dependabot schedule keys

`interval` must be set to `daily`, `weekly`, or `monthly`; `cron` and `cronjob` are not supported and will block updates.

</details>
created_at: 2025-05-31T13:00:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,63 +8,95 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    for row in dataset:
+        data = row.split(",")
path: main.py
user: login: sourcery-ai[bot]
body: **suggestion:** 使用上下文管理器进行文件 I/O

将文件访问包装在上下文管理器中可确保文件正确关闭，即使发生异常也是如此。

```suggestion
    with open("TSS-data/TSS-data.wikitext") as f:
        dataset = [line.strip() for line in f]
    for row in dataset:
        data = row.split(",")
```

<details>
<summary>Original comment in English</summary>

**suggestion:** Use context manager for file I/O

Wrapping file access in a context manager ensures the file is properly closed, even if an exception occurs.

```suggestion
    with open("TSS-data/TSS-data.wikitext") as f:
        dataset = [line.strip() for line in f]
    for row in dataset:
        data = row.split(",")
```

</details>
created_at: 2025-05-31T13:00:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: sourcery-ai[bot]
body: **issue (complexity):** 考虑通过将环境标志逻辑和会话设置集中到帮助程序中来进行重构，以使 pull 和 push 函数保持简单且无副作用。

以下是一种将所有标志逻辑和会话破解合并到一个小型帮助程序中的方法，以便您的 `pull`/`push` 保持简单且无副作用：

```python
import os
import requests
from pwiki.wiki import Wiki

def _make_wiki_if_enabled():
    owner = os.environ.get("GITHUB_REPOSITORY_OWNER")
    ref   = os.environ.get("GITHUB_REF")
    event = os.environ.get("GITHUB_EVENT_NAME")

    enabled = (
        owner == "yusancky"
        and (ref == "refs/heads/main" or event in ("workflow_dispatch", "pull_request"))
    )
    if not enabled:
        return None

    session = requests.Session()
    session.headers["X-authkey"] = os.environ["X_AUTHKEY"]
    # assume Wiki accepts a session param; if not, add one.
    return Wiki(
        "sat.huijiwiki.com",
        username="雨伞CKY",
        password=os.environ["BOT_PASSWORD"],
        session=session,
    )

_wiki = _make_wiki_if_enabled()
```

然后，您的实际 API 保持非常精简：

```python
def pull(title: str, split_line=False) -> str:
    if not _wiki:
        return ""
    return _wiki.page_text(title)

def push(title: str, content_id: str, content: str):
    with open(f"{title}.wikitext", "w") as f:
        f.write(content)

    if _wiki:
        _wiki.edit(title, content, "Edit via AllUp-Satwiki")

    if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
        with open("PR_preview.md", "a") as prf:
            prf.write(f"### {content_id}\n\n```go\n{content}\n```\n\n")
```

这有什么作用：

1. 将_所有_ env 标志逻辑集中在一个地方。  
2. 删除 `requests.Session` monkey-patch—现在它是显式的。  
3. 使 `pull`/`push` 保持纯粹且易于推理。

<details>
<summary>Original comment in English</summary>

**issue (complexity):** Consider refactoring by centralizing environment flag logic and session setup into a helper to keep pull and push functions simple and side-effect-free.

Here’s one way to collapse all of the flag‐logic and the session‐hacking into a small helper so that your `pull`/`push` remain trivial and side‐effect-free:

```python
import os
import requests
from pwiki.wiki import Wiki

def _make_wiki_if_enabled():
    owner = os.environ.get("GITHUB_REPOSITORY_OWNER")
    ref   = os.environ.get("GITHUB_REF")
    event = os.environ.get("GITHUB_EVENT_NAME")

    enabled = (
        owner == "yusancky"
        and (ref == "refs/heads/main" or event in ("workflow_dispatch", "pull_request"))
    )
    if not enabled:
        return None

    session = requests.Session()
    session.headers["X-authkey"] = os.environ["X_AUTHKEY"]
    # assume Wiki accepts a session param; if not, add one.
    return Wiki(
        "sat.huijiwiki.com",
        username="雨伞CKY",
        password=os.environ["BOT_PASSWORD"],
        session=session,
    )

_wiki = _make_wiki_if_enabled()
```

Then your actual API stays razor‐thin:

```python
def pull(title: str, split_line=False) -> str:
    if not _wiki:
        return ""
    return _wiki.page_text(title)

def push(title: str, content_id: str, content: str):
    with open(f"{title}.wikitext", "w") as f:
        f.write(content)

    if _wiki:
        _wiki.edit(title, content, "Edit via AllUp-Satwiki")

    if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
        with open("PR_preview.md", "a") as prf:
            prf.write(f"### {content_id}\n\n```go\n{content}\n```\n\n")
```

What this does:

1. Centralizes _all_ env‐flag logic in one place.  
2. Removes the `requests.Session` monkey‐patch—now it’s explicit.  
3. Leaves `pull`/`push` pure and easy to reason about.

</details>
created_at: 2025-05-31T13:00:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
+      interval: "cron"
+      cronjob: "26 1 * * 5"
path: .github/dependabot.yml
user: login: yusancky
body: Dependabot now lets you schedule update frequencies with cron expressions https://github.blog/changelog/2025-04-22-dependabot-now-lets-you-schedule-update-frequencies-with-cron-expressions/
created_at: 2025-05-31T13:09:29Z
author_association: OWNER
diff_hunk: @@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
+      interval: "cron"
+      cronjob: "26 1 * * 5"
path: .github/dependabot.yml
user: login: sourcery-ai[bot]
body: Great catch on the new cron support! The original lint was based on the old schema (only daily/weekly/monthly), but since GitHub just added cron‐based schedules you’ll want to switch to their new syntax.

Specifically, replace your schedule block with:

```yaml
schedule:
  # drop `interval` and `cronjob`
  cron: "26 1 * * 5"
  # optional: time_zone: "UTC"
```

So your full dependabot.yml would look like:

```yaml
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      cron: "26 1 * * 5"
```

This matches their April 2025 changelog. Let me know if you hit any snags!
created_at: 2025-05-31T13:09:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,31 +1,50 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
+    TEST_PR = environ["GITHUB_EVENT_NAME"] == "pull_request"
+except Exception:
+    MAIN_REPO_BRANCH, TEST_DISPATCH, TEST_PR = False, False, False
+
+_original_session_init = requests.Session.__init__
+
+
+def _patched_session_init(self, *args, **kwargs):
+    _original_session_init(self, *args, **kwargs)
+    self.headers["X-authkey"] = environ["X_AUTHKEY"]
+
+
+requests.Session.__init__ = _patched_session_init
+
+if MAIN_REPO_BRANCH or PR_TEST:
path: AllUp_utils/wiki.py
user: login: yusancky
body: fixed
created_at: 2025-05-31T13:12:22Z
author_association: OWNER
diff_hunk: @@ -8,63 +8,95 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    for row in dataset:
+        data = row.split(",")
path: main.py
user: login: yusancky
body: 这样的修改在运行上有什么实际的不同点？

相比之下，修改后的方式又有哪些优点（它似乎并没有现在这种这么简洁明了）？
created_at: 2025-05-31T13:14:17Z
author_association: OWNER
diff_hunk: @@ -8,63 +8,95 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    for row in dataset:
+        data = row.split(",")
path: main.py
user: login: sourcery-ai[bot]
body: 在运行时，这两段代码其实是等价的——都会把整个文件读到内存里，性能和输出都不会有差别。真正的不同点在于资源管理和代码健壮性：

1. 自动关闭文件  
   `with open(...) as f:` 会在代码块退出时（包括遇到异常时）自动调用 `f.close()`，确保文件句柄及时释放，不会因为忘记 `close()` 而导致描述符泄露。

2. 异常安全  
   如果在读取或处理文件内容时抛了异常，`with` 保证 `__exit__` 被调用，文件依然会被关闭；而直接 `open()` 的写法就得自己在 `finally` 里写 `f.close()`，否则异常时就漏掉了。

3. 符合惯例  
   这是 Python 官方推荐的文件 I/O 方式（PEP 343），在社区里也更常见，利于新同学快速理解 “读完就关” 的意图。

可读性方面，虽然多了一级缩进，但其实把“打开—读取—关闭”三个步骤显式地包在一起，更清晰地表达了「这里是在做一次文件读取操作」的语义。总之，这主要是提升代码的健壮性和可维护性，并不是为了改变功能或性能。
created_at: 2025-05-31T13:14:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,63 +8,95 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    for row in dataset:
+        data = row.split(",")
path: main.py
user: login: yusancky
body: 这个 suggestion 在 GitHub 上被标记为 outdated 了，请再生成一个新的。
created_at: 2025-05-31T13:18:17Z
author_association: OWNER
diff_hunk: @@ -8,63 +8,95 @@
 from re import compile, findall
 from time import localtime, strftime
 
+
 def fetch_voyager_data():
-  """[Deprecated] Fetch Voyager mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://voyager.jpl.nasa.gov/mission/status/')
-  data = {'switch_key': 'id'}
-  for id in [str(i + 1) for i in range(2)]:
-    data[id] = {'switch_key': 'section'}
-    for section in ['km', 'au', 'kms', 'aus', 'speed', 'lt']:
-      data[id][section] = findall(
-        compile(f'id="voy{id}_{section}">(.*)</div>'),
-        web_data
-      )[0]
-    data[id]['#default'] = '请输入正确的选项名！'
-  data['#default'] = '请输入正确的编号！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """[Deprecated] Fetch Voyager mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://voyager.jpl.nasa.gov/mission/status/"
+    )
+    data = {"switch_key": "id"}
+    for id in [str(i + 1) for i in range(2)]:
+        data[id] = {"switch_key": "section"}
+        for section in ["km", "au", "kms", "aus", "speed", "lt"]:
+            data[id][section] = findall(
+                compile(f'id="voy{id}_{section}">(.*)</div>'), web_data
+            )[0]
+        data[id]["#default"] = "请输入正确的选项名！"
+    data["#default"] = "请输入正确的编号！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_orbital_data():
-  """Fetch orbital data."""
-  web_data = AllUp_utils.web.fetch_data('https://in-the-sky.org/spacecraft.php?id=6073')
-  data = {'switch_key': 'section'}
-  for section in ['Inclination', 'Eccentricity', 'RA ascending node', 'Argument perigee', 'Mean anomaly', 'Orbital period', 'Epoch of osculation']:
-    data[section] = findall(f'<td>{section}</td>\n *<td>([^<>]*)</td>', web_data)[0].strip()
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch orbital data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://in-the-sky.org/spacecraft.php?id=6073"
+    )
+    data = {"switch_key": "section"}
+    for section in [
+        "Inclination",
+        "Eccentricity",
+        "RA ascending node",
+        "Argument perigee",
+        "Mean anomaly",
+        "Orbital period",
+        "Epoch of osculation",
+    ]:
+        data[section] = findall(
+            f"<td>{section}</td>\n *<td>([^<>]*)</td>", web_data
+        )[0].strip()
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def fetch_starlink_data():
-  """Fetch Starlink mission data."""
-  web_data = AllUp_utils.web.fetch_data('https://planet4589.org/space/con/star/stats.html')
-  data = {'switch_key': 'section'}
-  dataset = findall(r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',web_data)
-  for section in range(4):
-    data[str(section + 1)] = dataset[0][section]
-  data['#default'] = '请输入正确的选项名！'
-  return AllUp_utils.wikitext.build_switch(data)
+    """Fetch Starlink mission data."""
+    web_data = AllUp_utils.web.fetch_data(
+        "https://planet4589.org/space/con/star/stats.html"
+    )
+    data = {"switch_key": "section"}
+    dataset = findall(
+        r'<TR><TD>Total</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:red" *>\d*</TD><TD style="color:blue" *>(\d*)</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:blue" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *>\d*</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD><TD style="color:green" *> *</TD></TR>',
+        web_data,
+    )
+    for section in range(4):
+        data[str(section + 1)] = dataset[0][section]
+    data["#default"] = "请输入正确的选项名！"
+    return AllUp_utils.wikitext.build_switch(data)
+
 
 def build_tiangong_chart():
-  """Build Tiangong missions chart."""
-  missions = []
-  today = date.today()
-  dataset = [line.strip() for line in open('TSS-data/TSS-data.wikitext')]
-  for row in dataset:
-    data = row.split(',')
-    start_date = date.fromisoformat(data[2])
-    end_date = date.fromisoformat(data[3]) if data[3] != 'future' else today
-    delta_days = (end_date - start_date).days
-    missions.append([
-      data[0],
-      start_date,
-      delta_days,
-      '#fdba74' if data[1] == 'main' else ('#6ee7b7' if data[3] != 'future' else '#fcd34d')
-    ])
-  data_name,start_date,delta_days_with_data_color = [],[],''
-  for mission in missions:
-    data_name.insert(0,mission[0])
-    start_date.insert(0,(mission[1] - date.fromisoformat('20210429')).days)
-    delta_days_with_data_color = f'{{"value": {mission[2]}, "itemStyle": {{"color": "{mission[3]}"}} }},{delta_days_with_data_color}'
-  delta_days_with_data_color = delta_days_with_data_color[:-1]
-  return f'''{{{{#echarts:option={{
+    """Build Tiangong Space Station missions chart."""
+    missions = []
+    today = date.today()
+    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    for row in dataset:
+        data = row.split(",")
path: main.py
user: login: sourcery-ai[bot]
body: 下面是针对 `build_tiangong_chart` 中文件读取部分的新版建议，你可以直接复制到 PR 对应位置：

```diff
 def build_tiangong_chart():
     """Build Tiangong Space Station missions chart."""
     missions = []
     today = date.today()
-    dataset = [line.strip() for line in open("TSS-data/TSS-data.wikitext")]
+    # 建议使用上下文管理器，确保文件一定会被关闭
+    with open("TSS-data/TSS-data.wikitext", encoding="utf-8") as f:
+        dataset = [line.strip() for line in f]
     for row in dataset:
         data = row.split(",")
         …
```

改动要点：
1. 用 `with open(...) as f:` 包裹 I/O，避免手动调用 `close()` 导致的潜在泄露。  
2. （可选）加上 `encoding="utf-8"` 以保证跨平台一致的编码解析。
created_at: 2025-05-31T13:18:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: yusancky
body: 我认为这样修改意义不很大，wdyt
created_at: 2025-05-31T13:21:22Z
author_association: OWNER
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: sourcery-ai[bot]
body: 这是一个可选的重构建议，主要目的是把所有的环境判断和 session 注入都集中到一个小 helper 里，让 pull/push 的逻辑保持极简、可测、无副作用。好处大概有：

- 只在一处写环境判断（是否 main 分支、dispatch、PR…），之后新增场景／修改条件都只改这儿
- 不再在全局 scope 或函数里散落地 monkey-patch `requests.Session`，而是显式地创建并传给 Wiki
- pull/push 变得轻量，复用性更好，也更容易单元测试

但也确实有点「过度设计」的味道，尤其当前功能点比较少、代码量不大时。你可以根据团队习惯和未来扩展预期来决定：

- 如果觉得目前就这几行、后续也不太会再改，可以保持现状，代码更直接；
- 如果后续还可能加更多 auth 客制化、或别的环境分支，就合并到 helper 有利于维护。

总之，这条建议只是让职责更分明，非硬性要求，按你判断和团队风格定就好。
created_at: 2025-05-31T13:21:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,17 +1,27 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from requests import get
 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options
 
+
 def configure_chromedriver():
     chrome_options = Options()
-    for option in ['--headless','--disable-gpu','--window-size=1920,1200','--ignore-certificate-errors','--disable-extensions','--no-sandbox','--disable-dev-shm-usage']:
+    for option in [
+        "--headless",
+        "--disable-gpu",
+        "--window-size=1920,1200",
+        "--ignore-certificate-errors",
+        "--disable-extensions",
+        "--no-sandbox",
+        "--disable-dev-shm-usage",
+    ]:
         chrome_options.add_argument(option)
-    return webdriver.Chrome(options = chrome_options)
+    return webdriver.Chrome(options=chrome_options)
+
 
-def fetch_data(url : str,need_selenium = False):
+def fetch_data(url: str, need_selenium=False):
     if need_selenium:
         need_selenium.get(url)
         return need_selenium.page_source
path: AllUp_utils/web.py
user: login: yusancky
body: 我是这样想的：
- 如果使用这个函数时同时传入了 `url` 和 `need_selenium`，就使用传递进来的 Selenium WebDriver 对象操作；
- 如果使用这个函数时只传入了 `url`，没有传入 `need_selenium`，就直接用 Requests 库去操作读取。

你有没有什么能不改变原有调用操作的，针对这种方便快捷需求的优化建议？
created_at: 2025-05-31T13:26:31Z
author_association: OWNER
diff_hunk: @@ -1,17 +1,27 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from requests import get
 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options
 
+
 def configure_chromedriver():
     chrome_options = Options()
-    for option in ['--headless','--disable-gpu','--window-size=1920,1200','--ignore-certificate-errors','--disable-extensions','--no-sandbox','--disable-dev-shm-usage']:
+    for option in [
+        "--headless",
+        "--disable-gpu",
+        "--window-size=1920,1200",
+        "--ignore-certificate-errors",
+        "--disable-extensions",
+        "--no-sandbox",
+        "--disable-dev-shm-usage",
+    ]:
         chrome_options.add_argument(option)
-    return webdriver.Chrome(options = chrome_options)
+    return webdriver.Chrome(options=chrome_options)
+
 
-def fetch_data(url : str,need_selenium = False):
+def fetch_data(url: str, need_selenium=False):
     if need_selenium:
         need_selenium.get(url)
         return need_selenium.page_source
path: AllUp_utils/web.py
user: login: sourcery-ai[bot]
body: 你的思路没问题，我补充一个“向下兼容又懒人-friendly”的小技巧：让 `need_selenium` 同时能接受布尔和 WebDriver，对这两种类型做分支，这样：

1. 只传 `url` 或者 `need_selenium=False` → 用 requests  
2. 传入 `need_selenium=True` → 内部帮你 `configure_chromedriver()` 并自动关闭  
3. 传入一个 WebDriver 实例 → 用你传进去的 driver  

示例改法（改动调用方极小）：

```python
from requests import get
from selenium.webdriver.remote.webdriver import WebDriver

def fetch_data(
    url: str,
    need_selenium: bool | WebDriver = False,
    close_driver: bool = True,
) -> str:
    # 1) 传 False 或者不传 → requests
    if not need_selenium:
        return get(url).text

    # 2) 传 True → 自动帮你 new 一个 driver
    if need_selenium is True:
        driver = configure_chromedriver()
    # 3) 传 WebDriver → 用它
    elif isinstance(need_selenium, WebDriver):
        driver = need_selenium
    else:
        raise TypeError("need_selenium must be bool or WebDriver instance")

    try:
        driver.get(url)
        return driver.page_source
    finally:
        if close_driver and need_selenium is True:
            driver.quit()
```

这样：

- 现有只用 `fetch_data(url)` 的地方完全不动  
- 想“一键起 Selenium” 的地方只需 `fetch_data(url, True)`  
- 想重用自己建好的 driver 的地方依旧 `fetch_data(url, driver)`  

另外加了一个 `close_driver` 参数，默认只在自动创建时关闭，自己传入的 driver 就不动它。这样既保证了最小侵入，又满足了多种使用场景。
created_at: 2025-05-31T13:26:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: yusancky
body: 你能不能给我个修改后的完整代码效果和对应的 diff 让我看看？
created_at: 2025-05-31T13:28:24Z
author_association: OWNER
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: sourcery-ai[bot]
body: 下面是一种完整的重构示例，把所有环境判断和 session 注入逻辑都集中到一个 helper 里，`pull`/`push` 保持非常轻量且无副作用。你可以对比一下效果和改动：

```diff
--- a/AllUp_utils/wiki.py
+++ b/AllUp_utils/wiki.py
@@ -1,6 +1,9 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
+
 import os
-from pwiki.wiki import Wiki
+import requests
+from pwiki.wiki import Wiki
 
-
-def PR_TEST():
-    return os.environ.get('GITHUB_EVENT_NAME') == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (
-        os.environ.get('GITHUB_REF') == 'refs/heads/main'
-        and os.environ.get('GITHUB_REPOSITORY_OWNER') == 'yusancky'
-    )
-
-def pull(title: str, split_line=False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.'
-                  f'\nREF: {os.environ["GITHUB_REF"]}'
-                  f'\nREPO_OWNER: {os.environ["GITHUB_REPOSITORY_OWNER"]}')
+def _make_wiki_if_enabled():
+    owner = os.environ.get("GITHUB_REPOSITORY_OWNER")
+    ref   = os.environ.get("GITHUB_REF")
+    evt   = os.environ.get("GITHUB_EVENT_NAME")
+
+    enabled = (
+        owner == "yusancky"
+        and (
+            ref in ("refs/heads/main",)
+            or evt in ("workflow_dispatch", "pull_request")
+        )
+    )
+    if not enabled:
+        return None
+
+    # 创建带 X-AuthKey 的会话
+    session = requests.Session()
+    session.headers["X-authkey"] = os.environ["X_AUTHKEY"]
+
+    return Wiki(
+        "sat.huijiwiki.com",
+        username="雨倩CKY",
+        password=os.environ["BOT_PASSWORD"],
+        session=session,
+    )
+
+
+_wiki = _make_wiki_if_enabled()
+
+def pull(title: str, split_line=False) -> str:
+    """获取页面文本，如果有 split_line=True 则返回 list"""
+    if not _wiki:
+        return ""
+    text = _wiki.page_text(title)
+    return text.splitlines() if split_line else text
+
+def push(title: str, content_id: str, content: str):
+    """将内容写入本地 .wikitext 并推送到 Satwiki，PR 时生成预览文件"""
+    with open(f"{title}.wikitext", "w", encoding="utf-8") as f:
+        f.write(content)
+
+    if _wiki:
+        _wiki.edit(title, content, "Edit via AllUp-Satwiki")
+
+    if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
+        with open("PR_preview.md", "a", encoding="utf-8") as prf:
+            prf.write(
+                f"### {content_id}\n\n```go\n{content}\n```\n\n"
+            )
```

改动要点：
1. 把所有环境判断（branch、event、owner）和 `requests.Session` 的 header 注入都集中到 `_make_wiki_if_enabled` 里  
2. 只在一个地方（模块加载时）创建 `_wiki` 实例，后续 `pull`/`push` 无需再关心环境和会话细节  
3. 保持 `pull`/`push` 逻辑极简、纯粹，易于单元测试和维护

你可以把上面这段 diff 应用到当前的 `AllUp_utils/wiki.py`，看看效果。如果想保留原来的某些细节（比如异常处理、日志打印），也可以在 helper 里补充。
created_at: 2025-05-31T13:28:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,17 +1,27 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from requests import get
 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options
 
+
 def configure_chromedriver():
     chrome_options = Options()
-    for option in ['--headless','--disable-gpu','--window-size=1920,1200','--ignore-certificate-errors','--disable-extensions','--no-sandbox','--disable-dev-shm-usage']:
+    for option in [
+        "--headless",
+        "--disable-gpu",
+        "--window-size=1920,1200",
+        "--ignore-certificate-errors",
+        "--disable-extensions",
+        "--no-sandbox",
+        "--disable-dev-shm-usage",
+    ]:
         chrome_options.add_argument(option)
-    return webdriver.Chrome(options = chrome_options)
+    return webdriver.Chrome(options=chrome_options)
+
 
-def fetch_data(url : str,need_selenium = False):
+def fetch_data(url: str, need_selenium=False):
     if need_selenium:
         need_selenium.get(url)
         return need_selenium.page_source
path: AllUp_utils/web.py
user: login: yusancky
body: 我不打算修改 closed
created_at: 2025-05-31T13:30:45Z
author_association: OWNER
diff_hunk: @@ -3,29 +1,50 @@
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
path: AllUp_utils/wiki.py
user: login: yusancky
body: 我认为这条件有限，我的需求不需要这些改动 closed
created_at: 2025-05-31T13:31:30Z
author_association: OWNER
diff_hunk: @@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
path: .github/dependabot.yml
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** Dependabot 的计划密钥对于 cron 计划无效

更新计划块以使用 `cron:` 而不是 `interval: cron` 和 `cronjob`，如下所示：

```yaml
schedule:
  cron: "26 1 * * 5"
  timezone: "Asia/Shanghai"
```

<details>
<summary>Original comment in English</summary>

**issue (bug_risk):** Dependabot schedule keys are invalid for cron schedules

Update the schedule block to use `cron:` instead of `interval: cron` and `cronjob`, as shown below:

```yaml
schedule:
  cron: "26 1 * * 5"
  timezone: "Asia/Shanghai"
```

</details>
created_at: 2025-05-31T13:36:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,31 +1,50 @@
-# Copyright (c) yusancky. All rights reserved. 
-# Licensed under the Apache License 2.0. See License in the project root for license information. 
+# Copyright (c) yusancky. All rights reserved.
+# Licensed under the Apache License 2.0. See License in the project root for license information.
 
 from os import environ
 from pwiki.wiki import Wiki
+import requests
 
-def PR_TEST():
-    return environ['GITHUB_EVENT_NAME'] == 'pull_request'
-
-def MAIN_REPO_BRANCH():
-    return (environ['GITHUB_REF'] == 'refs/heads/main' and environ['GITHUB_REPOSITORY_OWNER'] == 'yusancky')
-    
-def pull(title : str,split_line = False):
-    if MAIN_REPO_BRANCH() or PR_TEST():
-        print('Unable to find test sources.')
-        try:
-            wiki = Wiki('sat.huijiwiki.com')
-            return wiki.page_text(title)
-        except:
-            print(f'You do not have permission to get password.\nREF: {environ["GITHUB_REF"]}\nREPO_OWNER: {environ["GITHUB_REPOSITORY_OWNER"]}')
+try:
+    MAIN_REPO_BRANCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_REF"] == "refs/heads/main"
+    )
+    TEST_DISPATCH = (
+        environ["GITHUB_REPOSITORY_OWNER"] == "yusancky"
+        and environ["GITHUB_EVENT_NAME"] == "workflow_dispatch"
+    )
+    TEST_PR = environ["GITHUB_EVENT_NAME"] == "pull_request"
+except Exception:
+    MAIN_REPO_BRANCH, TEST_DISPATCH, TEST_PR = False, False, False
+
+_original_session_init = requests.Session.__init__
path: AllUp_utils/wiki.py
user: login: sourcery-ai[bot]
body: **issue (complexity):** 考虑通过集中环境标志逻辑并使用自定义 Session 类来避免全局 monkey-patch 并提高清晰度来重构。

```markdown
您可以通过将 env-flags 封装在一个小的配置对象中来简化，避免全局 monkey-patch，并使用支持身份验证的 Session 子类或工厂。例如：

```python
# 1. 将所有 env 逻辑转换为一个配置
class EnvConfig:
    def __init__(self):
        owner = environ.get("GITHUB_REPOSITORY_OWNER", "")
        ref   = environ.get("GITHUB_REF", "")
        event = environ.get("GITHUB_EVENT_NAME", "")
        self.main_repo_branch = (owner == "yusancky" and ref == "refs/heads/main")
        self.test_dispatch   = (owner == "yusancky" and event == "workflow_dispatch")
        self.test_pr         = (event == "pull_request")

config = EnvConfig()
```

```python
# 2. 定义一个 Session 子类来注入标头
import requests

class AuthSession(requests.Session):
    def __init__(self, authkey: str):
        super().__init__()
        self.headers.update({"X-authkey": authkey})
```

```python
# 3. 按需构建 Wiki 实例
def get_wiki() -> Wiki:
    session = AuthSession(environ["X_AUTHKEY"])
    return Wiki("sat.huijiwiki.com", session=session)
```

```python
# 4. 使用清晰的条件简化 pull()/push()
def pull(title: str, split_line=False) -> str:
    if not any([config.main_repo_branch, config.test_dispatch, config.test_pr]):
        return ""
    return get_wiki().page_text(title)

def push(title: str, content_id: str, content: str) -> None:
    with open(f"{title}.wikitext", "w") as f:
        f.write(content)

    if config.main_repo_branch or config.test_dispatch:
        get_wiki().edit(title, content, "Edit via AllUp-Satwiki")

    if config.test_pr:
        with open("PR_preview.md", "a") as f:
            f.write(f"### {content_id}\n\n```go\n{content}\n```\n\n")
```

这

- 删除 `requests.Session.__init__` monkey-patch
- 集中环境逻辑
- 保持 pull/push 行为相同，但更清晰且更易于测试。

<details>
<summary>Original comment in English</summary>

**issue (complexity):** Consider refactoring by centralizing environment flag logic and using a custom Session class to avoid global monkey-patching and improve clarity.

```markdown
You can simplify by encapsulating env-flags in a small config object, avoiding the global monkey-patch, and using an auth-aware Session subclass or factory. For example:

```python
# 1. Turn all your env-logic into one Config
class EnvConfig:
    def __init__(self):
        owner = environ.get("GITHUB_REPOSITORY_OWNER", "")
        ref   = environ.get("GITHUB_REF", "")
        event = environ.get("GITHUB_EVENT_NAME", "")
        self.main_repo_branch = (owner == "yusancky" and ref == "refs/heads/main")
        self.test_dispatch   = (owner == "yusancky" and event == "workflow_dispatch")
        self.test_pr         = (event == "pull_request")

config = EnvConfig()
```

```python
# 2. Define a Session subclass to inject the header
import requests

class AuthSession(requests.Session):
    def __init__(self, authkey: str):
        super().__init__()
        self.headers.update({"X-authkey": authkey})
```

```python
# 3. Build Wiki instances on demand
def get_wiki() -> Wiki:
    session = AuthSession(environ["X_AUTHKEY"])
    return Wiki("sat.huijiwiki.com", session=session)
```

```python
# 4. Simplify pull()/push() with clear conditionals
def pull(title: str, split_line=False) -> str:
    if not any([config.main_repo_branch, config.test_dispatch, config.test_pr]):
        return ""
    return get_wiki().page_text(title)

def push(title: str, content_id: str, content: str) -> None:
    with open(f"{title}.wikitext", "w") as f:
        f.write(content)

    if config.main_repo_branch or config.test_dispatch:
        get_wiki().edit(title, content, "Edit via AllUp-Satwiki")

    if config.test_pr:
        with open("PR_preview.md", "a") as f:
            f.write(f"### {content_id}\n\n```go\n{content}\n```\n\n")
```

This

- Removes the `requests.Session.__init__` monkey-patch  
- Centralizes environment logic  
- Keeps pull/push behavior identical but much clearer and easier to test.

</details>
created_at: 2025-05-31T13:36:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,8 +3,8 @@ updates:
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
-      time: "06:00"
path: .github/dependabot.yml
user: login: yusancky
body: Dependabot now lets you schedule update frequencies with cron expressions https://github.blog/changelog/2025-04-22-dependabot-now-lets-you-schedule-update-frequencies-with-cron-expressions/
created_at: 2025-05-31T13:44:20Z
author_association: OWNER

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-05-31T12:57:31Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## 审查者指南

此 PR 通过注入 X-authkey 标头来增强已验证的 Satwiki 交互，并重构 wiki 实用程序逻辑，以便基于分支或工作流上下文进行条件客户端实例化，同时还简化了代码格式、使用更新的密钥提升了 CI Python 版本，并更新了文档和 Dependabot 计划。

### 文件级别更改

| 变更 | 详情 | 文件 |
| ------ | ------- | ----- |
| 引入身份验证注入和条件 Wiki 客户端实例化 | <ul><li>从 GitHub 环境定义 MAIN_REPO_BRANCH、TEST_DISPATCH、TEST_PR 标志</li><li>Monkey-patch requests.Session.__init__ 以添加 X-authkey 标头</li><li>在主分支或 PR 上下文中，使用 BOT_PASSWORD 实例化 Wiki 客户端</li><li>更新 pull() 和 push() 以有条件地获取/编辑页面并生成 PR 预览</li></ul> | `AllUp_utils/wiki.py` |
| 重构和重新格式化实用程序模块中的代码风格 | <ul><li>标准化 main.py 中的引号样式和多行格式</li><li>合并列表定义，收紧循环，并在文件打开中添加编码</li><li>清理 Selenium Chrome 选项并调整函数签名</li><li>规范化 build_switch 逻辑格式和错误消息</li></ul> | `main.py`<br/>`AllUp_utils/web.py`<br/>`AllUp_utils/wikitext.py` |
| 提升 CI Python 版本并注入密钥 | <ul><li>将 GitHub Actions Python 版本从 3.12 升级到 3.13</li><li>将 BOT_PASSWORD 和 X_AUTHKEY 作为工作流环境变量注入</li><li>删除 checkout 和 setup 的显式步骤名称</li></ul> | `.github/workflows/AllUp.yml` |
| 更新项目文档 | <ul><li>在 README 中将 AllUp 重命名为 AllUp-Satwiki</li><li>简化计划脚注描述</li></ul> | `README.md` |
| 使 Dependabot 计划与 CI cron 对齐 | <ul><li>将 Dependabot 计划切换为 cron 语法 “26 1 * * 5”</li><li>将时区设置为 Asia/Shanghai 以匹配工作流</li></ul> | `.github/dependabot.yml` |

---

<details>
<summary>提示和命令</summary>

#### 与 Sourcery 交互

- **触发新的审查：** 在 pull request 上评论 `@sourcery-ai review`。
- **继续讨论：** 直接回复 Sourcery 的审查评论。
- **从审查评论生成 GitHub issue：** 通过回复审查评论，要求 Sourcery 从审查评论创建一个 issue。您也可以回复审查评论并使用 `@sourcery-ai issue` 从中创建一个 issue。
- **生成 pull request 标题：** 在 pull request 标题中的任何位置写入 `@sourcery-ai` 以随时生成标题。您也可以在 pull request 上评论 `@sourcery-ai title` 以随时（重新）生成标题。
- **生成 pull request 摘要：** 在 pull request 正文中的任何位置写入 `@sourcery-ai summary` 以随时在您想要的位置生成 PR 摘要。您也可以在 pull request 上评论 `@sourcery-ai summary` 以随时（重新）生成摘要。
- **生成审查者指南：** 在 pull request 上评论 `@sourcery-ai guide` 以随时（重新）生成审查者指南。
- **解决所有 Sourcery 评论：** 在 pull request 上评论 `@sourcery-ai resolve` 以解决所有 Sourcery 评论。如果您已经解决了所有评论并且不想再看到它们，这将非常有用。
- **驳回所有 Sourcery 审查：** 在 pull request 上评论 `@sourcery-ai dismiss` 以驳回所有现有的 Sourcery 审查。如果您想从新的审查开始，这将特别有用 - 不要忘记评论 `@sourcery-ai review` 以触发新的审查！

#### 自定义您的体验

访问您的 [仪表板](https://app.sourcery.ai) 以：
- 启用或禁用审查功能，例如 Sourcery 生成的 pull request 摘要、审查者指南等。
- 更改审查语言。
- 添加、删除或编辑自定义审查说明。
- 调整其他审查设置。

#### 获取帮助

- [联系我们的支持团队](mailto:support@sourcery.ai) 提出问题或反馈。
- 访问我们的 [文档](https://docs.sourcery.ai) 获取详细指南和信息。
- 通过在 [X/Twitter](https://x.com/SourceryAI)、[LinkedIn](https://www.linkedin.com/company/sourcery-ai/) 或 [GitHub](https://github.com/sourcery-ai) 上关注我们，与 Sourcery 团队保持联系。

</details>

<details>
<summary>Original review guide in English</summary>

## Reviewer's Guide

This PR enhances authenticated Satwiki interactions by injecting the X-authkey header and refactors the wiki utility logic for conditional client instantiation based on branch or workflow context, while also streamlining code formatting, bumping the CI Python version with updated secrets, and updating documentation and Dependabot schedules.

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Introduce authentication injection and conditional Wiki client instantiation | <ul><li>Define MAIN_REPO_BRANCH, TEST_DISPATCH, TEST_PR flags from GitHub environment</li><li>Monkey-patch requests.Session.__init__ to add the X-authkey header</li><li>Instantiate Wiki client with BOT_PASSWORD when in main branch or PR contexts</li><li>Update pull() and push() to conditionally fetch/edit pages and produce PR previews</li></ul> | `AllUp_utils/wiki.py` |
| Refactor and reformat code style across utility modules | <ul><li>Standardize quote styles and multi-line formatting in main.py</li><li>Consolidate list definitions, tighten loops, and add encoding in file opens</li><li>Clean up Selenium Chrome options and adjust function signatures</li><li>Normalize build_switch logic formatting and error messages</li></ul> | `main.py`<br/>`AllUp_utils/web.py`<br/>`AllUp_utils/wikitext.py` |
| Bump CI Python version and inject secrets | <ul><li>Upgrade GitHub Actions Python version from 3.12 to 3.13</li><li>Inject BOT_PASSWORD and X_AUTHKEY as workflow environment variables</li><li>Remove explicit step names for checkout and setup</li></ul> | `.github/workflows/AllUp.yml` |
| Update project documentation | <ul><li>Rename AllUp to AllUp-Satwiki in README</li><li>Simplify schedule footnote description</li></ul> | `README.md` |
| Align Dependabot schedule with CI cron | <ul><li>Switch Dependabot schedule to cron syntax “26 1 * * 5”</li><li>Set timezone to Asia/Shanghai to match workflow</li></ul> | `.github/dependabot.yml` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-31T13:00:18Z
body: ## Preview

After _current_ modification of the PR, the program builds the main and TSS content as shown below. The content won't be uploaded to Satwiki before the PR is merged.

### MAIN

```go
<includeonly>{{#switch:{{{1|}}}|t=2025年05月31日21时|1=因上游数据进行格式调整，<code><nowiki>{{AllUp|1}}</nowiki></code> 暂时停用！{{需要更新}}|2={{#switch:{{{section|}}}|Inclination=51.946&deg;|Eccentricity=0.00354|RA ascending node=16.127&nbsp;hr|Argument perigee=103.655&deg;|Mean anomaly=63.643&deg;|Orbital period=87.344&nbsp;min|Epoch of osculation=10 May 2025, 00:35|#default=请输入正确的选项名！}}|3={{#switch:{{{section|}}}|1=8788|2=1159|3=7629|4=7605|#default=请输入正确的选项名！}}|4={{#echarts:option={
  "title": {
    "text": "天宫空间站任务列表",
    "subtext": "上次更新：2025年5月31日（1493）"
  },
  "tooltip": {
    "trigger": "axis",
    "axisPointer": {
      "type": "shadow"
    }
  },
  "grid": {
    "left": "3%",
    "right": "4%",
    "bottom": "3%",
    "containLabel": true
  },
  "xAxis": {
    "type": "value"
  },
  "yAxis": {
    "type": "category",
    "splitLine": {
      "show": false
    },
    "data": ["神舟二十号", "天舟八号", "神舟十九号", "神舟十八号", "天舟七号", "神舟十七号", "神舟十六号", "天舟六号", "神舟十五号", "天舟五号", "梦天实验舱", "问天实验舱", "神舟十四号", "天舟四号", "神舟十三号", "天舟三号", "神舟十二号", "天舟二号", "天和核心舱"]
  },
  "series": [
    {
      "name": "发射时间",
      "type": "bar",
      "stack": "Total",
      "itemStyle": {
        "borderColor": "transparent",
        "color": "transparent"
      },
      "emphasis": {
        "itemStyle": {
          "borderColor": "transparent",
          "color": "transparent"
        }
      },
      "data": [1456, 1296, 1280, 1092, 993, 910, 761, 741, 579, 562, 550, 451, 402, 376, 170, 144, 49, 30, 0]
    },
    {
      "name": "已进行任务天数",
      "type": "bar",
      "stack": "Total",
      "label": {
        "show": true,
        "position": "inside"
      },
      "data": [
        {"value": 37, "itemStyle": {"color": "#fcd34d"} },{"value": 197, "itemStyle": {"color": "#fcd34d"} },{"value": 182, "itemStyle": {"color": "#6ee7b7"} },{"value": 193, "itemStyle": {"color": "#6ee7b7"} },{"value": 305, "itemStyle": {"color": "#6ee7b7"} },{"value": 187, "itemStyle": {"color": "#6ee7b7"} },{"value": 154, "itemStyle": {"color": "#6ee7b7"} },{"value": 254, "itemStyle": {"color": "#6ee7b7"} },{"value": 187, "itemStyle": {"color": "#6ee7b7"} },{"value": 304, "itemStyle": {"color": "#6ee7b7"} },{"value": 943, "itemStyle": {"color": "#fdba74"} },{"value": 1042, "itemStyle": {"color": "#fdba74"} },{"value": 182, "itemStyle": {"color": "#6ee7b7"} },{"value": 189, "itemStyle": {"color": "#6ee7b7"} },{"value": 182, "itemStyle": {"color": "#6ee7b7"} },{"value": 310, "itemStyle": {"color": "#6ee7b7"} },{"value": 92, "itemStyle": {"color": "#6ee7b7"} },{"value": 306, "itemStyle": {"color": "#6ee7b7"} },{"value": 1493, "itemStyle": {"color": "#fdba74"} }
      ]
    }
  ]
}
|style=min-height:380px}}|5={{#switch:{{{sat|}}}|star={{#switch:{{{section|}}}|1=8788|2=1159|3=7629|4=7605|#default=请输入正确的选项名！}}|ow={{#switch:{{{section|}}}|1=660|2=6|3=654|4=652|#default=请输入正确的选项名！}}|kp={{#switch:{{{section|}}}|1=29|2=2|3=27|4=27|#default=请输入正确的选项名！}}|stsh={{#switch:{{{section|}}}|1=193|2=4|3=189|4=189|#default=请输入正确的选项名！}}|xw={{#switch:{{{section|}}}|1=50|2=0|3=50|4=50|#default=请输入正确的选项名！}}|qf={{#switch:{{{section|}}}|1=90|2=0|3=90|4=77|#default=请输入正确的选项名！}}|ynh={{#switch:{{{section|}}}|1=8|2=0|3=8|4=7|#default=请输入正确的选项名！}}|lynk={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|esp={{#switch:{{{section|}}}|1=4|2=3|3=1|4=1|#default=请输入正确的选项名！}}|s1m={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|pln={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|iri={{#switch:{{{section|}}}|1=170|2=68|3=102|4=73|#default=请输入正确的选项名！}}|gbl={{#switch:{{{section|}}}|1=90|2=6|3=84|4=29|#default=请输入正确的选项名！}}|jil={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|slog={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|asts={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|swa={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|glo={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|spr={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|st3={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|par={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|gps={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|bei={{#switch:{{{section|}}}|1=63|2=0|3=63|4=57|#default=请输入正确的选项名！}}|oco={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|hwk={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|kep={{#switch:{{{section|}}}|1=list index out of range|2=list index out of range|3=list index out of range|4=list index out of range|#default=请输入正确的选项名！}}|int={{#switch:{{{section|}}}|1=123|2=2|3=121|4=43|#default=请输入正确的选项名！}}|ses={{#switch:{{{section|}}}|1=65|2=1|3=64|4=38|#default=请输入正确的选项名！}}|#default=请输入正确的卫星名！}}|#default=请输入正确的AllUp编号！}}</includeonly><noinclude>[[Category:模板]]{{documentation}}</noinclude>
```



<!-- thollander/actions-comment-pull-request "actions-wikitext-preview" -->
author_association: NONE