koishi-plugin-wordpress-notifier 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # WordPress 文章自动推送插件
2
+
3
+ 自动从 WordPress 网站获取最新文章并推送到指定 QQ 群或私聊。
4
+
5
+ ## 功能特性
6
+
7
+ - 自动从 WordPress REST API 获取最新文章
8
+ - 定时推送新文章到指定 QQ 群或私聊
9
+ - 支持手动查询最新文章和文章列表
10
+ - 支持 @全体成员
11
+ - 完善的去重机制,避免重复推送
12
+ - 采用服务模式架构,便于扩展和维护
13
+ - 支持自动推送开关
14
+
15
+ ## 安装
16
+
17
+ 插件已集成到项目中,无需额外安装。
18
+
19
+ ## 配置
20
+
21
+ 在 `koishi.yml` 中配置插件:
22
+
23
+ ```yaml
24
+ wordpress-notifier:
25
+ wordpressUrl: 'https://your-wordpress-site.com' # WordPress 网站地址
26
+ interval: 3600000 # 检查间隔(毫秒,默认 1 小时)
27
+ targets:
28
+ - '2801323326' # 推送目标(群号或 QQ 号)
29
+ enableAutoPush: true # 是否启用自动推送
30
+ mentionAll: false # 是否 @全体成员
31
+ maxArticles: 5 # 每次最多推送的文章数量
32
+ ```
33
+
34
+ ## 使用命令
35
+
36
+ ### 查看最新文章
37
+ ```
38
+ wordpress.latest
39
+ ```
40
+ 显示最新的 WordPress 文章列表,包含标题、日期和链接。
41
+
42
+ ### 查看文章列表
43
+ ```
44
+ wordpress.list
45
+ ```
46
+ 显示文章 ID 和标题的简洁列表。
47
+
48
+ ### 手动推送最新文章
49
+ ```
50
+ wordpress.push
51
+ ```
52
+ 立即检查并推送最新文章(即使自动推送已关闭)。
53
+
54
+ ### 查看插件状态
55
+ ```
56
+ wordpress.status
57
+ ```
58
+ 显示当前插件配置状态,包括网站地址、检查间隔、推送目标等。
59
+
60
+ ### 切换自动推送开关
61
+ ```
62
+ wordpress.toggle
63
+ ```
64
+ 开启或关闭自动推送功能。
65
+
66
+ ### 切换 @全体成员 开关
67
+ ```
68
+ wordpress.mention
69
+ ```
70
+ 开启或关闭 @全体成员 功能。
71
+
72
+ ## 工作原理
73
+
74
+ 1. 插件启动时会自动创建数据库表 `wordpress_posts` 用于记录已推送的文章
75
+ 2. 定时器每隔指定时间(默认 1 小时)检查一次 WordPress 网站的最新文章
76
+ 3. 对于每篇新文章,检查是否已推送过
77
+ 4. 如果是新文章,则格式化消息并推送到所有配置的目标
78
+ 5. 推送成功后,将文章 ID 记录到数据库中
79
+
80
+ ## 注意事项
81
+
82
+ - WordPress 网站必须启用 REST API(默认启用)
83
+ - 确保机器人有权限向目标群或私聊发送消息
84
+ - @全体成员 功能需要机器人有相应权限
85
+ - 建议设置合理的检查间隔,避免频繁请求 WordPress 网站
86
+
87
+ ## 开发
88
+
89
+ 插件位于 `external/wordpress-notifier/` 目录。
90
+
91
+ ### 编译插件
92
+ ```bash
93
+ cd external/wordpress-notifier
94
+ yarn build
95
+ ```
96
+
97
+ ### 重新安装依赖
98
+ ```bash
99
+ cd external/wordpress-notifier
100
+ yarn install
101
+ ```
package/lib/index.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { Context, Schema } from 'koishi';
2
+ export declare const name = "wordpress-notifier";
3
+ export interface Config {
4
+ wordpressUrl: string;
5
+ interval: number;
6
+ targets: string[];
7
+ enableAutoPush: boolean;
8
+ mentionAll: boolean;
9
+ maxArticles: number;
10
+ }
11
+ export interface WordPressPost {
12
+ id: number;
13
+ title: {
14
+ rendered: string;
15
+ };
16
+ link: string;
17
+ date: string;
18
+ excerpt: {
19
+ rendered: string;
20
+ };
21
+ author: number;
22
+ categories: number[];
23
+ tags: number[];
24
+ }
25
+ export declare const Config: Schema<Config>;
26
+ export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js ADDED
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Config = exports.name = void 0;
4
+ exports.apply = apply;
5
+ const koishi_1 = require("koishi");
6
+ exports.name = 'wordpress-notifier';
7
+ exports.Config = koishi_1.Schema.object({
8
+ wordpressUrl: koishi_1.Schema.string().description('WordPress 网站地址(例如:https://example.com)'),
9
+ interval: koishi_1.Schema.number().default(3600000).description('检查间隔(毫秒,默认 1 小时)'),
10
+ targets: koishi_1.Schema.array(koishi_1.Schema.string()).description('推送目标(群号或 QQ 号)'),
11
+ enableAutoPush: koishi_1.Schema.boolean().default(true).description('是否启用自动推送'),
12
+ mentionAll: koishi_1.Schema.boolean().default(false).description('是否 @全体成员'),
13
+ maxArticles: koishi_1.Schema.number().default(5).description('每次最多推送的文章数量')
14
+ });
15
+ function apply(ctx, config) {
16
+ ctx.logger.info('WordPress 推送插件已加载');
17
+ const pushedPosts = new Set();
18
+ async function fetchLatestPosts() {
19
+ try {
20
+ const url = `${config.wordpressUrl}/wp-json/wp/v2/posts?per_page=${config.maxArticles}&orderby=date&order=desc`;
21
+ ctx.logger.info(`正在获取文章: ${url}`);
22
+ const response = await ctx.http.get(url);
23
+ ctx.logger.info(`成功获取 ${response.length} 篇文章`);
24
+ return response;
25
+ }
26
+ catch (error) {
27
+ ctx.logger.error(`获取 WordPress 文章失败: ${error}`);
28
+ return [];
29
+ }
30
+ }
31
+ function isPostPushed(postId) {
32
+ return pushedPosts.has(postId);
33
+ }
34
+ function markPostAsPushed(postId) {
35
+ pushedPosts.add(postId);
36
+ }
37
+ function formatPostMessage(post, mention = false) {
38
+ const title = post.title.rendered.replace(/<[^>]*>/g, '');
39
+ const excerpt = post.excerpt.rendered.replace(/<[^>]*>/g, '').substring(0, 100);
40
+ const date = new Date(post.date).toLocaleString('zh-CN');
41
+ let message = '';
42
+ if (mention && config.mentionAll) {
43
+ message += '@全体成员\n';
44
+ }
45
+ message += `📝 ${title}\n`;
46
+ message += `📅 ${date}\n`;
47
+ message += `📄 ${excerpt}...\n`;
48
+ message += `🔗 ${post.link}`;
49
+ return message;
50
+ }
51
+ async function pushNewPosts() {
52
+ if (!config.enableAutoPush)
53
+ return;
54
+ const posts = await fetchLatestPosts();
55
+ if (posts.length === 0)
56
+ return;
57
+ for (const post of posts) {
58
+ if (!isPostPushed(post.id)) {
59
+ const message = formatPostMessage(post, true);
60
+ for (const target of config.targets) {
61
+ try {
62
+ await ctx.broadcast([`onebot:${target}`], message);
63
+ ctx.logger.info(`已推送文章到 ${target}: ${post.title.rendered}`);
64
+ }
65
+ catch (error) {
66
+ ctx.logger.error(`推送文章到 ${target} 失败: ${error}`);
67
+ }
68
+ }
69
+ markPostAsPushed(post.id);
70
+ }
71
+ }
72
+ }
73
+ ctx.command('wordpress.latest', '查看最新文章')
74
+ .action(async () => {
75
+ ctx.logger.info('命令 wordpress.latest 被调用');
76
+ const posts = await fetchLatestPosts();
77
+ if (posts.length === 0) {
78
+ ctx.logger.info('没有找到文章');
79
+ return '暂无文章';
80
+ }
81
+ let message = '📰 最新文章:\n\n';
82
+ for (const post of posts) {
83
+ const title = post.title.rendered.replace(/<[^>]*>/g, '');
84
+ const date = new Date(post.date).toLocaleString('zh-CN');
85
+ message += `${title}\n📅 ${date}\n🔗 ${post.link}\n\n`;
86
+ }
87
+ ctx.logger.info(`准备返回消息,长度: ${message.length}`);
88
+ return message;
89
+ });
90
+ ctx.command('wordpress.list', '查看文章列表')
91
+ .action(async () => {
92
+ ctx.logger.info('命令 wordpress.list 被调用');
93
+ const posts = await fetchLatestPosts();
94
+ if (posts.length === 0) {
95
+ return '暂无文章';
96
+ }
97
+ let message = '📚 文章列表:\n\n';
98
+ for (const post of posts) {
99
+ const title = post.title.rendered.replace(/<[^>]*>/g, '');
100
+ message += `${post.id}. ${title}\n`;
101
+ }
102
+ return message;
103
+ });
104
+ ctx.command('wordpress.push', '手动推送最新文章')
105
+ .action(async () => {
106
+ ctx.logger.info('命令 wordpress.push 被调用');
107
+ await pushNewPosts();
108
+ return '已检查并推送最新文章';
109
+ });
110
+ ctx.command('wordpress.status', '查看插件状态')
111
+ .action(() => {
112
+ ctx.logger.info('命令 wordpress.status 被调用');
113
+ return `📊 WordPress 推送插件状态:
114
+ 🌐 网站地址: ${config.wordpressUrl}
115
+ ⏰ 检查间隔: ${config.interval / 1000} 秒
116
+ 🎯 推送目标: ${config.targets.join(', ')}
117
+ 🔔 自动推送: ${config.enableAutoPush ? '开启' : '关闭'}
118
+ 📢 @全体成员: ${config.mentionAll ? '开启' : '关闭'}
119
+ 📝 最多推送: ${config.maxArticles} 篇`;
120
+ });
121
+ ctx.command('wordpress.toggle', '切换自动推送开关')
122
+ .action(async () => {
123
+ ctx.logger.info('命令 wordpress.toggle 被调用');
124
+ config.enableAutoPush = !config.enableAutoPush;
125
+ return `自动推送已${config.enableAutoPush ? '开启' : '关闭'}`;
126
+ });
127
+ ctx.command('wordpress.mention', '切换 @全体成员 开关')
128
+ .action(async () => {
129
+ ctx.logger.info('命令 wordpress.mention 被调用');
130
+ config.mentionAll = !config.mentionAll;
131
+ return `@全体成员 已${config.mentionAll ? '开启' : '关闭'}`;
132
+ });
133
+ ctx.command('wordpress', 'WordPress 推送插件菜单')
134
+ .action(() => {
135
+ ctx.logger.info('命令 wordpress 被调用');
136
+ return `📚 WordPress 推送插件菜单:
137
+
138
+ 🔹 /wordpress.status - 查看插件状态
139
+ 🔹 /wordpress.latest - 查看最新文章
140
+ 🔹 /wordpress.list - 查看文章列表
141
+ 🔹 /wordpress.push - 手动推送最新文章
142
+ 🔹 /wordpress.toggle - 切换自动推送开关
143
+ 🔹 /wordpress.mention - 切换 @全体成员 开关
144
+
145
+ 💡 提示:所有命令都需要加 / 前缀`;
146
+ });
147
+ ctx.on('ready', async () => {
148
+ ctx.logger.info('WordPress 推送插件已就绪');
149
+ await pushNewPosts();
150
+ });
151
+ ctx.setInterval(() => {
152
+ pushNewPosts();
153
+ }, config.interval);
154
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "koishi-plugin-wordpress-notifier",
3
+ "version": "1.0.0",
4
+ "description": "WordPress 文章自动推送到 QQ",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "files": [
8
+ "lib",
9
+ "data"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Your Name <your.email@example.com>",
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "build:watch": "tsc --watch",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "dependencies": {
19
+ "koishi": "^4.18.10"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^20.0.0",
23
+ "typescript": "^5.0.0"
24
+ },
25
+ "peerDependencies": {
26
+ "koishi": "^4.18.10"
27
+ },
28
+ "keywords": [
29
+ "koishi",
30
+ "plugin",
31
+ "wordpress",
32
+ "notifier",
33
+ "qq"
34
+ ],
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/your-username/koishi-plugin-wordpress-notifier.git"
38
+ },
39
+ "homepage": "https://github.com/your-username/koishi-plugin-wordpress-notifier#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/your-username/koishi-plugin-wordpress-notifier/issues"
42
+ },
43
+ "engines": {
44
+ "node": ">=14.0.0"
45
+ }
46
+ }