@hieuzest/koishi-plugin-riichi-city 0.3.1 → 0.4.1
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/api.d.ts +7 -3
- package/lib/api.js +10 -0
- package/lib/index.d.ts +13 -2
- package/lib/index.js +45 -6
- package/lib/lobby.d.ts +2 -2
- package/lib/types.d.ts +42 -3
- package/package.json +1 -1
package/lib/api.d.ts
CHANGED
|
@@ -79,9 +79,11 @@ export declare class RiichiCityApi {
|
|
|
79
79
|
stageType?: number;
|
|
80
80
|
matchType?: number;
|
|
81
81
|
gamePlay?: number;
|
|
82
|
-
round?:
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
round?: 1 | 2;
|
|
83
|
+
playerCount?: 3 | 4;
|
|
84
|
+
friend?: boolean;
|
|
85
|
+
classifyID?: string;
|
|
86
|
+
}): Promise<types.Room[]>;
|
|
85
87
|
listPaipus(options: {
|
|
86
88
|
startTime?: number;
|
|
87
89
|
endTime?: number;
|
|
@@ -92,6 +94,8 @@ export declare class RiichiCityApi {
|
|
|
92
94
|
limit?: number;
|
|
93
95
|
skip?: number;
|
|
94
96
|
}): Promise<types.Paipu[]>;
|
|
97
|
+
getRoomData(roomId: string): Promise<types.RoomData>;
|
|
98
|
+
getGameData(roomId: string, eventStartPos: number): Promise<types.GameData>;
|
|
95
99
|
}
|
|
96
100
|
export declare namespace RiichiCityApi {
|
|
97
101
|
export interface Cookie {
|
package/lib/api.js
CHANGED
|
@@ -270,6 +270,8 @@ var RiichiCityApi = class _RiichiCityApi {
|
|
|
270
270
|
const res = await this.post("/lobbys/getSelfManageInfo", { matchID });
|
|
271
271
|
return res.data;
|
|
272
272
|
}
|
|
273
|
+
// Lobby games: { classifyID }
|
|
274
|
+
// Rank games: { playerCount, round, stageType }
|
|
273
275
|
async listGames(options) {
|
|
274
276
|
const res = await this.post("/record/readOnlineRoom", options);
|
|
275
277
|
return res.data;
|
|
@@ -279,6 +281,14 @@ var RiichiCityApi = class _RiichiCityApi {
|
|
|
279
281
|
const res = await this.post("/record/readPaiPuList", { limit, skip, ...options });
|
|
280
282
|
return res.data;
|
|
281
283
|
}
|
|
284
|
+
async getRoomData(roomId) {
|
|
285
|
+
const res = await this.post("/record/getRoomData", { isObserve: true, keyValue: roomId });
|
|
286
|
+
return res.data;
|
|
287
|
+
}
|
|
288
|
+
async getGameData(roomId, eventStartPos) {
|
|
289
|
+
const res = await this.post("/record/getGameData", { roomId, eventStartPos });
|
|
290
|
+
return res.data;
|
|
291
|
+
}
|
|
282
292
|
};
|
|
283
293
|
((RiichiCityApi2) => {
|
|
284
294
|
function md5(data) {
|
package/lib/index.d.ts
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
import { Context, Schema, Service } from 'koishi';
|
|
1
|
+
import { Context, Dict, Schema, Service } from 'koishi';
|
|
2
2
|
import { RiichiCityApi } from './api';
|
|
3
3
|
import { RiichiCityDHS } from './dhs';
|
|
4
4
|
declare module 'koishi' {
|
|
5
5
|
interface Context {
|
|
6
6
|
'riichi-city': RiichiCity;
|
|
7
7
|
}
|
|
8
|
+
interface Tables {
|
|
9
|
+
'riichi-city.accounts': RiichiCityAccount;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export interface RiichiCityAccount {
|
|
13
|
+
userId: number;
|
|
14
|
+
nickname: string;
|
|
15
|
+
updatedAt?: number;
|
|
8
16
|
}
|
|
9
17
|
export declare class RiichiCity extends Service {
|
|
10
18
|
ctx: Context;
|
|
11
19
|
config: RiichiCity.Config;
|
|
12
20
|
api: RiichiCityApi;
|
|
13
21
|
constructor(ctx: Context, config: RiichiCity.Config);
|
|
22
|
+
getAccountsByNicknames(nicknames: string[], query?: boolean): Promise<Dict<RiichiCityAccount[]>>;
|
|
23
|
+
getAccounts(userIds: number[]): Promise<Dict<RiichiCityAccount | undefined>>;
|
|
24
|
+
setAccounts(accounts: RiichiCityAccount[]): Promise<void>;
|
|
14
25
|
}
|
|
15
26
|
export declare namespace RiichiCity {
|
|
27
|
+
const inject: string[];
|
|
16
28
|
type Config = RiichiCityApi.Config & {
|
|
17
|
-
name?: string;
|
|
18
29
|
dhs: RiichiCityDHS.Config;
|
|
19
30
|
};
|
|
20
31
|
const Config: Schema<Config>;
|
package/lib/index.js
CHANGED
|
@@ -188,7 +188,7 @@ ${config.extraHelp}`.trim();
|
|
|
188
188
|
return "已关闭通知";
|
|
189
189
|
} else {
|
|
190
190
|
c.notifyIdle = 0;
|
|
191
|
-
c.notifyCache =
|
|
191
|
+
c.notifyCache = [];
|
|
192
192
|
c.notify = ctx.setInterval(async () => {
|
|
193
193
|
const send = /* @__PURE__ */ __name(async (roomID, retry = 0) => {
|
|
194
194
|
const paipu = await c.listPaipus().then((l) => l.find((x) => x.roomID === roomID));
|
|
@@ -206,19 +206,19 @@ ${config.extraHelp}`.trim();
|
|
|
206
206
|
}, "send");
|
|
207
207
|
try {
|
|
208
208
|
const games = await c.listGames();
|
|
209
|
-
if (c.notifyCache) {
|
|
209
|
+
if (c.notifyCache?.length) {
|
|
210
210
|
for (const roomID of Object.keys(c.notifyCache)) {
|
|
211
211
|
if (!games.some((g) => g.roomID === roomID)) {
|
|
212
212
|
ctx.setTimeout(() => send(roomID), 1e3 * 5);
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
if (!games?.length && !
|
|
216
|
+
if (!games?.length && !c.notifyCache?.length) c.notifyIdle++;
|
|
217
217
|
if (c.notifyIdle > config.notifyIdle) {
|
|
218
218
|
c.notify?.();
|
|
219
219
|
return "自动关闭通知";
|
|
220
220
|
}
|
|
221
|
-
c.notifyCache =
|
|
221
|
+
c.notifyCache = games.map((g) => g.roomID);
|
|
222
222
|
} catch (e) {
|
|
223
223
|
console.warn(e);
|
|
224
224
|
c.notifyIdle++;
|
|
@@ -394,6 +394,7 @@ var Rcpt = class {
|
|
|
394
394
|
const findFriend = await this.api.findFriend(pattern).catch(import_koishi2.noop);
|
|
395
395
|
const friend = findFriend?.friendList?.find((f) => f.nickname === pattern);
|
|
396
396
|
if (!friend) return session.text(".failed");
|
|
397
|
+
ctx["riichi-city"].setAccounts([{ userId: friend.userID, nickname: friend.nickname }]);
|
|
397
398
|
userId = friend.userID;
|
|
398
399
|
}
|
|
399
400
|
try {
|
|
@@ -429,10 +430,17 @@ ${session.text(".recent-results")} [${ranks.three.lastRankList.reverse().join(""
|
|
|
429
430
|
// src/index.ts
|
|
430
431
|
var RiichiCity = class extends import_koishi3.Service {
|
|
431
432
|
constructor(ctx, config) {
|
|
432
|
-
super(ctx,
|
|
433
|
+
super(ctx, "riichi-city", true);
|
|
433
434
|
this.ctx = ctx;
|
|
434
435
|
this.config = config;
|
|
435
436
|
ctx.i18n.define("zh-CN", require_zh_CN());
|
|
437
|
+
ctx.model.extend("riichi-city.accounts", {
|
|
438
|
+
userId: "unsigned",
|
|
439
|
+
nickname: "string",
|
|
440
|
+
updatedAt: "unsigned"
|
|
441
|
+
}, {
|
|
442
|
+
primary: "userId"
|
|
443
|
+
});
|
|
436
444
|
this.api = new import_api2.RiichiCityApi(ctx, config);
|
|
437
445
|
ctx.on("ready", async () => {
|
|
438
446
|
await this.api.login().catch((e) => ctx.logger.warn(e));
|
|
@@ -444,12 +452,43 @@ var RiichiCity = class extends import_koishi3.Service {
|
|
|
444
452
|
__name(this, "RiichiCity");
|
|
445
453
|
}
|
|
446
454
|
api;
|
|
455
|
+
async getAccountsByNicknames(nicknames, query = true) {
|
|
456
|
+
const curtime = Date.now() / 1e3;
|
|
457
|
+
const list = await this.ctx.database.select("riichi-city.accounts", { nickname: nicknames }).groupBy("nickname", {
|
|
458
|
+
accounts: /* @__PURE__ */ __name((row) => import_koishi3.$.array(import_koishi3.$.object(row)), "accounts")
|
|
459
|
+
}).execute();
|
|
460
|
+
const res = Object.fromEntries(list.map((l) => [l.nickname, l.accounts.sort((a, b) => b.updatedAt - a.updatedAt)]));
|
|
461
|
+
if (!query) return res;
|
|
462
|
+
const upsert = [];
|
|
463
|
+
await Promise.all(nicknames.filter((nickname) => !res[nickname]).map((nickname) => this.api.findFriend(nickname).catch(import_koishi3.noop))).then((friends) => {
|
|
464
|
+
friends.forEach((friend) => {
|
|
465
|
+
console.log(">", friend);
|
|
466
|
+
if (!friend?.friendList?.length) return;
|
|
467
|
+
for (const info of friend.friendList) {
|
|
468
|
+
(res[info.nickname] ??= []).push({ userId: info.userID, nickname: info.nickname, updatedAt: curtime });
|
|
469
|
+
upsert.push({ userId: info.userID, nickname: info.nickname, updatedAt: curtime });
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
if (upsert.length) this.setAccounts(upsert);
|
|
474
|
+
return res;
|
|
475
|
+
}
|
|
476
|
+
async getAccounts(userIds) {
|
|
477
|
+
const res = Object.fromEntries(userIds.map((userId) => [userId, void 0]));
|
|
478
|
+
Object.assign(Object.fromEntries(await this.ctx.database.get("riichi-city.accounts", { userId: userIds }).then((x) => x.map((x2) => [x2.userId, x2]))), res);
|
|
479
|
+
return res;
|
|
480
|
+
}
|
|
481
|
+
async setAccounts(accounts) {
|
|
482
|
+
const curtime = Date.now() / 1e3;
|
|
483
|
+
accounts = accounts.map((x) => ({ updatedAt: curtime, ...x }));
|
|
484
|
+
await this.ctx.database.upsert("riichi-city.accounts", accounts);
|
|
485
|
+
}
|
|
447
486
|
};
|
|
448
487
|
((RiichiCity2) => {
|
|
488
|
+
RiichiCity2.inject = ["database"];
|
|
449
489
|
RiichiCity2.Config = import_koishi3.Schema.intersect([
|
|
450
490
|
import_api2.RiichiCityApi.Config,
|
|
451
491
|
import_koishi3.Schema.object({
|
|
452
|
-
name: import_koishi3.Schema.string(),
|
|
453
492
|
dhs: RiichiCityDHS.Config
|
|
454
493
|
})
|
|
455
494
|
]);
|
package/lib/lobby.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Disposable, SessionError } from 'koishi';
|
|
2
2
|
import { RiichiCityApi } from './api';
|
|
3
3
|
import { LobbyDetails } from './types';
|
|
4
4
|
export declare class DHSError extends SessionError {
|
|
@@ -55,7 +55,7 @@ export declare class RiichiCityLobby {
|
|
|
55
55
|
details?: LobbyDetails;
|
|
56
56
|
notify?: Disposable;
|
|
57
57
|
notifyIdle: number;
|
|
58
|
-
notifyCache?:
|
|
58
|
+
notifyCache?: string[];
|
|
59
59
|
constructor(api: RiichiCityApi, id: number);
|
|
60
60
|
init(): Promise<void>;
|
|
61
61
|
listAllowedPlayers(): Promise<RiichiCityApi.Identity[]>;
|
package/lib/types.d.ts
CHANGED
|
@@ -146,7 +146,7 @@ export interface LobbyUser {
|
|
|
146
146
|
status: number;
|
|
147
147
|
userID: number;
|
|
148
148
|
}
|
|
149
|
-
export interface
|
|
149
|
+
export interface RoomPlayer {
|
|
150
150
|
headID: number;
|
|
151
151
|
headTag: number;
|
|
152
152
|
identity: number;
|
|
@@ -159,13 +159,13 @@ export interface GamePlayer {
|
|
|
159
159
|
stageLevel: number;
|
|
160
160
|
userId: number;
|
|
161
161
|
}
|
|
162
|
-
export interface
|
|
162
|
+
export interface Room {
|
|
163
163
|
isEnd: boolean;
|
|
164
164
|
isPause: boolean;
|
|
165
165
|
matchStage: number;
|
|
166
166
|
nowTime: number;
|
|
167
167
|
playerCount: number;
|
|
168
|
-
players:
|
|
168
|
+
players: RoomPlayer[];
|
|
169
169
|
roomId: string;
|
|
170
170
|
stageNum: number;
|
|
171
171
|
startTime: number;
|
|
@@ -196,4 +196,43 @@ export interface Paipu {
|
|
|
196
196
|
startTime: number;
|
|
197
197
|
players: PaipuPlayer[];
|
|
198
198
|
}
|
|
199
|
+
export interface GameEventRecord {
|
|
200
|
+
data: string;
|
|
201
|
+
eventPos: number;
|
|
202
|
+
eventType: number;
|
|
203
|
+
handId: string;
|
|
204
|
+
startTime: number;
|
|
205
|
+
userId: number;
|
|
206
|
+
}
|
|
207
|
+
export interface GameRecord {
|
|
208
|
+
benChangNum: number;
|
|
209
|
+
changCi: number;
|
|
210
|
+
handCardEncode: string;
|
|
211
|
+
handCardSHA256: string;
|
|
212
|
+
handEventRecord: GameEventRecord[];
|
|
213
|
+
handID: string;
|
|
214
|
+
handPos: number;
|
|
215
|
+
paiShan: string;
|
|
216
|
+
players: PaipuPlayer[];
|
|
217
|
+
quanFeng: number;
|
|
218
|
+
}
|
|
219
|
+
export interface RoomData {
|
|
220
|
+
fangFu: number;
|
|
221
|
+
gamePlay: number;
|
|
222
|
+
handRecord: GameRecord[];
|
|
223
|
+
initPoints: number;
|
|
224
|
+
keyValue: string;
|
|
225
|
+
nowTime: number;
|
|
226
|
+
matchStage: number;
|
|
227
|
+
matchType: number;
|
|
228
|
+
roomId: string;
|
|
229
|
+
playerCount: number;
|
|
230
|
+
round: number;
|
|
231
|
+
stageNum: number;
|
|
232
|
+
stageType: number;
|
|
233
|
+
}
|
|
234
|
+
export interface GameData {
|
|
235
|
+
handEventRecord: GameEventRecord[];
|
|
236
|
+
nowTime: number;
|
|
237
|
+
}
|
|
199
238
|
export declare const stages: string[];
|