mioku-plugin-meme 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/skills.ts ADDED
@@ -0,0 +1,157 @@
1
+ import type { AISkill, AITool } from "../../src";
2
+ import type { MemeImageSourceOptions } from "./types";
3
+ import { getMemeRuntimeState } from "./runtime";
4
+
5
+ function parseImageSource(args: any): {
6
+ ok: boolean;
7
+ source?: MemeImageSourceOptions;
8
+ message?: string;
9
+ } {
10
+ const sourceType = String(args?.source_type || "").trim();
11
+ if (!sourceType) {
12
+ return {
13
+ ok: false,
14
+ message: "缺少 source_type。可选值: user_avatar 或 message_image。",
15
+ };
16
+ }
17
+
18
+ if (sourceType === "user_avatar") {
19
+ const qq = Number(args?.qq);
20
+ if (!Number.isFinite(qq) || qq <= 0) {
21
+ return {
22
+ ok: false,
23
+ message: "source_type=user_avatar 时必须提供有效的 qq。",
24
+ };
25
+ }
26
+ return {
27
+ ok: true,
28
+ source: {
29
+ type: "user_avatar",
30
+ qq,
31
+ },
32
+ };
33
+ }
34
+
35
+ if (sourceType === "message_image") {
36
+ const messageId = Number(args?.message_id);
37
+ if (!Number.isFinite(messageId) || messageId <= 0) {
38
+ return {
39
+ ok: false,
40
+ message: "source_type=message_image 时必须提供有效的 message_id。",
41
+ };
42
+ }
43
+ return {
44
+ ok: true,
45
+ source: {
46
+ type: "message_image",
47
+ messageId,
48
+ },
49
+ };
50
+ }
51
+
52
+ return {
53
+ ok: false,
54
+ message: "source_type 无效。只能是 user_avatar 或 message_image。",
55
+ };
56
+ }
57
+
58
+ const memeSkills: AISkill[] = [
59
+ {
60
+ name: "meme",
61
+ description:
62
+ "搜索,制作和发送各种各样的表情包,可以使用聊天中的图片或用户头像制作,如制作摸别人活其他的表情",
63
+ permission: "member",
64
+ tools: [
65
+ {
66
+ name: "search_memes",
67
+ description: "按关键词搜索可用的 meme 表情关键词",
68
+ parameters: {
69
+ type: "object",
70
+ properties: {
71
+ query: {
72
+ type: "string",
73
+ description: "搜索关键词,可以是中文或英文片段",
74
+ },
75
+ },
76
+ required: ["query"],
77
+ },
78
+ handler: async (args: any) => {
79
+ const runtime = getMemeRuntimeState().runtime;
80
+ if (!runtime) {
81
+ return "meme 插件尚未初始化";
82
+ }
83
+
84
+ await runtime.ensureCache();
85
+ const hits = runtime.searchKeywords(String(args?.query || ""));
86
+ return hits.length > 0
87
+ ? hits.join("、")
88
+ : "没有找到匹配的 meme 关键词";
89
+ },
90
+ } as AITool,
91
+ {
92
+ name: "send_meme",
93
+ description:
94
+ "发送 meme。必须指定图片来源:用户头像(qq)或聊天图片(message_id)。",
95
+ parameters: {
96
+ type: "object",
97
+ properties: {
98
+ keyword: {
99
+ type: "string",
100
+ description: "要生成的 meme 关键词",
101
+ },
102
+ text: {
103
+ type: "string",
104
+ description: "文本内容,多段文本用 / 分隔",
105
+ },
106
+ args: {
107
+ type: "string",
108
+ description: "额外参数,例如 圆、左、循环 等",
109
+ },
110
+ source_type: {
111
+ type: "string",
112
+ description: "图片来源类型,只能是 user_avatar 或 message_image",
113
+ enum: ["user_avatar", "message_image"],
114
+ },
115
+ qq: {
116
+ type: "number",
117
+ description: "source_type=user_avatar 时必填,头像对应 QQ 号",
118
+ },
119
+ message_id: {
120
+ type: "number",
121
+ description:
122
+ "source_type=message_image 时必填,包含图片的消息 message_id",
123
+ },
124
+ },
125
+ required: ["keyword", "source_type"],
126
+ },
127
+ handler: async (args: any, runtimeCtx?: any) => {
128
+ const runtime = getMemeRuntimeState().runtime;
129
+ const ctx = runtimeCtx?.ctx;
130
+ const event = runtimeCtx?.event || runtimeCtx?.rawEvent;
131
+ if (!runtime) {
132
+ return "meme 插件尚未初始化";
133
+ }
134
+ if (!ctx || !event) {
135
+ return "当前上下文不支持发送 meme";
136
+ }
137
+
138
+ const source = parseImageSource(args);
139
+ if (!source.ok) {
140
+ return source.message || "图片来源参数不合法";
141
+ }
142
+
143
+ const result = await runtime.generateByKeyword(ctx, event, {
144
+ keyword: String(args?.keyword || ""),
145
+ text: args?.text ? String(args.text) : "",
146
+ args: args?.args ? String(args.args) : "",
147
+ imageSource: source.source,
148
+ send: true,
149
+ });
150
+ return result.message;
151
+ },
152
+ } as AITool,
153
+ ],
154
+ },
155
+ ];
156
+
157
+ export default memeSkills;
package/types.ts ADDED
@@ -0,0 +1,93 @@
1
+ export interface MemeApiConfig {
2
+ baseUrl: string;
3
+ timeoutMs: number;
4
+ }
5
+
6
+ export interface MemeTriggerConfig {
7
+ requirePrefix: boolean;
8
+ prefixes: string[];
9
+ directKeywordNeedPrefix: boolean;
10
+ }
11
+
12
+ export interface MemeBehaviorConfig {
13
+ quoteReply: boolean;
14
+ useSenderAvatarFallback: boolean;
15
+ includePreviewInDetail: boolean;
16
+ maxSearchResults: number;
17
+ }
18
+
19
+ export interface MemeCacheConfig {
20
+ refreshOnStartup: boolean;
21
+ }
22
+
23
+ export interface MemePermissionConfig {
24
+ ownerOnlyUpdate: boolean;
25
+ }
26
+
27
+ export interface MemeBaseConfig {
28
+ api: MemeApiConfig;
29
+ trigger: MemeTriggerConfig;
30
+ behavior: MemeBehaviorConfig;
31
+ cache: MemeCacheConfig;
32
+ permissions: MemePermissionConfig;
33
+ }
34
+
35
+ export interface MemeFilterConfig {
36
+ enabled: boolean;
37
+ blockedKeywords: string[];
38
+ replyOnBlocked: boolean;
39
+ }
40
+
41
+ export type MemeImageSourceType = "auto" | "user_avatar" | "message_image";
42
+
43
+ export interface MemeImageSourceOptions {
44
+ type?: MemeImageSourceType;
45
+ qq?: number;
46
+ messageId?: number;
47
+ }
48
+
49
+ export interface MemeInfoParams {
50
+ min_images?: number;
51
+ max_images?: number;
52
+ min_texts?: number;
53
+ max_texts?: number;
54
+ default_texts?: string[];
55
+ }
56
+
57
+ export interface MemeInfo {
58
+ key: string;
59
+ keywords: string[];
60
+ params?: MemeInfoParams;
61
+ params_type?: MemeInfoParams;
62
+ }
63
+
64
+ export interface MemeKeywordMatch {
65
+ keyword: string;
66
+ key: string;
67
+ info: MemeInfo;
68
+ rest: string;
69
+ }
70
+
71
+ export interface MemeUserInfo {
72
+ name: string;
73
+ gender: string;
74
+ }
75
+
76
+ export interface MemeGenerateOptions {
77
+ keyword: string;
78
+ text?: string;
79
+ args?: string;
80
+ send?: boolean;
81
+ quoteReply?: boolean;
82
+ randomLabel?: string;
83
+ imageSource?: MemeImageSourceOptions;
84
+ }
85
+
86
+ export interface MemeGenerateResult {
87
+ ok: boolean;
88
+ message: string;
89
+ keyword?: string;
90
+ key?: string;
91
+ shouldNotice?: boolean;
92
+ noticeInstruction?: string;
93
+ }