koishi-plugin-vrchat 0.0.2 → 0.0.4
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/lib/index.d.ts +5 -0
- package/lib/index.js +60 -17
- package/package.json +7 -4
- package/readme.md +1 -1
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -28,10 +28,19 @@ __export(index_exports, {
|
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
29
|
var import_koishi = require("koishi");
|
|
30
30
|
var name = "vrchat";
|
|
31
|
-
var inject = ["http"];
|
|
31
|
+
var inject = ["http", "cache"];
|
|
32
32
|
var Config = import_koishi.Schema.object({});
|
|
33
|
+
function countryCodeToEmoji(code) {
|
|
34
|
+
if (!code || code.length !== 2) return "";
|
|
35
|
+
const A = 127462;
|
|
36
|
+
const offset = "A".charCodeAt(0);
|
|
37
|
+
const chars = code.toUpperCase().split("");
|
|
38
|
+
const first = A + (chars[0].charCodeAt(0) - offset);
|
|
39
|
+
const second = A + (chars[1].charCodeAt(0) - offset);
|
|
40
|
+
return String.fromCodePoint(first) + String.fromCodePoint(second);
|
|
41
|
+
}
|
|
42
|
+
__name(countryCodeToEmoji, "countryCodeToEmoji");
|
|
33
43
|
function apply(ctx, config) {
|
|
34
|
-
let auth;
|
|
35
44
|
ctx.command("vrchat-login", "登录 VRChat API").action(async ({ session }) => {
|
|
36
45
|
if (!session.isDirect) return "请通过私聊进行登录";
|
|
37
46
|
await session.send("请输入用户名或邮箱地址:");
|
|
@@ -56,24 +65,28 @@ function apply(ctx, config) {
|
|
|
56
65
|
await session.send("请输入发送到邮箱的验证码:");
|
|
57
66
|
const code = await session.prompt();
|
|
58
67
|
if (!code) return "输入超时。";
|
|
59
|
-
const cookie = authResp.headers.get("set-cookie").split("; ")
|
|
68
|
+
const cookie = authResp.headers.get("set-cookie").split("; ");
|
|
60
69
|
const emailOtpResp = await ctx.http.post("https://api.vrchat.cloud/api/1/auth/twofactorauth/emailotp/verify", { code }, {
|
|
61
70
|
headers: {
|
|
62
71
|
"User-Agent": "VRCX 2026.02.11",
|
|
63
|
-
"Cookie": cookie
|
|
72
|
+
"Cookie": cookie[0]
|
|
64
73
|
},
|
|
65
74
|
responseType: "json",
|
|
66
75
|
validateStatus: /* @__PURE__ */ __name((status) => status < 500, "validateStatus")
|
|
67
76
|
});
|
|
68
77
|
if (emailOtpResp.verified) {
|
|
69
|
-
|
|
78
|
+
const expires = new Date(cookie[3].split("=")[1]);
|
|
79
|
+
await ctx.cache.set("vrchat_auth", "cookie", cookie[0], expires.getTime() - Date.now());
|
|
70
80
|
return "登录成功";
|
|
81
|
+
} else if (emailOtpResp.error) {
|
|
82
|
+
return emailOtpResp.error.message;
|
|
71
83
|
}
|
|
72
84
|
} else {
|
|
73
85
|
ctx.logger.info(authResp);
|
|
74
86
|
}
|
|
75
87
|
});
|
|
76
88
|
ctx.command("vrchat-avatars <keyword:text>", "检索 VRChat 模型").option("number", "-n <value:number>", { fallback: 10 }).action(async ({ session, options }, keyword) => {
|
|
89
|
+
const auth = await ctx.cache.get("vrchat_auth", "cookie");
|
|
77
90
|
if (!auth) return "请先登录";
|
|
78
91
|
if (!keyword) return "请输入关键词";
|
|
79
92
|
const [msgId] = await session.send("检索中…");
|
|
@@ -94,6 +107,10 @@ function apply(ctx, config) {
|
|
|
94
107
|
} catch {
|
|
95
108
|
}
|
|
96
109
|
}
|
|
110
|
+
if (avatarlist.length === 0) {
|
|
111
|
+
await session.bot.deleteMessage(session.channelId, msgId);
|
|
112
|
+
return "无检索结果";
|
|
113
|
+
}
|
|
97
114
|
await session.send(`<message forward>${avatarlist.map(
|
|
98
115
|
(e) => `<message>模型名:
|
|
99
116
|
${e.name}
|
|
@@ -119,6 +136,7 @@ ${new Date(e.updated_at).toLocaleString()}<img src="${e.imageUrl}"></img></messa
|
|
|
119
136
|
await session.bot.deleteMessage(session.channelId, msgId);
|
|
120
137
|
});
|
|
121
138
|
ctx.command("vrchat-worlds <keyword:text>", "检索 VRChat 世界").option("number", "-n <value:number>", { fallback: 10 }).action(async ({ session, options }, keyword) => {
|
|
139
|
+
const auth = await ctx.cache.get("vrchat_auth", "cookie");
|
|
122
140
|
if (!auth) return "请先登录";
|
|
123
141
|
if (!keyword) return "请输入关键词";
|
|
124
142
|
const [msgId] = await session.send("检索中…");
|
|
@@ -129,6 +147,10 @@ ${new Date(e.updated_at).toLocaleString()}<img src="${e.imageUrl}"></img></messa
|
|
|
129
147
|
},
|
|
130
148
|
responseType: "json"
|
|
131
149
|
});
|
|
150
|
+
if (resp.length === 0) {
|
|
151
|
+
await session.bot.deleteMessage(session.channelId, msgId);
|
|
152
|
+
return "无检索结果";
|
|
153
|
+
}
|
|
132
154
|
const messages = [];
|
|
133
155
|
for (const item of resp) {
|
|
134
156
|
let tags = [];
|
|
@@ -159,12 +181,13 @@ ${item.favorites}
|
|
|
159
181
|
${new Date(item.created_at).toLocaleString()}
|
|
160
182
|
|
|
161
183
|
最后更新时间:
|
|
162
|
-
${new Date(item.updated_at).toLocaleString()}<img src="${item.
|
|
184
|
+
${new Date(item.updated_at).toLocaleString()}<img src="${item.thumbnailImageUrl}"></img></message>`);
|
|
163
185
|
}
|
|
164
186
|
await session.send(`<message forward>${messages.join("")}</message>`);
|
|
165
187
|
await session.bot.deleteMessage(session.channelId, msgId);
|
|
166
188
|
});
|
|
167
189
|
ctx.command("vrchat-users <keyword:text>", "检索 VRChat 玩家").option("number", "-n <value:number>", { fallback: 3 }).action(async ({ session, options }, keyword) => {
|
|
190
|
+
const auth = await ctx.cache.get("vrchat_auth", "cookie");
|
|
168
191
|
if (!auth) return "请先登录";
|
|
169
192
|
if (!keyword) return "请输入关键词";
|
|
170
193
|
const [msgId] = await session.send("检索中…");
|
|
@@ -175,6 +198,10 @@ ${new Date(item.updated_at).toLocaleString()}<img src="${item.imageUrl}"></img><
|
|
|
175
198
|
},
|
|
176
199
|
responseType: "json"
|
|
177
200
|
});
|
|
201
|
+
if (resp.length === 0) {
|
|
202
|
+
await session.bot.deleteMessage(session.channelId, msgId);
|
|
203
|
+
return "无检索结果";
|
|
204
|
+
}
|
|
178
205
|
const users = [];
|
|
179
206
|
for (const item of resp) {
|
|
180
207
|
const resp2 = await ctx.http.get(`https://api.vrchat.cloud/api/1/users/${item.id}`, {
|
|
@@ -189,26 +216,42 @@ ${new Date(item.updated_at).toLocaleString()}<img src="${item.imageUrl}"></img><
|
|
|
189
216
|
const messages = [];
|
|
190
217
|
for (const item of users) {
|
|
191
218
|
let avatar = "";
|
|
219
|
+
let currentAvatarImageUrl = item.currentAvatarImageUrl;
|
|
192
220
|
if (item.currentAvatarImageUrl.startsWith("https://api.vrchat.cloud")) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
221
|
+
try {
|
|
222
|
+
const resp2 = await ctx.http.get(item.currentAvatarImageUrl.slice(0, -7), {
|
|
223
|
+
headers: {
|
|
224
|
+
"User-Agent": "VRCX 2026.02.11"
|
|
225
|
+
},
|
|
226
|
+
responseType: "json"
|
|
227
|
+
});
|
|
228
|
+
avatar = resp2.name.split(" - ")[1];
|
|
229
|
+
} catch {
|
|
230
|
+
currentAvatarImageUrl = void 0;
|
|
231
|
+
}
|
|
200
232
|
}
|
|
201
233
|
let location = item.location;
|
|
202
234
|
if (item.location.startsWith("wrld_")) {
|
|
203
|
-
const
|
|
235
|
+
const info = item.location.split(":");
|
|
236
|
+
const resp2 = await ctx.http.get(`https://api.vrchat.cloud/api/1/worlds/${info[0]}`, {
|
|
204
237
|
headers: {
|
|
205
238
|
"User-Agent": "VRCX 2026.02.11",
|
|
206
239
|
"Cookie": auth
|
|
207
240
|
},
|
|
208
241
|
responseType: "json"
|
|
209
242
|
});
|
|
210
|
-
|
|
243
|
+
const ext = info[1].split("~");
|
|
244
|
+
location = `${resp2.name} #${ext[0]} ${countryCodeToEmoji(ext.at(-1).match(/region\(([^)]+)\)/)[1])}`;
|
|
211
245
|
}
|
|
246
|
+
const statusLight = {
|
|
247
|
+
"active": "🟢",
|
|
248
|
+
"join me": "🔵",
|
|
249
|
+
"ask me": "🟠",
|
|
250
|
+
"busy": "🔴",
|
|
251
|
+
"offline": "⚪"
|
|
252
|
+
}[item.status];
|
|
253
|
+
let imgUrl = item.userIcon || currentAvatarImageUrl;
|
|
254
|
+
const img = imgUrl ? `<img src="${imgUrl}"></img>` : "";
|
|
212
255
|
messages.push(`<message>玩家名:
|
|
213
256
|
${item.displayName}
|
|
214
257
|
|
|
@@ -216,7 +259,7 @@ ${item.displayName}
|
|
|
216
259
|
${item.id}
|
|
217
260
|
|
|
218
261
|
状态:
|
|
219
|
-
${item.status} - ${item.statusDescription}
|
|
262
|
+
${statusLight} ${item.status} - ${item.statusDescription}
|
|
220
263
|
|
|
221
264
|
当前位置:
|
|
222
265
|
${location}
|
|
@@ -234,7 +277,7 @@ ${item.bio}
|
|
|
234
277
|
${item.bioLinks.join("\n")}
|
|
235
278
|
|
|
236
279
|
账号创建日期:
|
|
237
|
-
${item.date_joined}
|
|
280
|
+
${item.date_joined}${img}</message>`);
|
|
238
281
|
}
|
|
239
282
|
await session.send(`<message forward>${messages.join("")}</message>`);
|
|
240
283
|
await session.bot.deleteMessage(session.channelId, msgId);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-vrchat",
|
|
3
|
-
"description": "Search VRChat
|
|
4
|
-
"version": "0.0.
|
|
3
|
+
"description": "Search VRChat avatars, worlds, and users",
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -19,14 +19,17 @@
|
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"koishi": "^4.17.7"
|
|
21
21
|
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@koishijs/cache": "^2.1.0"
|
|
24
|
+
},
|
|
22
25
|
"repository": {
|
|
23
26
|
"type": "git",
|
|
24
27
|
"url": "https://github.com/idranme/koishi-plugin-vrchat.git"
|
|
25
28
|
},
|
|
26
29
|
"koishi": {
|
|
27
30
|
"description": {
|
|
28
|
-
"zh": "检索 VRChat
|
|
29
|
-
"en": "Search VRChat
|
|
31
|
+
"zh": "检索 VRChat 模型、世界和玩家",
|
|
32
|
+
"en": "Search VRChat avatars, worlds, and users"
|
|
30
33
|
},
|
|
31
34
|
"browser": true
|
|
32
35
|
}
|
package/readme.md
CHANGED