nonebot-plugin-apod 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 lyqgzbl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.1
2
+ Name: nonebot-plugin-apod
3
+ Version: 0.0.1
4
+ Summary: 定时发送 NASA 每日提供的天文图片
5
+ Home-page: https://github.com/lyqgzbl/nonebot-plugin-apod
6
+ License: MIT
7
+ Keywords: nonebot2,NASA
8
+ Author: lyqgzbl
9
+ Author-email: admin@lyqgzbl.com
10
+ Requires-Python: >=3.8,<4.0
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Dist: nonebot-plugin-alconna (>=0.54.0,<0.55.0)
20
+ Requires-Dist: nonebot-plugin-apscheduler (>=0.5.0,<0.6.0)
21
+ Requires-Dist: nonebot-plugin-localstore (>=0.7.0,<0.8.0)
22
+ Requires-Dist: nonebot-plugin-send-anything-anywhere (>=0.7.0,<0.8.0)
23
+ Requires-Dist: nonebot2 (>=2.2.1,<3.0.0)
24
+ Project-URL: Documentation, https://github.com/lyqgzbl/nonebot-plugin-apod#readme
25
+ Project-URL: Repository, https://github.com/lyqgzbl/nonebot-plugin-apod
26
+ Description-Content-Type: text/markdown
27
+
28
+ # nonebot-plugin-apod
@@ -0,0 +1 @@
1
+ # nonebot-plugin-apod
@@ -0,0 +1,133 @@
1
+ import re
2
+ import json
3
+
4
+ from nonebot import require, get_plugin_config
5
+ from nonebot.rule import Rule
6
+ from nonebot.log import logger
7
+ from nonebot.permission import SUPERUSER
8
+ from nonebot.plugin import PluginMetadata, inherit_supported_adapters
9
+
10
+ require("nonebot_plugin_saa")
11
+ require("nonebot_plugin_alconna")
12
+ require("nonebot_plugin_localstore")
13
+ require("nonebot_plugin_apscheduler")
14
+ import nonebot_plugin_localstore as store
15
+ from nonebot_plugin_apscheduler import scheduler
16
+ from nonebot_plugin_alconna import Args, Match, Option, Alconna, CommandMeta, on_alconna
17
+ from nonebot_plugin_saa import SaaTarget, enable_auto_select_bot, PlatformTarget, get_target
18
+
19
+ from .config import Config
20
+ from .apod import send_apod, remove_apod_task, schedule_apod_task
21
+
22
+
23
+ __plugin_meta__ = PluginMetadata(
24
+ name="每日天文一图",
25
+ description="定时发送 NASA 每日提供的天文图片",
26
+ usage="/apod 状态; /apod 关闭; /apod 开启 13:30",
27
+ type="application",
28
+ homepage="https://github.com/lyqgzbl/nonebot-plugin-apod",
29
+ config=Config,
30
+ supported_adapters=inherit_supported_adapters(
31
+ "nonebot_plugin_alconna", "nonebot_plugin_saa"
32
+ ),
33
+ )
34
+
35
+
36
+ enable_auto_select_bot()
37
+ plugin_config = get_plugin_config(Config)
38
+ if not plugin_config.nasa_api_key:
39
+ logger.opt(colors=True).warning("<yellow>缺失必要配置项 'nasa_api_key',已禁用该插件</yellow>")
40
+ def is_enable() -> Rule:
41
+ def _rule() -> bool:
42
+ return bool(plugin_config.nasa_api_key)
43
+ return Rule(_rule)
44
+
45
+
46
+ apod = on_alconna(
47
+ Alconna(
48
+ "apod",
49
+ Option("状态|status"),
50
+ Option("关闭|stop"),
51
+ Option("开启|start", Args["send_time?#每日一图发送时间", str]),
52
+ meta=CommandMeta(
53
+ compact=True,
54
+ description="NASA 每日天文图片设置",
55
+ usage=__plugin_meta__.usage,
56
+ example=(
57
+ "/apod 状态\n"
58
+ "/apod 关闭\n"
59
+ "/apod 开启 13:30"
60
+ ),
61
+ ),
62
+ ),
63
+ rule=is_enable(),
64
+ aliases={"APOD"},
65
+ permission=SUPERUSER,
66
+ use_cmd_start=True,
67
+ )
68
+
69
+
70
+ def is_valid_time_format(time_str: str) -> bool:
71
+ if not re.match(r"^\d{1,2}:\d{2}$", time_str):
72
+ return False
73
+ try:
74
+ hour, minute = map(int, time_str.split(":"))
75
+ return 0 <= hour <= 23 and 0 <= minute <= 59
76
+ except ValueError:
77
+ return False
78
+
79
+
80
+ @apod.assign("status")
81
+ async def apod_status(event):
82
+ task_config_file = store.get_plugin_data_file("apod_task_config.json")
83
+ if not task_config_file.exists():
84
+ await apod.finish("NASA 每日天文一图定时任务未开启")
85
+ try:
86
+ with task_config_file.open("r", encoding="utf-8") as f:
87
+ config = json.load(f)
88
+ tasks = config.get("tasks", [])
89
+ except Exception as e:
90
+ await apod.finish(f"加载任务配置时发生错误:{e}")
91
+ if not tasks:
92
+ await apod.finish("NASA 每日天文一图定时任务未开启")
93
+ current_target = get_target(event)
94
+ for task in tasks:
95
+ target_data = task["target"]
96
+ target = PlatformTarget.deserialize(target_data)
97
+ if target == current_target:
98
+ send_time = task["send_time"]
99
+ job_id = f"send_apod_task_{target.dict()}"
100
+ job = scheduler.get_job(job_id)
101
+ if job:
102
+ next_run = (
103
+ job.next_run_time.strftime("%Y-%m-%d %H:%M:%S")
104
+ if job.next_run_time else "未知"
105
+ )
106
+ await apod.finish(f"NASA 每日天文一图定时任务已开启 | 下次发送时间: {next_run}")
107
+ else:
108
+ await apod.finish("NASA 每日天文一图定时任务未开启")
109
+ await apod.finish("NASA 每日天文一图定时任务未开启")
110
+
111
+
112
+ @apod.assign("stop")
113
+ async def apod_stop(target: SaaTarget):
114
+ remove_apod_task(target)
115
+ await apod.finish("已关闭 NASA 每日天文一图定时任务")
116
+
117
+
118
+ @apod.assign("start")
119
+ async def apod_start(send_time: Match[str], target: SaaTarget):
120
+ if send_time.available:
121
+ time = send_time.result
122
+ if not is_valid_time_format(time):
123
+ await apod.send("时间格式不正确,请使用 HH:MM 格式")
124
+ try:
125
+ schedule_apod_task(time, target)
126
+ await apod.send(f"已开启 NASA 每日天文一图定时任务,发送时间为 {time}")
127
+ except Exception as e:
128
+ logger.error(f"设置 NASA 每日天文一图定时任务时发生错误:{e}")
129
+ await apod.finish("设置 NASA 每日天文一图定时任务时发生错误")
130
+ else:
131
+ default_time = plugin_config.default_apod_send_time
132
+ schedule_apod_task(default_time, target)
133
+ await apod.finish(f"已开启 NASA 每日天文一图定时任务,默认发送时间为 {default_time}")
@@ -0,0 +1,121 @@
1
+ import datetime
2
+ import httpx
3
+ import json
4
+ import nonebot_plugin_localstore as store
5
+
6
+ from nonebot import get_plugin_config, get_bot
7
+ from nonebot.log import logger
8
+ from nonebot_plugin_apscheduler import scheduler
9
+ from nonebot_plugin_saa import Text, Image, PlatformTarget
10
+ from .config import Config
11
+
12
+ plugin_config = get_plugin_config(Config)
13
+ NASA_API_URL = "https://api.nasa.gov/planetary/apod"
14
+ NASA_API_KEY = plugin_config.nasa_api_key
15
+ task_config_file = store.get_plugin_data_file("apod_task_config.json")
16
+
17
+
18
+ def save_task_configs(tasks: list):
19
+ try:
20
+ serialized_tasks = [
21
+ {"send_time": task["send_time"], "target": task["target"].dict()} for task in tasks
22
+ ]
23
+ with task_config_file.open("w", encoding="utf-8") as f:
24
+ json.dump({"tasks": serialized_tasks}, f, ensure_ascii=False, indent=4)
25
+ logger.info("NASA 每日天文一图定时任务配置已保存")
26
+ except Exception as e:
27
+ logger.error(f"保存 NASA 每日天文一图定时任务配置时发生错误:{e}")
28
+
29
+
30
+ def load_task_configs():
31
+ if not task_config_file.exists():
32
+ return []
33
+ try:
34
+ with task_config_file.open("r", encoding="utf-8") as f:
35
+ config = json.load(f)
36
+ tasks = [
37
+ {"send_time": task["send_time"], "target": PlatformTarget.deserialize(task["target"])}
38
+ for task in config.get("tasks", [])
39
+ ]
40
+ return tasks
41
+ except Exception as e:
42
+ logger.error(f"加载 NASA 每日天文一图定时任务配置时发生错误:{e}")
43
+ return []
44
+
45
+
46
+ async def fetch_apod_data():
47
+ try:
48
+ async with httpx.AsyncClient() as client:
49
+ response = await client.get(NASA_API_URL, params={"api_key": NASA_API_KEY})
50
+ response.raise_for_status()
51
+ return response.json()
52
+ except httpx.RequestError as e:
53
+ logger.error(f"获取 NASA 每日天文一图数据时发生错误: {e}")
54
+ return None
55
+
56
+
57
+ async def send_apod(target: PlatformTarget):
58
+ apod_data = await fetch_apod_data()
59
+ if apod_data:
60
+ title = apod_data.get("title", "NASA APOD")
61
+ url = apod_data.get("url")
62
+ try:
63
+ await Image(url).send_to(target, bot=get_bot())
64
+ await Text(f"链接:{url}").send_to(target, bot=get_bot())
65
+ except Exception as e:
66
+ logger.error(f"发送 NASA 每日天文一图时发生错误:{e}")
67
+ await Text("发送 NASA 每日天文一图时发生错误").send_to(target, bot=get_bot())
68
+ else:
69
+ logger.error("无法获取今天的天文图片")
70
+ await Text("无法获取今天的天文图片。").send_to(target, bot=get_bot())
71
+
72
+
73
+ def schedule_apod_task(send_time: str, target: PlatformTarget):
74
+ try:
75
+ hour, minute = map(int, send_time.split(":"))
76
+ job_id = f"send_apod_task_{target.dict()}"
77
+ scheduler.add_job(
78
+ func=send_apod,
79
+ trigger="cron",
80
+ args=[target],
81
+ hour=hour,
82
+ minute=minute,
83
+ id=job_id,
84
+ max_instances=1,
85
+ replace_existing=True,
86
+ )
87
+ logger.info(f"已成功设置 NASA 每日天文一图定时任务,发送时间为 {send_time} (目标: {target})")
88
+ tasks = load_task_configs()
89
+ tasks = [task for task in tasks if task["target"] != target]
90
+ tasks.append({"send_time": send_time, "target": target})
91
+ save_task_configs(tasks)
92
+ except ValueError:
93
+ logger.error(f"时间格式错误:{send_time},请使用 HH:MM 格式")
94
+ raise ValueError(f"时间格式错误:{send_time}")
95
+ except Exception as e:
96
+ logger.error(f"设置 NASA 每日天文一图定时任务时发生错误:{e}")
97
+
98
+
99
+ def remove_apod_task(target: PlatformTarget):
100
+ job_id = f"send_apod_task_{target.dict()}"
101
+ job = scheduler.get_job(job_id)
102
+ if job:
103
+ job.remove()
104
+ logger.info(f"已移除 NASA 每日天文一图定时任务 (目标: {target})")
105
+ tasks = load_task_configs()
106
+ tasks = [task for task in tasks if task["target"] != target]
107
+ save_task_configs(tasks)
108
+ else:
109
+ logger.info(f"未找到 NASA 每日天文一图定时任务 (目标: {target})")
110
+
111
+
112
+ try:
113
+ tasks = load_task_configs()
114
+ for task in tasks:
115
+ send_time = task["send_time"]
116
+ target = task["target"]
117
+ if send_time and target:
118
+ schedule_apod_task(send_time, target)
119
+ logger.debug("已恢复所有 NASA 每日天文一图定时任务")
120
+ except Exception as e:
121
+ logger.error(f"恢复 NASA 每日天文一图定时任务时发生错误:{e}")
@@ -0,0 +1,7 @@
1
+ from typing import Optional
2
+ from pydantic import BaseModel
3
+
4
+
5
+ class Config(BaseModel):
6
+ nasa_api_key: Optional[str] = None
7
+ default_apod_send_time: str = "13:00"
@@ -0,0 +1,23 @@
1
+ [tool.poetry]
2
+ name = "nonebot-plugin-apod"
3
+ version = "0.0.1"
4
+ description = "定时发送 NASA 每日提供的天文图片"
5
+ readme = "README.md"
6
+ authors = ["lyqgzbl <admin@lyqgzbl.com>"]
7
+ license = "MIT"
8
+ homepage = "https://github.com/lyqgzbl/nonebot-plugin-apod"
9
+ repository = "https://github.com/lyqgzbl/nonebot-plugin-apod"
10
+ documentation = "https://github.com/lyqgzbl/nonebot-plugin-apod#readme"
11
+ keywords = ["nonebot2", "NASA"]
12
+
13
+ [tool.poetry.dependencies]
14
+ python = "^3.8"
15
+ nonebot2 = "^2.2.1"
16
+ nonebot-plugin-alconna = "^0.54.0"
17
+ nonebot-plugin-localstore = "^0.7.0"
18
+ nonebot-plugin-apscheduler = "^0.5.0"
19
+ nonebot-plugin-send-anything-anywhere = "^0.7.0"
20
+
21
+ [build-system]
22
+ requires = ["poetry-core>=1.0.0"]
23
+ build-backend = "poetry.core.masonry.api"