koishi-plugin-steam-info-check 1.0.4 → 1.0.6
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/dist/index.js +190 -160
- package/package.json +1 -1
- package/src/index.ts +187 -155
package/dist/index.js
CHANGED
|
@@ -61,179 +61,209 @@ function apply(ctx, config) {
|
|
|
61
61
|
}, {
|
|
62
62
|
primary: 'id',
|
|
63
63
|
});
|
|
64
|
-
// Commands
|
|
65
|
-
ctx.
|
|
66
|
-
|
|
67
|
-
.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
// Commands and scheduler depend on steam/drawer being ready
|
|
65
|
+
ctx.using(['steam', 'drawer'], (ctx) => {
|
|
66
|
+
ctx.command('steam', 'Steam Information');
|
|
67
|
+
ctx.command('steam.bind <steamId:string>', 'Bind Steam ID', { authority: config.commandAuthority.bind })
|
|
68
|
+
.alias('steambind', '绑定steam')
|
|
69
|
+
.action(async ({ session }, steamId) => {
|
|
70
|
+
if (!session)
|
|
71
|
+
return;
|
|
72
|
+
if (!steamId || !/^\d+$/.test(steamId))
|
|
73
|
+
return session.text('.invalid_id');
|
|
74
|
+
const targetId = await ctx.steam.getSteamId(steamId);
|
|
75
|
+
if (!targetId)
|
|
76
|
+
return session.text('.id_not_found');
|
|
77
|
+
await ctx.database.upsert('steam_bind', [
|
|
78
|
+
{
|
|
79
|
+
userId: session.userId,
|
|
80
|
+
channelId: session.channelId,
|
|
81
|
+
steamId: targetId,
|
|
82
|
+
}
|
|
83
|
+
], ['userId', 'channelId']);
|
|
84
|
+
return session.text('.bind_success', [targetId]);
|
|
85
|
+
});
|
|
86
|
+
ctx.command('steam.unbind', 'Unbind Steam ID', { authority: config.commandAuthority.unbind })
|
|
87
|
+
.alias('steamunbind', '解绑steam')
|
|
88
|
+
.action(async ({ session }) => {
|
|
89
|
+
if (!session)
|
|
90
|
+
return;
|
|
91
|
+
const result = await ctx.database.remove('steam_bind', {
|
|
78
92
|
userId: session.userId,
|
|
79
93
|
channelId: session.channelId,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
], ['userId', 'channelId']);
|
|
83
|
-
return session.text('.bind_success', [targetId]);
|
|
84
|
-
});
|
|
85
|
-
ctx.command('steam.unbind', 'Unbind Steam ID', { authority: config.commandAuthority.unbind })
|
|
86
|
-
.alias('steamunbind', '解绑steam')
|
|
87
|
-
.action(async ({ session }) => {
|
|
88
|
-
if (!session)
|
|
89
|
-
return;
|
|
90
|
-
const result = await ctx.database.remove('steam_bind', {
|
|
91
|
-
userId: session.userId,
|
|
92
|
-
channelId: session.channelId,
|
|
94
|
+
});
|
|
95
|
+
return result ? session.text('.unbind_success') : session.text('.not_bound');
|
|
93
96
|
});
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
ctx.command('steam.info [target:text]', 'View Steam Profile', { authority: config.commandAuthority.info })
|
|
98
|
+
.alias('steaminfo', 'steam信息')
|
|
99
|
+
.action(async ({ session }, target) => {
|
|
100
|
+
if (!session)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
let steamId = null;
|
|
104
|
+
if (target) {
|
|
105
|
+
try {
|
|
106
|
+
const [, userId] = session.resolve(target);
|
|
107
|
+
if (userId) {
|
|
108
|
+
const bind = await ctx.database.get('steam_bind', { userId, channelId: session.channelId });
|
|
109
|
+
if (bind.length)
|
|
110
|
+
steamId = bind[0].steamId;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
/* ignore resolve errors */
|
|
115
|
+
}
|
|
116
|
+
if (!steamId && /^\d+$/.test(target)) {
|
|
117
|
+
steamId = await ctx.steam.getSteamId(target);
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
steamId = await ctx.steam.getSteamId(target);
|
|
120
|
+
else {
|
|
121
|
+
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId });
|
|
122
|
+
if (bind.length)
|
|
123
|
+
steamId = bind[0].steamId;
|
|
117
124
|
}
|
|
125
|
+
if (!steamId)
|
|
126
|
+
return session.text('.user_not_found');
|
|
127
|
+
const profile = await ctx.steam.getUserData(steamId);
|
|
128
|
+
const image = await ctx.drawer.drawPlayerStatus(profile, steamId);
|
|
129
|
+
if (typeof image === 'string')
|
|
130
|
+
return image;
|
|
131
|
+
return koishi_1.h.image(image, 'image/png');
|
|
118
132
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
steamId = bind[0].steamId;
|
|
133
|
+
catch (err) {
|
|
134
|
+
exports.logger.error(err);
|
|
135
|
+
return session.text('.error');
|
|
123
136
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
return
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
});
|
|
138
|
+
ctx.command('steam.check', 'Check Friends Status', { authority: config.commandAuthority.check })
|
|
139
|
+
.alias('steamcheck', '查看steam', '查steam')
|
|
140
|
+
.action(async ({ session }) => {
|
|
141
|
+
if (!session)
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
const binds = await ctx.database.get('steam_bind', { channelId: session.channelId });
|
|
145
|
+
if (binds.length === 0)
|
|
146
|
+
return session.text('.no_binds');
|
|
147
|
+
const steamIds = binds.map(b => b.steamId);
|
|
148
|
+
const summaries = await ctx.steam.getPlayerSummaries(steamIds);
|
|
149
|
+
if (summaries.length === 0)
|
|
150
|
+
return session.text('.api_error');
|
|
151
|
+
const channelInfo = await ensureChannelMeta(ctx, session);
|
|
152
|
+
const parentAvatar = channelInfo.avatar
|
|
153
|
+
? Buffer.from(channelInfo.avatar, 'base64')
|
|
154
|
+
: await ctx.drawer.getDefaultAvatar();
|
|
155
|
+
const parentName = channelInfo.name || session.channelId || 'Unknown';
|
|
156
|
+
const image = await ctx.drawer.drawFriendsStatus(parentAvatar, parentName, summaries, binds);
|
|
157
|
+
if (typeof image === 'string')
|
|
158
|
+
return image;
|
|
159
|
+
return koishi_1.h.image(image, 'image/png');
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
exports.logger.error(err);
|
|
163
|
+
return session.text('.error');
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
ctx.command('steam.enable', 'Enable Broadcast', { authority: config.commandAuthority.enable })
|
|
167
|
+
.alias('steamenable', '启用steam')
|
|
168
|
+
.action(async ({ session }) => {
|
|
169
|
+
if (!session)
|
|
170
|
+
return;
|
|
171
|
+
await ctx.database.upsert('steam_channel', [{
|
|
172
|
+
id: session.channelId,
|
|
173
|
+
enable: true,
|
|
174
|
+
platform: session.platform,
|
|
175
|
+
assignee: session.selfId,
|
|
176
|
+
}]);
|
|
177
|
+
return session.text('.enable_success');
|
|
178
|
+
});
|
|
179
|
+
ctx.command('steam.disable', 'Disable Broadcast', { authority: config.commandAuthority.disable })
|
|
180
|
+
.alias('steamdisable', '禁用steam')
|
|
181
|
+
.action(async ({ session }) => {
|
|
182
|
+
if (!session)
|
|
183
|
+
return;
|
|
184
|
+
await ctx.database.upsert('steam_channel', [{
|
|
185
|
+
id: session.channelId,
|
|
186
|
+
enable: false,
|
|
187
|
+
platform: session.platform,
|
|
188
|
+
assignee: session.selfId,
|
|
189
|
+
}]);
|
|
190
|
+
return session.text('.disable_success');
|
|
191
|
+
});
|
|
192
|
+
ctx.command('steam.update [name:string] [avatar:image]', 'Update Group Info', { authority: config.commandAuthority.update })
|
|
193
|
+
.alias('steamupdate', '更新群信息')
|
|
194
|
+
.action(async ({ session }, name, avatar) => {
|
|
195
|
+
if (!session)
|
|
196
|
+
return;
|
|
197
|
+
const img = session.elements && session.elements.find(e => e.type === 'img');
|
|
198
|
+
const imgUrl = img?.attrs?.src;
|
|
199
|
+
let avatarBase64 = null;
|
|
200
|
+
if (imgUrl) {
|
|
201
|
+
const buffer = await ctx.http.get(imgUrl, { responseType: 'arraybuffer' });
|
|
202
|
+
avatarBase64 = Buffer.from(buffer).toString('base64');
|
|
203
|
+
}
|
|
204
|
+
if (!name && !avatarBase64)
|
|
205
|
+
return session.text('.args_missing');
|
|
206
|
+
const update = { id: session.channelId, platform: session.platform, assignee: session.selfId };
|
|
207
|
+
if (name)
|
|
208
|
+
update.name = name;
|
|
209
|
+
if (avatarBase64)
|
|
210
|
+
update.avatar = avatarBase64;
|
|
211
|
+
await ctx.database.upsert('steam_channel', [update]);
|
|
212
|
+
return session.text('.update_success');
|
|
213
|
+
});
|
|
214
|
+
ctx.command('steam.nickname <nickname:string>', 'Set Steam Nickname', { authority: config.commandAuthority.nickname })
|
|
215
|
+
.alias('steamnickname', 'steam昵称')
|
|
216
|
+
.action(async ({ session }, nickname) => {
|
|
217
|
+
if (!session)
|
|
218
|
+
return;
|
|
219
|
+
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId });
|
|
220
|
+
if (!bind.length)
|
|
221
|
+
return session.text('.not_bound');
|
|
222
|
+
await ctx.database.upsert('steam_bind', [{ ...bind[0], nickname }]);
|
|
223
|
+
return session.text('.nickname_set', [nickname]);
|
|
224
|
+
});
|
|
225
|
+
// Scheduler
|
|
226
|
+
let skipFirstBroadcast = config.steamDisableBroadcastOnStartup;
|
|
227
|
+
ctx.setInterval(async () => {
|
|
228
|
+
if (skipFirstBroadcast) {
|
|
229
|
+
await seedStatusCache(ctx);
|
|
230
|
+
skipFirstBroadcast = false;
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
await broadcast(ctx, config);
|
|
234
|
+
}, config.steamRequestInterval * 1000);
|
|
136
235
|
});
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
236
|
+
}
|
|
237
|
+
// Broadcast Logic
|
|
238
|
+
const statusCache = new Map();
|
|
239
|
+
async function ensureChannelMeta(ctx, session) {
|
|
240
|
+
const channelId = session.channelId;
|
|
241
|
+
const existing = await ctx.database.get('steam_channel', { id: channelId });
|
|
242
|
+
const current = existing[0] || { id: channelId, enable: true, platform: session.platform, assignee: session.selfId };
|
|
243
|
+
let name = current.name;
|
|
244
|
+
if (!name && session.event?.channel?.name) {
|
|
245
|
+
name = session.event.channel.name;
|
|
246
|
+
}
|
|
247
|
+
let avatar = current.avatar;
|
|
248
|
+
if (!avatar) {
|
|
142
249
|
try {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const summaries = await ctx.steam.getPlayerSummaries(steamIds);
|
|
148
|
-
if (summaries.length === 0)
|
|
149
|
-
return session.text('.api_error');
|
|
150
|
-
const channelInfo = await ctx.database.get('steam_channel', { id: session.channelId });
|
|
151
|
-
const parentAvatar = channelInfo[0]?.avatar
|
|
152
|
-
? Buffer.from(channelInfo[0].avatar, 'base64')
|
|
153
|
-
: await ctx.drawer.getDefaultAvatar();
|
|
154
|
-
const parentName = channelInfo[0]?.name || session.channelId || 'Unknown';
|
|
155
|
-
const image = await ctx.drawer.drawFriendsStatus(parentAvatar, parentName, summaries, binds);
|
|
156
|
-
if (typeof image === 'string')
|
|
157
|
-
return session.send(image);
|
|
158
|
-
return session.send(koishi_1.h.image(image, 'image/png'));
|
|
159
|
-
}
|
|
160
|
-
catch (err) {
|
|
161
|
-
exports.logger.error(err);
|
|
162
|
-
return session.text('.error');
|
|
250
|
+
// For QQ group avatars
|
|
251
|
+
const url = `http://p.qlogo.cn/gh/${channelId}/${channelId}/0`;
|
|
252
|
+
const buffer = await ctx.http.get(url, { responseType: 'arraybuffer' });
|
|
253
|
+
avatar = Buffer.from(buffer).toString('base64');
|
|
163
254
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
.alias('steamenable', '启用steam')
|
|
167
|
-
.action(async ({ session }) => {
|
|
168
|
-
if (!session)
|
|
169
|
-
return;
|
|
170
|
-
await ctx.database.upsert('steam_channel', [{
|
|
171
|
-
id: session.channelId,
|
|
172
|
-
enable: true,
|
|
173
|
-
platform: session.platform,
|
|
174
|
-
assignee: session.selfId,
|
|
175
|
-
}]);
|
|
176
|
-
return session.text('.enable_success');
|
|
177
|
-
});
|
|
178
|
-
ctx.command('steam.disable', 'Disable Broadcast', { authority: config.commandAuthority.disable })
|
|
179
|
-
.alias('steamdisable', '禁用steam')
|
|
180
|
-
.action(async ({ session }) => {
|
|
181
|
-
if (!session)
|
|
182
|
-
return;
|
|
183
|
-
await ctx.database.upsert('steam_channel', [{
|
|
184
|
-
id: session.channelId,
|
|
185
|
-
enable: false,
|
|
186
|
-
platform: session.platform,
|
|
187
|
-
assignee: session.selfId,
|
|
188
|
-
}]);
|
|
189
|
-
return session.text('.disable_success');
|
|
190
|
-
});
|
|
191
|
-
ctx.command('steam.update [name:string] [avatar:image]', 'Update Group Info', { authority: config.commandAuthority.update })
|
|
192
|
-
.alias('steamupdate', '更新群信息')
|
|
193
|
-
.action(async ({ session }, name, avatar) => {
|
|
194
|
-
if (!session)
|
|
195
|
-
return;
|
|
196
|
-
const img = session.elements && session.elements.find(e => e.type === 'img');
|
|
197
|
-
const imgUrl = img?.attrs?.src;
|
|
198
|
-
let avatarBase64 = null;
|
|
199
|
-
if (imgUrl) {
|
|
200
|
-
const buffer = await ctx.http.get(imgUrl, { responseType: 'arraybuffer' });
|
|
201
|
-
avatarBase64 = Buffer.from(buffer).toString('base64');
|
|
255
|
+
catch {
|
|
256
|
+
// fallback later to default avatar
|
|
202
257
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return session.text('.update_success');
|
|
212
|
-
});
|
|
213
|
-
ctx.command('steam.nickname <nickname:string>', 'Set Steam Nickname', { authority: config.commandAuthority.nickname })
|
|
214
|
-
.alias('steamnickname', 'steam昵称')
|
|
215
|
-
.action(async ({ session }, nickname) => {
|
|
216
|
-
if (!session)
|
|
217
|
-
return;
|
|
218
|
-
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId });
|
|
219
|
-
if (!bind.length)
|
|
220
|
-
return session.text('.not_bound');
|
|
221
|
-
await ctx.database.upsert('steam_bind', [{ ...bind[0], nickname }]);
|
|
222
|
-
return session.text('.nickname_set', [nickname]);
|
|
223
|
-
});
|
|
224
|
-
// Scheduler
|
|
225
|
-
let skipFirstBroadcast = config.steamDisableBroadcastOnStartup;
|
|
226
|
-
ctx.setInterval(async () => {
|
|
227
|
-
if (skipFirstBroadcast) {
|
|
228
|
-
await seedStatusCache(ctx);
|
|
229
|
-
skipFirstBroadcast = false;
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
await broadcast(ctx, config);
|
|
233
|
-
}, config.steamRequestInterval * 1000);
|
|
258
|
+
}
|
|
259
|
+
const update = { id: channelId, platform: session.platform, assignee: session.selfId };
|
|
260
|
+
if (name)
|
|
261
|
+
update.name = name;
|
|
262
|
+
if (avatar)
|
|
263
|
+
update.avatar = avatar;
|
|
264
|
+
await ctx.database.upsert('steam_channel', [update]);
|
|
265
|
+
return { ...current, ...update };
|
|
234
266
|
}
|
|
235
|
-
// Broadcast Logic
|
|
236
|
-
const statusCache = new Map();
|
|
237
267
|
async function seedStatusCache(ctx) {
|
|
238
268
|
const binds = await ctx.database.get('steam_bind', {});
|
|
239
269
|
if (!binds.length)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -93,180 +93,212 @@ export function apply(ctx: Context, config: Config) {
|
|
|
93
93
|
primary: 'id',
|
|
94
94
|
})
|
|
95
95
|
|
|
96
|
-
// Commands
|
|
97
|
-
ctx.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
// Commands and scheduler depend on steam/drawer being ready
|
|
97
|
+
ctx.using(['steam', 'drawer'], (ctx) => {
|
|
98
|
+
ctx.command('steam', 'Steam Information')
|
|
99
|
+
|
|
100
|
+
ctx.command('steam.bind <steamId:string>', 'Bind Steam ID', { authority: config.commandAuthority.bind })
|
|
101
|
+
.alias('steambind', '绑定steam')
|
|
102
|
+
.action(async ({ session }, steamId) => {
|
|
103
|
+
if (!session) return
|
|
104
|
+
if (!steamId || !/^\d+$/.test(steamId)) return session.text('.invalid_id')
|
|
105
|
+
|
|
106
|
+
const targetId = await ctx.steam.getSteamId(steamId)
|
|
107
|
+
if (!targetId) return session.text('.id_not_found')
|
|
108
|
+
|
|
109
|
+
await ctx.database.upsert('steam_bind', [
|
|
110
|
+
{
|
|
111
|
+
userId: session.userId,
|
|
112
|
+
channelId: session.channelId,
|
|
113
|
+
steamId: targetId,
|
|
114
|
+
}
|
|
115
|
+
], ['userId', 'channelId'])
|
|
116
|
+
|
|
117
|
+
return session.text('.bind_success', [targetId])
|
|
118
|
+
})
|
|
107
119
|
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
ctx.command('steam.unbind', 'Unbind Steam ID', { authority: config.commandAuthority.unbind })
|
|
121
|
+
.alias('steamunbind', '解绑steam')
|
|
122
|
+
.action(async ({ session }) => {
|
|
123
|
+
if (!session) return
|
|
124
|
+
const result = await ctx.database.remove('steam_bind', {
|
|
110
125
|
userId: session.userId,
|
|
111
126
|
channelId: session.channelId,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
], ['userId', 'channelId'])
|
|
115
|
-
|
|
116
|
-
return session.text('.bind_success', [targetId])
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
ctx.command('steam.unbind', 'Unbind Steam ID', { authority: config.commandAuthority.unbind })
|
|
120
|
-
.alias('steamunbind', '解绑steam')
|
|
121
|
-
.action(async ({ session }) => {
|
|
122
|
-
if (!session) return
|
|
123
|
-
const result = await ctx.database.remove('steam_bind', {
|
|
124
|
-
userId: session.userId,
|
|
125
|
-
channelId: session.channelId,
|
|
127
|
+
})
|
|
128
|
+
return result ? session.text('.unbind_success') : session.text('.not_bound')
|
|
126
129
|
})
|
|
127
|
-
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
|
|
131
|
+
ctx.command('steam.info [target:text]', 'View Steam Profile', { authority: config.commandAuthority.info })
|
|
132
|
+
.alias('steaminfo', 'steam信息')
|
|
133
|
+
.action(async ({ session }, target) => {
|
|
134
|
+
if (!session) return
|
|
135
|
+
try {
|
|
136
|
+
let steamId: string | null = null
|
|
137
|
+
if (target) {
|
|
138
|
+
try {
|
|
139
|
+
const [, userId] = session.resolve(target)
|
|
140
|
+
if (userId) {
|
|
141
|
+
const bind = await ctx.database.get('steam_bind', { userId, channelId: session.channelId })
|
|
142
|
+
if (bind.length) steamId = bind[0].steamId
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
/* ignore resolve errors */
|
|
142
146
|
}
|
|
143
|
-
} catch {
|
|
144
|
-
/* ignore resolve errors */
|
|
145
|
-
}
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
if (!steamId && /^\d+$/.test(target)) {
|
|
149
|
+
steamId = await ctx.steam.getSteamId(target)
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId })
|
|
153
|
+
if (bind.length) steamId = bind[0].steamId
|
|
149
154
|
}
|
|
150
|
-
} else {
|
|
151
|
-
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId })
|
|
152
|
-
if (bind.length) steamId = bind[0].steamId
|
|
153
|
-
}
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
if (!steamId) return session.text('.user_not_found')
|
|
156
157
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (!session) return
|
|
171
|
-
try {
|
|
172
|
-
const binds = await ctx.database.get('steam_bind', { channelId: session.channelId })
|
|
173
|
-
if (binds.length === 0) return session.text('.no_binds')
|
|
174
|
-
|
|
175
|
-
const steamIds = binds.map(b => b.steamId)
|
|
176
|
-
const summaries = await ctx.steam.getPlayerSummaries(steamIds)
|
|
177
|
-
|
|
178
|
-
if (summaries.length === 0) return session.text('.api_error')
|
|
179
|
-
|
|
180
|
-
const channelInfo = await ctx.database.get('steam_channel', { id: session.channelId })
|
|
181
|
-
const parentAvatar = channelInfo[0]?.avatar
|
|
182
|
-
? Buffer.from(channelInfo[0].avatar, 'base64')
|
|
183
|
-
: await ctx.drawer.getDefaultAvatar()
|
|
184
|
-
const parentName = channelInfo[0]?.name || session.channelId || 'Unknown'
|
|
185
|
-
|
|
186
|
-
const image = await ctx.drawer.drawFriendsStatus(parentAvatar, parentName, summaries, binds)
|
|
187
|
-
if (typeof image === 'string') return session.send(image)
|
|
188
|
-
return session.send(h.image(image, 'image/png'))
|
|
189
|
-
} catch (err) {
|
|
190
|
-
logger.error(err)
|
|
191
|
-
return session.text('.error')
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
ctx.command('steam.enable', 'Enable Broadcast', { authority: config.commandAuthority.enable })
|
|
196
|
-
.alias('steamenable', '启用steam')
|
|
197
|
-
.action(async ({ session }) => {
|
|
198
|
-
if (!session) return
|
|
199
|
-
await ctx.database.upsert('steam_channel', [{
|
|
200
|
-
id: session.channelId,
|
|
201
|
-
enable: true,
|
|
202
|
-
platform: session.platform,
|
|
203
|
-
assignee: session.selfId,
|
|
204
|
-
}])
|
|
205
|
-
return session.text('.enable_success')
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
ctx.command('steam.disable', 'Disable Broadcast', { authority: config.commandAuthority.disable })
|
|
209
|
-
.alias('steamdisable', '禁用steam')
|
|
210
|
-
.action(async ({ session }) => {
|
|
211
|
-
if (!session) return
|
|
212
|
-
await ctx.database.upsert('steam_channel', [{
|
|
213
|
-
id: session.channelId,
|
|
214
|
-
enable: false,
|
|
215
|
-
platform: session.platform,
|
|
216
|
-
assignee: session.selfId,
|
|
217
|
-
}])
|
|
218
|
-
return session.text('.disable_success')
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
ctx.command('steam.update [name:string] [avatar:image]', 'Update Group Info', { authority: config.commandAuthority.update })
|
|
222
|
-
.alias('steamupdate', '更新群信息')
|
|
223
|
-
.action(async ({ session }, name, avatar) => {
|
|
158
|
+
const profile = await ctx.steam.getUserData(steamId)
|
|
159
|
+
const image = await ctx.drawer.drawPlayerStatus(profile, steamId)
|
|
160
|
+
if (typeof image === 'string') return image
|
|
161
|
+
return h.image(image, 'image/png')
|
|
162
|
+
} catch (err) {
|
|
163
|
+
logger.error(err)
|
|
164
|
+
return session.text('.error')
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
ctx.command('steam.check', 'Check Friends Status', { authority: config.commandAuthority.check })
|
|
169
|
+
.alias('steamcheck', '查看steam', '查steam')
|
|
170
|
+
.action(async ({ session }) => {
|
|
224
171
|
if (!session) return
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
172
|
+
try {
|
|
173
|
+
const binds = await ctx.database.get('steam_bind', { channelId: session.channelId })
|
|
174
|
+
if (binds.length === 0) return session.text('.no_binds')
|
|
175
|
+
|
|
176
|
+
const steamIds = binds.map(b => b.steamId)
|
|
177
|
+
const summaries = await ctx.steam.getPlayerSummaries(steamIds)
|
|
178
|
+
|
|
179
|
+
if (summaries.length === 0) return session.text('.api_error')
|
|
180
|
+
|
|
181
|
+
const channelInfo = await ensureChannelMeta(ctx, session)
|
|
182
|
+
const parentAvatar = channelInfo.avatar
|
|
183
|
+
? Buffer.from(channelInfo.avatar, 'base64')
|
|
184
|
+
: await ctx.drawer.getDefaultAvatar()
|
|
185
|
+
const parentName = channelInfo.name || session.channelId || 'Unknown'
|
|
186
|
+
|
|
187
|
+
const image = await ctx.drawer.drawFriendsStatus(parentAvatar, parentName, summaries, binds)
|
|
188
|
+
if (typeof image === 'string') return image
|
|
189
|
+
return h.image(image, 'image/png')
|
|
190
|
+
} catch (err) {
|
|
191
|
+
logger.error(err)
|
|
192
|
+
return session.text('.error')
|
|
232
193
|
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
ctx.command('steam.enable', 'Enable Broadcast', { authority: config.commandAuthority.enable })
|
|
197
|
+
.alias('steamenable', '启用steam')
|
|
198
|
+
.action(async ({ session }) => {
|
|
199
|
+
if (!session) return
|
|
200
|
+
await ctx.database.upsert('steam_channel', [{
|
|
201
|
+
id: session.channelId,
|
|
202
|
+
enable: true,
|
|
203
|
+
platform: session.platform,
|
|
204
|
+
assignee: session.selfId,
|
|
205
|
+
}])
|
|
206
|
+
return session.text('.enable_success')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
ctx.command('steam.disable', 'Disable Broadcast', { authority: config.commandAuthority.disable })
|
|
210
|
+
.alias('steamdisable', '禁用steam')
|
|
211
|
+
.action(async ({ session }) => {
|
|
212
|
+
if (!session) return
|
|
213
|
+
await ctx.database.upsert('steam_channel', [{
|
|
214
|
+
id: session.channelId,
|
|
215
|
+
enable: false,
|
|
216
|
+
platform: session.platform,
|
|
217
|
+
assignee: session.selfId,
|
|
218
|
+
}])
|
|
219
|
+
return session.text('.disable_success')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
ctx.command('steam.update [name:string] [avatar:image]', 'Update Group Info', { authority: config.commandAuthority.update })
|
|
223
|
+
.alias('steamupdate', '更新群信息')
|
|
224
|
+
.action(async ({ session }, name, avatar) => {
|
|
225
|
+
if (!session) return
|
|
226
|
+
const img = session.elements && session.elements.find(e => e.type === 'img')
|
|
227
|
+
const imgUrl = img?.attrs?.src
|
|
228
|
+
|
|
229
|
+
let avatarBase64 = null
|
|
230
|
+
if (imgUrl) {
|
|
231
|
+
const buffer = await ctx.http.get(imgUrl, { responseType: 'arraybuffer' })
|
|
232
|
+
avatarBase64 = Buffer.from(buffer).toString('base64')
|
|
233
|
+
}
|
|
233
234
|
|
|
234
|
-
|
|
235
|
+
if (!name && !avatarBase64) return session.text('.args_missing')
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
const update: any = { id: session.channelId, platform: session.platform, assignee: session.selfId }
|
|
238
|
+
if (name) update.name = name
|
|
239
|
+
if (avatarBase64) update.avatar = avatarBase64
|
|
240
|
+
|
|
241
|
+
await ctx.database.upsert('steam_channel', [update])
|
|
242
|
+
return session.text('.update_success')
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
ctx.command('steam.nickname <nickname:string>', 'Set Steam Nickname', { authority: config.commandAuthority.nickname })
|
|
246
|
+
.alias('steamnickname', 'steam昵称')
|
|
247
|
+
.action(async ({ session }, nickname) => {
|
|
248
|
+
if (!session) return
|
|
249
|
+
const bind = await ctx.database.get('steam_bind', { userId: session.userId, channelId: session.channelId })
|
|
250
|
+
if (!bind.length) return session.text('.not_bound')
|
|
239
251
|
|
|
240
|
-
await ctx.database.upsert('
|
|
241
|
-
return session.text('.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
.
|
|
246
|
-
.
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
// Scheduler
|
|
256
|
-
let skipFirstBroadcast = config.steamDisableBroadcastOnStartup
|
|
257
|
-
ctx.setInterval(async () => {
|
|
258
|
-
if (skipFirstBroadcast) {
|
|
259
|
-
await seedStatusCache(ctx)
|
|
260
|
-
skipFirstBroadcast = false
|
|
261
|
-
return
|
|
262
|
-
}
|
|
263
|
-
await broadcast(ctx, config)
|
|
264
|
-
}, config.steamRequestInterval * 1000)
|
|
252
|
+
await ctx.database.upsert('steam_bind', [{ ...bind[0], nickname }])
|
|
253
|
+
return session.text('.nickname_set', [nickname])
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// Scheduler
|
|
257
|
+
let skipFirstBroadcast = config.steamDisableBroadcastOnStartup
|
|
258
|
+
ctx.setInterval(async () => {
|
|
259
|
+
if (skipFirstBroadcast) {
|
|
260
|
+
await seedStatusCache(ctx)
|
|
261
|
+
skipFirstBroadcast = false
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
await broadcast(ctx, config)
|
|
265
|
+
}, config.steamRequestInterval * 1000)
|
|
266
|
+
})
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
// Broadcast Logic
|
|
268
270
|
const statusCache = new Map<string, any>()
|
|
269
271
|
|
|
272
|
+
async function ensureChannelMeta(ctx: Context, session: Session) {
|
|
273
|
+
const channelId = session.channelId
|
|
274
|
+
const existing = await ctx.database.get('steam_channel', { id: channelId })
|
|
275
|
+
const current = existing[0] || { id: channelId, enable: true, platform: session.platform, assignee: session.selfId }
|
|
276
|
+
|
|
277
|
+
let name = current.name
|
|
278
|
+
if (!name && session.event?.channel?.name) {
|
|
279
|
+
name = session.event.channel.name
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let avatar = current.avatar
|
|
283
|
+
if (!avatar) {
|
|
284
|
+
try {
|
|
285
|
+
// For QQ group avatars
|
|
286
|
+
const url = `http://p.qlogo.cn/gh/${channelId}/${channelId}/0`
|
|
287
|
+
const buffer = await ctx.http.get(url, { responseType: 'arraybuffer' })
|
|
288
|
+
avatar = Buffer.from(buffer).toString('base64')
|
|
289
|
+
} catch {
|
|
290
|
+
// fallback later to default avatar
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const update: any = { id: channelId, platform: session.platform, assignee: session.selfId }
|
|
295
|
+
if (name) update.name = name
|
|
296
|
+
if (avatar) update.avatar = avatar
|
|
297
|
+
await ctx.database.upsert('steam_channel', [update])
|
|
298
|
+
|
|
299
|
+
return { ...current, ...update }
|
|
300
|
+
}
|
|
301
|
+
|
|
270
302
|
async function seedStatusCache(ctx: Context) {
|
|
271
303
|
const binds = await ctx.database.get('steam_bind', {})
|
|
272
304
|
if (!binds.length) return
|