gcm-database-local 0.0.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/dist/chunithm/chart.d.ts +16 -0
- package/dist/chunithm/chart.js +3 -0
- package/dist/chunithm/chart.js.map +1 -0
- package/dist/chunithm/database.d.ts +36 -0
- package/dist/chunithm/database.js +115 -0
- package/dist/chunithm/database.js.map +1 -0
- package/dist/chunithm/presence.d.ts +36 -0
- package/dist/chunithm/presence.js +3 -0
- package/dist/chunithm/presence.js.map +1 -0
- package/dist/chunithm.d.ts +3 -0
- package/dist/chunithm.js +6 -0
- package/dist/chunithm.js.map +1 -0
- package/dist/lib/cache.d.ts +24 -0
- package/dist/lib/cache.js +80 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/getInternalLevelFromPresences.d.ts +4 -0
- package/dist/lib/getInternalLevelFromPresences.js +21 -0
- package/dist/lib/getInternalLevelFromPresences.js.map +1 -0
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.js +16 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/maimai/chart.d.ts +19 -0
- package/dist/maimai/chart.js +3 -0
- package/dist/maimai/chart.js.map +1 -0
- package/dist/maimai/database.d.ts +37 -0
- package/dist/maimai/database.js +118 -0
- package/dist/maimai/database.js.map +1 -0
- package/dist/maimai/presence.d.ts +52 -0
- package/dist/maimai/presence.js +3 -0
- package/dist/maimai/presence.js.map +1 -0
- package/dist/maimai.d.ts +3 -0
- package/dist/maimai.js +6 -0
- package/dist/maimai.js.map +1 -0
- package/dist/ongeki/chart.d.ts +16 -0
- package/dist/ongeki/chart.js +3 -0
- package/dist/ongeki/chart.js.map +1 -0
- package/dist/ongeki/database.d.ts +44 -0
- package/dist/ongeki/database.js +140 -0
- package/dist/ongeki/database.js.map +1 -0
- package/dist/ongeki/presence.d.ts +36 -0
- package/dist/ongeki/presence.js +3 -0
- package/dist/ongeki/presence.js.map +1 -0
- package/dist/ongeki.d.ts +3 -0
- package/dist/ongeki.js +6 -0
- package/dist/ongeki.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Chart as BaseChart } from "gcm-database/chunithm";
|
|
2
|
+
import type { Presences } from "./presence";
|
|
3
|
+
export interface Chart extends BaseChart {
|
|
4
|
+
optionalData: Partial<{
|
|
5
|
+
bpm: number[];
|
|
6
|
+
notes: {
|
|
7
|
+
tap: number;
|
|
8
|
+
hold: number;
|
|
9
|
+
slide: number;
|
|
10
|
+
air: number;
|
|
11
|
+
flick?: number;
|
|
12
|
+
};
|
|
13
|
+
designer: string;
|
|
14
|
+
presences: Presences[];
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/chunithm/chart.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Database as BaseDatabase, Difficulty } from "gcm-database/chunithm";
|
|
2
|
+
import type { Chart } from "./chart";
|
|
3
|
+
export declare class Database implements BaseDatabase<Chart> {
|
|
4
|
+
private _localDatabasePath;
|
|
5
|
+
constructor(_localDatabasePath: string);
|
|
6
|
+
setLocalDatabasePath(path: string): boolean;
|
|
7
|
+
hasLocalDatabase(): boolean;
|
|
8
|
+
private cache;
|
|
9
|
+
getJacket(identifier: string, variant?: "DX" | "EX" | "CN"): Promise<{
|
|
10
|
+
data: Buffer<ArrayBuffer> | Buffer<any>;
|
|
11
|
+
err?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
err: string;
|
|
14
|
+
data?: undefined;
|
|
15
|
+
}>;
|
|
16
|
+
getChart(identifier: string, difficulty: Difficulty): Promise<{
|
|
17
|
+
data: any;
|
|
18
|
+
err?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
err: string;
|
|
21
|
+
data?: undefined;
|
|
22
|
+
}>;
|
|
23
|
+
private getAllCharts;
|
|
24
|
+
searchChart(payload: {
|
|
25
|
+
title: string;
|
|
26
|
+
level: number;
|
|
27
|
+
difficulty: Difficulty;
|
|
28
|
+
}, options?: Partial<{
|
|
29
|
+
maxResultCount: number;
|
|
30
|
+
}>): Promise<{
|
|
31
|
+
data: {
|
|
32
|
+
chart: Chart;
|
|
33
|
+
weight: number;
|
|
34
|
+
}[];
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Database = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const cache_1 = require("../lib/cache");
|
|
10
|
+
const getInternalLevelFromPresences_1 = require("../lib/getInternalLevelFromPresences");
|
|
11
|
+
class Database {
|
|
12
|
+
_localDatabasePath;
|
|
13
|
+
constructor(_localDatabasePath) {
|
|
14
|
+
this._localDatabasePath = _localDatabasePath;
|
|
15
|
+
}
|
|
16
|
+
setLocalDatabasePath(path) {
|
|
17
|
+
if (node_fs_1.default.existsSync(path)) {
|
|
18
|
+
this._localDatabasePath = path;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
hasLocalDatabase() {
|
|
26
|
+
return node_fs_1.default.existsSync(this._localDatabasePath);
|
|
27
|
+
}
|
|
28
|
+
cache = new cache_1.Cache("gcm-database-local/chunithm");
|
|
29
|
+
async getJacket(identifier, variant) {
|
|
30
|
+
const cacheKey = `jacket-${identifier}${variant ? `-${variant}` : ""}`;
|
|
31
|
+
const cached = await this.cache.get(cacheKey);
|
|
32
|
+
if (cached instanceof Buffer) {
|
|
33
|
+
return { data: cached };
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const songId = identifier.slice(-4);
|
|
37
|
+
if (variant) {
|
|
38
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "chunithm", "jackets", `${songId.padStart(6, "0")}-${variant}.png`);
|
|
39
|
+
if (node_fs_1.default.existsSync(localFilePath)) {
|
|
40
|
+
return { data: node_fs_1.default.readFileSync(localFilePath) };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Falls back to normal jacket if a variant cannot be found.
|
|
44
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "chunithm", "jackets", `${songId.padStart(6, "0")}.png`);
|
|
45
|
+
const jacket = node_fs_1.default.existsSync(localFilePath) && node_fs_1.default.readFileSync(localFilePath);
|
|
46
|
+
if (jacket) {
|
|
47
|
+
this.cache.put(cacheKey, jacket, 5 * 1000); // 5 seconds.
|
|
48
|
+
return { data: jacket };
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return { err: `Cannot find the jacket of ${identifier}.` };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async getChart(identifier, difficulty) {
|
|
56
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "chunithm", "charts", `${identifier.padStart(6, "0")}`);
|
|
57
|
+
if (node_fs_1.default.existsSync(node_path_1.default.join(localFilePath, difficulty))) {
|
|
58
|
+
try {
|
|
59
|
+
return {
|
|
60
|
+
data: JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(localFilePath, difficulty), "utf-8")),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {
|
|
65
|
+
err: `Failed to parse ${identifier} ${difficulty}.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
err: `Cannot find a chart with identifier ${identifier}.`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async getAllCharts() {
|
|
74
|
+
const cached = await this.cache.get("all-charts");
|
|
75
|
+
if (cached)
|
|
76
|
+
return cached;
|
|
77
|
+
const localFolderPath = node_path_1.default.join(this._localDatabasePath, "assets", "chunithm", "charts");
|
|
78
|
+
const chartFolders = node_fs_1.default.readdirSync(localFolderPath);
|
|
79
|
+
const songs = [];
|
|
80
|
+
for (const folder of chartFolders) {
|
|
81
|
+
const charts = node_fs_1.default.readdirSync(node_path_1.default.join(localFolderPath, folder));
|
|
82
|
+
for (const chart of charts) {
|
|
83
|
+
try {
|
|
84
|
+
songs.push(require(node_path_1.default.join(localFolderPath, folder, chart)));
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
await this.cache.put("all-charts", songs, 15 * 60 * 1000); // 15 minutes.
|
|
90
|
+
return songs;
|
|
91
|
+
}
|
|
92
|
+
async searchChart(payload, options) {
|
|
93
|
+
const allSongs = await this.getAllCharts();
|
|
94
|
+
const sortedCandidates = allSongs
|
|
95
|
+
.filter((v) => v.title === payload.title &&
|
|
96
|
+
v.difficulty === payload.difficulty)
|
|
97
|
+
.map((v) => {
|
|
98
|
+
if (v.optionalData.presences) {
|
|
99
|
+
const internalLevel = (0, getInternalLevelFromPresences_1.getInternalLevelFromPresences)(v.optionalData.presences);
|
|
100
|
+
if (internalLevel) {
|
|
101
|
+
return {
|
|
102
|
+
chart: v,
|
|
103
|
+
weight: Math.abs(internalLevel - payload.level),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { chart: v };
|
|
108
|
+
})
|
|
109
|
+
.filter((v) => !!v.weight)
|
|
110
|
+
.sort((a, b) => a.weight - b.weight);
|
|
111
|
+
return { data: sortedCandidates.slice(options?.maxResultCount || 20) };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.Database = Database;
|
|
115
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/chunithm/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface BasePresence {
|
|
2
|
+
type: string;
|
|
3
|
+
data?: unknown;
|
|
4
|
+
version: Version;
|
|
5
|
+
}
|
|
6
|
+
export interface Existence extends BasePresence {
|
|
7
|
+
type: "existence";
|
|
8
|
+
data: {
|
|
9
|
+
level: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface Absence extends BasePresence {
|
|
13
|
+
type: "absence";
|
|
14
|
+
}
|
|
15
|
+
export interface Removal extends BasePresence {
|
|
16
|
+
type: "removal";
|
|
17
|
+
}
|
|
18
|
+
export type Presences = Existence | Absence | Removal;
|
|
19
|
+
export interface Version {
|
|
20
|
+
/**
|
|
21
|
+
* Full name of the version.
|
|
22
|
+
* @example "CHUNITHM X-VERSE-X"
|
|
23
|
+
*/
|
|
24
|
+
name: string;
|
|
25
|
+
/**
|
|
26
|
+
* Version number as it is used internally.
|
|
27
|
+
* Formatted as `{major}.{minor}.{patch}`.
|
|
28
|
+
*/
|
|
29
|
+
gameVersion: {
|
|
30
|
+
major: number;
|
|
31
|
+
minor: number;
|
|
32
|
+
release?: number;
|
|
33
|
+
};
|
|
34
|
+
region: "JPN" | "INT" | "CHN";
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/chunithm/presence.ts"],"names":[],"mappings":""}
|
package/dist/chunithm.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Database = void 0;
|
|
4
|
+
var database_1 = require("./chunithm/database");
|
|
5
|
+
Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return database_1.Database; } });
|
|
6
|
+
//# sourceMappingURL=chunithm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunithm.js","sourceRoot":"","sources":["../src/chunithm.ts"],"names":[],"mappings":";;;AACA,+CAA8C;AAArC,oGAAA,QAAQ,OAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class Cache<T> {
|
|
2
|
+
private namespace;
|
|
3
|
+
private logger;
|
|
4
|
+
private memCache;
|
|
5
|
+
private redisClient;
|
|
6
|
+
private isRedisAvailable;
|
|
7
|
+
constructor(namespace: string);
|
|
8
|
+
private getKey;
|
|
9
|
+
/**
|
|
10
|
+
* Get a value from cache.
|
|
11
|
+
*
|
|
12
|
+
* @param key Cache key.
|
|
13
|
+
* @returns Cache value.
|
|
14
|
+
*/
|
|
15
|
+
get(key: string): Promise<any>;
|
|
16
|
+
/**
|
|
17
|
+
* Put a value into cache.
|
|
18
|
+
*
|
|
19
|
+
* @param key Cache key.
|
|
20
|
+
* @param value Cache value.
|
|
21
|
+
* @param ttl Cache TTL in milliseconds.
|
|
22
|
+
*/
|
|
23
|
+
put(key: string, value: T, ttl: number): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Cache = void 0;
|
|
4
|
+
const memory_cache_1 = require("memory-cache");
|
|
5
|
+
const redis_1 = require("redis");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
class Cache {
|
|
8
|
+
namespace;
|
|
9
|
+
logger;
|
|
10
|
+
memCache;
|
|
11
|
+
redisClient;
|
|
12
|
+
isRedisAvailable = true;
|
|
13
|
+
constructor(namespace) {
|
|
14
|
+
this.namespace = namespace;
|
|
15
|
+
this.logger = logger_1.logger.child().withGroup(`${this.namespace}:cache`);
|
|
16
|
+
this.memCache = new memory_cache_1.Cache();
|
|
17
|
+
this.redisClient = (0, redis_1.createClient)();
|
|
18
|
+
this.redisClient.on("error", async () => {
|
|
19
|
+
this.logger.error("Redis connection error, using memory-cache");
|
|
20
|
+
this.isRedisAvailable = false;
|
|
21
|
+
this.redisClient.destroy();
|
|
22
|
+
});
|
|
23
|
+
this.redisClient.connect();
|
|
24
|
+
}
|
|
25
|
+
getKey(key) {
|
|
26
|
+
return `${this.namespace}:${key}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get a value from cache.
|
|
30
|
+
*
|
|
31
|
+
* @param key Cache key.
|
|
32
|
+
* @returns Cache value.
|
|
33
|
+
*/
|
|
34
|
+
async get(key) {
|
|
35
|
+
if (this.isRedisAvailable) {
|
|
36
|
+
const redisValue = await this.redisClient.get(this.getKey(key));
|
|
37
|
+
if (redisValue) {
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(redisValue);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return Buffer.from(redisValue, "base64");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
return this.memCache.get(this.getKey(key));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Put a value into cache.
|
|
51
|
+
*
|
|
52
|
+
* @param key Cache key.
|
|
53
|
+
* @param value Cache value.
|
|
54
|
+
* @param ttl Cache TTL in milliseconds.
|
|
55
|
+
*/
|
|
56
|
+
async put(key, value, ttl) {
|
|
57
|
+
if (this.isRedisAvailable) {
|
|
58
|
+
if (Buffer.isBuffer(value)) {
|
|
59
|
+
await this.redisClient.set(this.getKey(key), value.toString("base64"), {
|
|
60
|
+
expiration: {
|
|
61
|
+
type: "EX",
|
|
62
|
+
value: Math.trunc(ttl / 1000),
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
await this.redisClient.set(this.getKey(key), JSON.stringify(value), {
|
|
68
|
+
expiration: {
|
|
69
|
+
type: "EX",
|
|
70
|
+
value: Math.trunc(ttl / 1000),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
this.memCache.put(this.getKey(key), value, ttl);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.Cache = Cache;
|
|
80
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":";;;AAAA,+CAAiD;AACjD,iCAAqC;AACrC,qCAAkC;AAElC,MAAa,KAAK;IAOM;IANZ,MAAM,CAAC;IAEP,QAAQ,CAAC;IACT,WAAW,CAAC;IAEZ,gBAAgB,GAAG,IAAI,CAAC;IAChC,YAAoB,SAAiB;QAAjB,cAAS,GAAT,SAAS,CAAQ;QACjC,IAAI,CAAC,MAAM,GAAG,eAAM,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAQ,EAAa,CAAC;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAA,oBAAY,GAAE,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;IAC/B,CAAC;IACO,MAAM,CAAC,GAAW;QACtB,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;IACtC,CAAC;IACD;;;;;OAKG;IACI,KAAK,CAAC,GAAG,CAAC,GAAW;QACxB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,IAAI,UAAU,EAAE,CAAC;gBACb,IAAI,CAAC;oBACD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAClC,CAAC;gBAAC,MAAM,CAAC;oBACL,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAC7C,CAAC;YACL,CAAC;QACL,CAAC;;YAAM,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;IACD;;;;;;OAMG;IACI,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,GAAW;QAC/C,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAChB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EACxB;oBACI,UAAU,EAAE;wBACR,IAAI,EAAE,IAAI;wBACV,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;qBAChC;iBACJ,CACJ,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAChB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EACrB;oBACI,UAAU,EAAE;wBACR,IAAI,EAAE,IAAI;wBACV,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;qBAChC;iBACJ,CACJ,CAAC;YACN,CAAC;QACL,CAAC;;YAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;CACJ;AAzED,sBAyEC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Presences as ChunithmPresences } from "../chunithm/presence";
|
|
2
|
+
import type { Presences as MaimaiPresences } from "../maimai/presence";
|
|
3
|
+
import type { Presences as OngekiPresences } from "../ongeki/presence";
|
|
4
|
+
export declare function getInternalLevelFromPresences(presences: (MaimaiPresences | ChunithmPresences | OngekiPresences)[]): number | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInternalLevelFromPresences = getInternalLevelFromPresences;
|
|
4
|
+
function getInternalLevelFromPresences(presences) {
|
|
5
|
+
let latestPresence;
|
|
6
|
+
for (const presence of presences) {
|
|
7
|
+
if (!latestPresence ||
|
|
8
|
+
(presence.type === "existence" &&
|
|
9
|
+
presence.version.gameVersion.major >=
|
|
10
|
+
latestPresence.version.gameVersion.major &&
|
|
11
|
+
presence.version.gameVersion.minor >=
|
|
12
|
+
latestPresence.version.gameVersion.minor)) {
|
|
13
|
+
latestPresence = presence;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (latestPresence) {
|
|
17
|
+
return latestPresence.data.level;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=getInternalLevelFromPresences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getInternalLevelFromPresences.js","sourceRoot":"","sources":["../../src/lib/getInternalLevelFromPresences.ts"],"names":[],"mappings":";;AAeA,sEAoBC;AApBD,SAAgB,6BAA6B,CACzC,SAAoE;IAEpE,IAAI,cAAwC,CAAC;IAC7C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,IACI,CAAC,cAAc;YACf,CAAC,QAAQ,CAAC,IAAI,KAAK,WAAW;gBAC1B,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;oBAC9B,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;gBAC5C,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;oBAC9B,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EACnD,CAAC;YACC,cAAc,GAAG,QAAwB,CAAC;QAC9C,CAAC;IACL,CAAC;IACD,IAAI,cAAc,EAAE,CAAC;QACjB,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
const log_level_manager_global_1 = require("@loglayer/log-level-manager-global");
|
|
5
|
+
const transport_pino_1 = require("@loglayer/transport-pino");
|
|
6
|
+
const loglayer_1 = require("loglayer");
|
|
7
|
+
const pino_1 = require("pino");
|
|
8
|
+
const p = (0, pino_1.pino)({
|
|
9
|
+
level: "trace", // Enable all log levels
|
|
10
|
+
});
|
|
11
|
+
exports.logger = new loglayer_1.LogLayer({
|
|
12
|
+
transport: new transport_pino_1.PinoTransport({
|
|
13
|
+
logger: p,
|
|
14
|
+
}),
|
|
15
|
+
}).withLogLevelManager(new log_level_manager_global_1.GlobalLogLevelManager());
|
|
16
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":";;;AAAA,iFAA2E;AAC3E,6DAAyD;AACzD,uCAAoC;AACpC,+BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,WAAI,EAAC;IACX,KAAK,EAAE,OAAO,EAAE,wBAAwB;CAC3C,CAAC,CAAC;AAEU,QAAA,MAAM,GAAG,IAAI,mBAAQ,CAAC;IAC/B,SAAS,EAAE,IAAI,8BAAa,CAAC;QACzB,MAAM,EAAE,CAAC;KACZ,CAAC;CACL,CAAC,CAAC,mBAAmB,CAAC,IAAI,gDAAqB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Chart as BaseChart } from "gcm-database/maimai";
|
|
2
|
+
import type { Presences } from "./presence";
|
|
3
|
+
export interface Chart extends BaseChart {
|
|
4
|
+
optionalData: Partial<{
|
|
5
|
+
bpm: number[];
|
|
6
|
+
notes: {
|
|
7
|
+
tap: number;
|
|
8
|
+
hold: number;
|
|
9
|
+
slide: number;
|
|
10
|
+
touch: number;
|
|
11
|
+
break: number;
|
|
12
|
+
};
|
|
13
|
+
designer: {
|
|
14
|
+
id: number;
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
presences: Presences[];
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/maimai/chart.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Database as BaseDatabase, Difficulty, Type } from "gcm-database/maimai";
|
|
2
|
+
import type { Chart } from "./chart";
|
|
3
|
+
export declare class Database implements BaseDatabase<Chart> {
|
|
4
|
+
private _localDatabasePath;
|
|
5
|
+
constructor(_localDatabasePath: string);
|
|
6
|
+
setLocalDatabasePath(path: string): boolean;
|
|
7
|
+
hasLocalDatabase(): boolean;
|
|
8
|
+
private cache;
|
|
9
|
+
getJacket(identifier: string, variant?: "DX" | "EX" | "CN"): Promise<{
|
|
10
|
+
data: Buffer<ArrayBuffer> | Buffer<any>;
|
|
11
|
+
err?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
err: string;
|
|
14
|
+
data?: undefined;
|
|
15
|
+
}>;
|
|
16
|
+
getChart(identifier: string, difficulty: Difficulty): Promise<{
|
|
17
|
+
data: any;
|
|
18
|
+
err?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
err: string;
|
|
21
|
+
data?: undefined;
|
|
22
|
+
}>;
|
|
23
|
+
private getAllCharts;
|
|
24
|
+
searchChart(payload: {
|
|
25
|
+
title: string;
|
|
26
|
+
level: number;
|
|
27
|
+
difficulty: Difficulty;
|
|
28
|
+
type: Type;
|
|
29
|
+
}, options?: Partial<{
|
|
30
|
+
maxResultCount: number;
|
|
31
|
+
}>): Promise<{
|
|
32
|
+
data: {
|
|
33
|
+
chart: Chart;
|
|
34
|
+
weight: number;
|
|
35
|
+
}[];
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Database = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const cache_1 = require("../lib/cache");
|
|
10
|
+
const getInternalLevelFromPresences_1 = require("../lib/getInternalLevelFromPresences");
|
|
11
|
+
class Database {
|
|
12
|
+
_localDatabasePath;
|
|
13
|
+
constructor(_localDatabasePath) {
|
|
14
|
+
this._localDatabasePath = _localDatabasePath;
|
|
15
|
+
}
|
|
16
|
+
setLocalDatabasePath(path) {
|
|
17
|
+
if (node_fs_1.default.existsSync(path)) {
|
|
18
|
+
this._localDatabasePath = path;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
hasLocalDatabase() {
|
|
26
|
+
return node_fs_1.default.existsSync(this._localDatabasePath);
|
|
27
|
+
}
|
|
28
|
+
cache = new cache_1.Cache("gcm-database-local/maimai");
|
|
29
|
+
async getJacket(identifier, variant) {
|
|
30
|
+
const cacheKey = `jacket-${identifier}${variant ? `-${variant}` : ""}`;
|
|
31
|
+
const cached = await this.cache.get(cacheKey);
|
|
32
|
+
if (cached instanceof Buffer) {
|
|
33
|
+
return { data: cached };
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const songId = identifier.slice(-4);
|
|
37
|
+
if (variant) {
|
|
38
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "maimai", "jackets", `${songId.padStart(6, "0")}-${variant}.png`);
|
|
39
|
+
if (node_fs_1.default.existsSync(localFilePath)) {
|
|
40
|
+
return { data: node_fs_1.default.readFileSync(localFilePath) };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Falls back to normal jacket if a variant cannot be found.
|
|
44
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "maimai", "jackets", `${songId.padStart(6, "0")}.png`);
|
|
45
|
+
const jacket = node_fs_1.default.existsSync(localFilePath) && node_fs_1.default.readFileSync(localFilePath);
|
|
46
|
+
if (jacket) {
|
|
47
|
+
this.cache.put(cacheKey, jacket, 5 * 1000); // 5 seconds.
|
|
48
|
+
return { data: jacket };
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return { err: `Cannot find the jacket of ${identifier}.` };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async getChart(identifier, difficulty) {
|
|
56
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "maimai", "charts", `${identifier.padStart(6, "0")}`);
|
|
57
|
+
if (node_fs_1.default.existsSync(node_path_1.default.join(localFilePath, difficulty))) {
|
|
58
|
+
try {
|
|
59
|
+
return {
|
|
60
|
+
data: JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(localFilePath, difficulty), "utf-8")),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {
|
|
65
|
+
err: `Failed to parse ${identifier} ${difficulty}.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
err: `Cannot find a chart with identifier ${identifier}.`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async getAllCharts() {
|
|
74
|
+
const cached = await this.cache.get("all-charts");
|
|
75
|
+
if (cached)
|
|
76
|
+
return cached;
|
|
77
|
+
const localFolderPath = node_path_1.default.join(this._localDatabasePath, "assets", "maimai", "charts");
|
|
78
|
+
const chartFolders = node_fs_1.default.readdirSync(localFolderPath);
|
|
79
|
+
const songs = [];
|
|
80
|
+
for (const folder of chartFolders) {
|
|
81
|
+
const charts = node_fs_1.default.readdirSync(node_path_1.default.join(localFolderPath, folder));
|
|
82
|
+
for (const chart of charts) {
|
|
83
|
+
try {
|
|
84
|
+
songs.push(require(node_path_1.default.join(localFolderPath, folder, chart)));
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
await this.cache.put("all-charts", songs, 15 * 60 * 1000); // 15 minutes.
|
|
90
|
+
return songs;
|
|
91
|
+
}
|
|
92
|
+
async searchChart(payload, options) {
|
|
93
|
+
const allSongs = await this.getAllCharts();
|
|
94
|
+
const sortedCandidates = allSongs
|
|
95
|
+
.filter((v) => v.title === payload.title &&
|
|
96
|
+
v.type === payload.type &&
|
|
97
|
+
v.difficulty === payload.difficulty)
|
|
98
|
+
.map((v) => {
|
|
99
|
+
if (v.optionalData.presences) {
|
|
100
|
+
if (v.optionalData.presences) {
|
|
101
|
+
const internalLevel = (0, getInternalLevelFromPresences_1.getInternalLevelFromPresences)(v.optionalData.presences);
|
|
102
|
+
if (internalLevel) {
|
|
103
|
+
return {
|
|
104
|
+
chart: v,
|
|
105
|
+
weight: Math.abs(internalLevel - payload.level),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { chart: v };
|
|
111
|
+
})
|
|
112
|
+
.filter((v) => !!v.weight)
|
|
113
|
+
.sort((a, b) => a.weight - b.weight);
|
|
114
|
+
return { data: sortedCandidates.slice(options?.maxResultCount || 20) };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.Database = Database;
|
|
118
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/maimai/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interface BasePresence {
|
|
2
|
+
type: string;
|
|
3
|
+
data?: unknown;
|
|
4
|
+
version: Version;
|
|
5
|
+
}
|
|
6
|
+
export interface Existence extends BasePresence {
|
|
7
|
+
type: "existence";
|
|
8
|
+
data: {
|
|
9
|
+
level: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface Absence extends BasePresence {
|
|
13
|
+
type: "absence";
|
|
14
|
+
}
|
|
15
|
+
export interface Removal extends BasePresence {
|
|
16
|
+
type: "removal";
|
|
17
|
+
}
|
|
18
|
+
export interface UsaLock extends BasePresence {
|
|
19
|
+
type: "usa_lock";
|
|
20
|
+
}
|
|
21
|
+
export type Presences = Existence | Absence | Removal | UsaLock;
|
|
22
|
+
export interface Version {
|
|
23
|
+
/**
|
|
24
|
+
* Full name of the version.
|
|
25
|
+
* @example "maimai でらっくす PRiSM PLUS"
|
|
26
|
+
*/
|
|
27
|
+
name: string;
|
|
28
|
+
/**
|
|
29
|
+
* Version number as it is used internally.
|
|
30
|
+
* Formatted as `{major}.{minor}.{patch}`.
|
|
31
|
+
*
|
|
32
|
+
* @example "1.40" for "1.40"
|
|
33
|
+
* @example "1.99" for "1.99"
|
|
34
|
+
* @example "2.41.7" for "DX1.41-G"
|
|
35
|
+
* @example "2.55.0" for "DX1.55"
|
|
36
|
+
*/
|
|
37
|
+
gameVersion: {
|
|
38
|
+
/**
|
|
39
|
+
* maimai FiNALE and earlier: `1`
|
|
40
|
+
*
|
|
41
|
+
* maimai DX and later: `2`
|
|
42
|
+
*/
|
|
43
|
+
major: number;
|
|
44
|
+
minor: number;
|
|
45
|
+
release?: number;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Events before maimai DX is always `DX`
|
|
49
|
+
*/
|
|
50
|
+
region: "DX" | "EX" | "CN";
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/maimai/presence.ts"],"names":[],"mappings":""}
|
package/dist/maimai.d.ts
ADDED
package/dist/maimai.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Database = void 0;
|
|
4
|
+
var database_1 = require("./maimai/database");
|
|
5
|
+
Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return database_1.Database; } });
|
|
6
|
+
//# sourceMappingURL=maimai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maimai.js","sourceRoot":"","sources":["../src/maimai.ts"],"names":[],"mappings":";;;AACA,6CAA4C;AAAnC,oGAAA,QAAQ,OAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Chart as BaseChart } from "gcm-database/ongeki";
|
|
2
|
+
import type { Presences } from "./presence";
|
|
3
|
+
export interface Chart extends BaseChart {
|
|
4
|
+
optionalData: Partial<{
|
|
5
|
+
bpm: number[];
|
|
6
|
+
notes: {
|
|
7
|
+
tap: number;
|
|
8
|
+
hold: number;
|
|
9
|
+
side: number;
|
|
10
|
+
flick: number;
|
|
11
|
+
bell: number;
|
|
12
|
+
};
|
|
13
|
+
designer: string;
|
|
14
|
+
presences: Presences[];
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/ongeki/chart.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Database as BaseDatabase, Difficulty } from "gcm-database/ongeki";
|
|
2
|
+
import type { Chart } from "./chart";
|
|
3
|
+
export declare class Database implements BaseDatabase<Chart> {
|
|
4
|
+
private _localDatabasePath;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(_localDatabasePath: string);
|
|
7
|
+
setLocalDatabasePath(path: string): boolean;
|
|
8
|
+
hasLocalDatabase(): boolean;
|
|
9
|
+
private cache;
|
|
10
|
+
getJacket(identifier: string, variant?: "DX" | "EX" | "CN"): Promise<{
|
|
11
|
+
data: Buffer<ArrayBuffer> | Buffer<any>;
|
|
12
|
+
err?: undefined;
|
|
13
|
+
} | {
|
|
14
|
+
err: string;
|
|
15
|
+
data?: undefined;
|
|
16
|
+
}>;
|
|
17
|
+
getChart(identifier: string, difficulty: Difficulty): Promise<{
|
|
18
|
+
data: any;
|
|
19
|
+
err?: undefined;
|
|
20
|
+
} | {
|
|
21
|
+
err: string;
|
|
22
|
+
data?: undefined;
|
|
23
|
+
}>;
|
|
24
|
+
private getAllCharts;
|
|
25
|
+
searchChart(payload: {
|
|
26
|
+
title: string;
|
|
27
|
+
level: number;
|
|
28
|
+
difficulty: Difficulty;
|
|
29
|
+
}, options?: Partial<{
|
|
30
|
+
maxResultCount: number;
|
|
31
|
+
}>): Promise<{
|
|
32
|
+
data: {
|
|
33
|
+
chart: Chart;
|
|
34
|
+
weight: number;
|
|
35
|
+
}[];
|
|
36
|
+
}>;
|
|
37
|
+
getBossCard(chart: Chart): Promise<{
|
|
38
|
+
data: Buffer<ArrayBuffer> | Buffer<any>;
|
|
39
|
+
err?: undefined;
|
|
40
|
+
} | {
|
|
41
|
+
err: string;
|
|
42
|
+
data?: undefined;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Database = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const cache_1 = require("../lib/cache");
|
|
10
|
+
const getInternalLevelFromPresences_1 = require("../lib/getInternalLevelFromPresences");
|
|
11
|
+
const logger_1 = require("../lib/logger");
|
|
12
|
+
class Database {
|
|
13
|
+
_localDatabasePath;
|
|
14
|
+
logger = logger_1.logger
|
|
15
|
+
.child()
|
|
16
|
+
.withGroup("gcm-database-local/ongeki");
|
|
17
|
+
constructor(_localDatabasePath) {
|
|
18
|
+
this._localDatabasePath = _localDatabasePath;
|
|
19
|
+
}
|
|
20
|
+
setLocalDatabasePath(path) {
|
|
21
|
+
if (node_fs_1.default.existsSync(path)) {
|
|
22
|
+
this._localDatabasePath = path;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
hasLocalDatabase() {
|
|
30
|
+
return node_fs_1.default.existsSync(this._localDatabasePath);
|
|
31
|
+
}
|
|
32
|
+
cache = new cache_1.Cache("gcm-database-local/ongeki");
|
|
33
|
+
async getJacket(identifier, variant) {
|
|
34
|
+
const cacheKey = `jacket-${identifier}${variant ? `-${variant}` : ""}`;
|
|
35
|
+
const cached = await this.cache.get(cacheKey);
|
|
36
|
+
if (cached instanceof Buffer) {
|
|
37
|
+
return { data: cached };
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const songId = identifier.slice(-4);
|
|
41
|
+
if (variant) {
|
|
42
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "ongeki", "jackets", `${songId.padStart(6, "0")}-${variant}.png`);
|
|
43
|
+
if (node_fs_1.default.existsSync(localFilePath)) {
|
|
44
|
+
return { data: node_fs_1.default.readFileSync(localFilePath) };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Falls back to normal jacket if a variant cannot be found.
|
|
48
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "ongeki", "jackets", `${songId.padStart(6, "0")}.png`);
|
|
49
|
+
const jacket = node_fs_1.default.existsSync(localFilePath) && node_fs_1.default.readFileSync(localFilePath);
|
|
50
|
+
if (jacket) {
|
|
51
|
+
this.cache.put(cacheKey, jacket, 5 * 1000); // 5 seconds.
|
|
52
|
+
return { data: jacket };
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return { err: `Cannot find the jacket of ${identifier}.` };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async getChart(identifier, difficulty) {
|
|
60
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "ongeki", "charts", `${identifier.padStart(6, "0")}`);
|
|
61
|
+
if (node_fs_1.default.existsSync(node_path_1.default.join(localFilePath, difficulty))) {
|
|
62
|
+
try {
|
|
63
|
+
return {
|
|
64
|
+
data: JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(localFilePath, difficulty), "utf-8")),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return {
|
|
69
|
+
err: `Failed to parse ${identifier} ${difficulty}.`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
err: `Cannot find a chart with identifier ${identifier}.`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async getAllCharts() {
|
|
78
|
+
const cached = await this.cache.get("all-charts");
|
|
79
|
+
if (cached)
|
|
80
|
+
return cached;
|
|
81
|
+
const localFolderPath = node_path_1.default.join(this._localDatabasePath, "assets", "ongeki", "charts");
|
|
82
|
+
const chartFolders = node_fs_1.default.readdirSync(localFolderPath);
|
|
83
|
+
const songs = [];
|
|
84
|
+
for (const folder of chartFolders) {
|
|
85
|
+
const charts = node_fs_1.default.readdirSync(node_path_1.default.join(localFolderPath, folder));
|
|
86
|
+
for (const chart of charts) {
|
|
87
|
+
try {
|
|
88
|
+
songs.push(require(node_path_1.default.join(localFolderPath, folder, chart)));
|
|
89
|
+
}
|
|
90
|
+
catch { }
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
await this.cache.put("all-charts", songs, 15 * 60 * 1000); // 15 minutes.
|
|
94
|
+
return songs;
|
|
95
|
+
}
|
|
96
|
+
async searchChart(payload, options) {
|
|
97
|
+
const allSongs = await this.getAllCharts();
|
|
98
|
+
const sortedCandidates = allSongs
|
|
99
|
+
.filter((v) => v.title === payload.title &&
|
|
100
|
+
v.difficulty === payload.difficulty)
|
|
101
|
+
.map((v) => {
|
|
102
|
+
if (v.optionalData.presences) {
|
|
103
|
+
const internalLevel = (0, getInternalLevelFromPresences_1.getInternalLevelFromPresences)(v.optionalData.presences);
|
|
104
|
+
if (internalLevel) {
|
|
105
|
+
return {
|
|
106
|
+
chart: v,
|
|
107
|
+
weight: Math.abs(internalLevel - payload.level),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { chart: v };
|
|
112
|
+
})
|
|
113
|
+
.filter((v) => !!v.weight)
|
|
114
|
+
.sort((a, b) => a.weight - b.weight);
|
|
115
|
+
return { data: sortedCandidates.slice(options?.maxResultCount || 20) };
|
|
116
|
+
}
|
|
117
|
+
async getBossCard(chart) {
|
|
118
|
+
const identifier = chart.boss.character.card;
|
|
119
|
+
const cacheKey = `boss-card-${identifier}`;
|
|
120
|
+
const cached = await this.cache.get(cacheKey);
|
|
121
|
+
if (cached instanceof Buffer) {
|
|
122
|
+
this.logger.trace(`GET Card-${identifier}-image, cache HIT`);
|
|
123
|
+
return { data: cached };
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
this.logger.trace(`GET Card-${identifier}-image, cache MISS`);
|
|
127
|
+
const localFilePath = node_path_1.default.join(this._localDatabasePath, "assets", "ongeki", "cards", "images", `${identifier.padStart(6, "0")}.png`);
|
|
128
|
+
if (node_fs_1.default.existsSync(localFilePath)) {
|
|
129
|
+
this.logger.trace(`GET Card-${identifier}-image, database HIT`);
|
|
130
|
+
const card = node_fs_1.default.readFileSync(localFilePath);
|
|
131
|
+
if (card)
|
|
132
|
+
this.cache.put(cacheKey, card, 5 * 1000); // 5 seconds
|
|
133
|
+
return { data: card };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { err: "Cannot find the card of this character." };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.Database = Database;
|
|
140
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/ongeki/database.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAyB;AACzB,0DAA6B;AAC7B,sCAAmC;AACnC,sFAAmF;AACnF,wCAAqC;AAIrC,MAAa,QAAQ;IAIG;IAHH,MAAM,GAAG,eAAM;SAC3B,KAAK,EAAE;SACP,SAAS,CAAC,2BAA2B,CAAC,CAAC;IAC5C,YAAoB,kBAA0B;QAA1B,uBAAkB,GAAlB,kBAAkB,CAAQ;IAAG,CAAC;IAE3C,oBAAoB,CAAC,IAAY;QACpC,IAAI,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC/B,OAAO,IAAI,CAAC;QAChB,CAAC;aAAM,CAAC;YACJ,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAEM,gBAAgB;QACnB,OAAO,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,GAAG,IAAI,aAAK,CAAC,2BAA2B,CAAC,CAAC;IAChD,KAAK,CAAC,SAAS,CAAC,UAAkB,EAAE,OAA4B;QACnE,MAAM,QAAQ,GAAG,UAAU,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,MAAM,YAAY,MAAM,EAAE,CAAC;YAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;aAAM,CAAC;YACJ,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,OAAO,EAAE,CAAC;gBACV,MAAM,aAAa,GAAG,mBAAI,CAAC,IAAI,CAC3B,IAAI,CAAC,kBAAkB,EACvB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,MAAM,CAC9C,CAAC;gBACF,IAAI,iBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC/B,OAAO,EAAE,IAAI,EAAE,iBAAE,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC;gBACpD,CAAC;YACL,CAAC;YACD,4DAA4D;YAC5D,MAAM,aAAa,GAAG,mBAAI,CAAC,IAAI,CAC3B,IAAI,CAAC,kBAAkB,EACvB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CACnC,CAAC;YACF,MAAM,MAAM,GACR,iBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,iBAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YACnE,IAAI,MAAM,EAAE,CAAC;gBACT,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa;gBACzD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACJ,OAAO,EAAE,GAAG,EAAE,6BAA6B,UAAU,GAAG,EAAE,CAAC;YAC/D,CAAC;QACL,CAAC;IACL,CAAC;IACM,KAAK,CAAC,QAAQ,CAAC,UAAkB,EAAE,UAAsB;QAC5D,MAAM,aAAa,GAAG,mBAAI,CAAC,IAAI,CAC3B,IAAI,CAAC,kBAAkB,EACvB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACnC,CAAC;QACF,IAAI,iBAAE,CAAC,UAAU,CAAC,mBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC;gBACD,OAAO;oBACH,IAAI,EAAE,IAAI,CAAC,KAAK,CACZ,iBAAE,CAAC,YAAY,CACX,mBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,EACpC,OAAO,CACV,CACJ;iBACJ,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO;oBACH,GAAG,EAAE,mBAAmB,UAAU,IAAI,UAAU,GAAG;iBACtD,CAAC;YACN,CAAC;QACL,CAAC;QACD,OAAO;YACH,GAAG,EAAE,uCAAuC,UAAU,GAAG;SAC5D,CAAC;IACN,CAAC;IACO,KAAK,CAAC,YAAY;QACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,MAAM;YAAE,OAAO,MAAiB,CAAC;QACrC,MAAM,eAAe,GAAG,mBAAI,CAAC,IAAI,CAC7B,IAAI,CAAC,kBAAkB,EACvB,QAAQ,EACR,QAAQ,EACR,QAAQ,CACX,CAAC;QACF,MAAM,YAAY,GAAG,iBAAE,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,KAAK,GAAY,EAAE,CAAC;QAC1B,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,iBAAE,CAAC,WAAW,CAAC,mBAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;YAClE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACD,KAAK,CAAC,IAAI,CACN,OAAO,CAAC,mBAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CACrD,CAAC;gBACN,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACd,CAAC;QACL,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc;QACzE,OAAO,KAAK,CAAC;IACjB,CAAC;IACM,KAAK,CAAC,WAAW,CACpB,OAIC,EACD,OAEE;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,QAAQ;aAC5B,MAAM,CACH,CAAC,CAAC,EAAE,EAAE,CACF,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK;YACzB,CAAC,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,CAC1C;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACP,IAAI,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;gBAC3B,MAAM,aAAa,GAAG,IAAA,6DAA6B,EAC/C,CAAC,CAAC,YAAY,CAAC,SAAS,CAC3B,CAAC;gBACF,IAAI,aAAa,EAAE,CAAC;oBAChB,OAAO;wBACH,KAAK,EAAE,CAAC;wBACR,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC;qBAClD,CAAC;gBACN,CAAC;YACL,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACxB,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAyC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;aAChE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3E,CAAC;IACM,KAAK,CAAC,WAAW,CAAC,KAAY;QACjC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7C,MAAM,QAAQ,GAAG,aAAa,UAAU,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,MAAM,YAAY,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,mBAAmB,CAAC,CAAC;YAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,oBAAoB,CAAC,CAAC;YAC9D,MAAM,aAAa,GAAG,mBAAI,CAAC,IAAI,CAC3B,IAAI,CAAC,kBAAkB,EACvB,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CACvC,CAAC;YACF,IAAI,iBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,sBAAsB,CAAC,CAAC;gBAChE,MAAM,IAAI,GAAG,iBAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC5C,IAAI,IAAI;oBAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,YAAY;gBAChE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC1B,CAAC;QACL,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,yCAAyC,EAAE,CAAC;IAC9D,CAAC;CACJ;AA1KD,4BA0KC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface BasePresence {
|
|
2
|
+
type: string;
|
|
3
|
+
data?: unknown;
|
|
4
|
+
version: Version;
|
|
5
|
+
}
|
|
6
|
+
export interface Existence extends BasePresence {
|
|
7
|
+
type: "existence";
|
|
8
|
+
data: {
|
|
9
|
+
level: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface Absence extends BasePresence {
|
|
13
|
+
type: "absence";
|
|
14
|
+
}
|
|
15
|
+
export interface Removal extends BasePresence {
|
|
16
|
+
type: "removal";
|
|
17
|
+
}
|
|
18
|
+
export type Presences = Existence | Absence | Removal;
|
|
19
|
+
export interface Version {
|
|
20
|
+
/**
|
|
21
|
+
* Full name of the version.
|
|
22
|
+
* @example "オンゲキ Re:Fresh"
|
|
23
|
+
*/
|
|
24
|
+
name: string;
|
|
25
|
+
/**
|
|
26
|
+
* Version number as it is used internally.
|
|
27
|
+
* Formatted as `{major}.{minor}.{patch}`.
|
|
28
|
+
*/
|
|
29
|
+
gameVersion: {
|
|
30
|
+
major: number;
|
|
31
|
+
minor: number;
|
|
32
|
+
release?: number;
|
|
33
|
+
};
|
|
34
|
+
region: "JPN";
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/ongeki/presence.ts"],"names":[],"mappings":""}
|
package/dist/ongeki.d.ts
ADDED
package/dist/ongeki.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Database = void 0;
|
|
4
|
+
var database_1 = require("./ongeki/database");
|
|
5
|
+
Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return database_1.Database; } });
|
|
6
|
+
//# sourceMappingURL=ongeki.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ongeki.js","sourceRoot":"","sources":["../src/ongeki.ts"],"names":[],"mappings":";;;AACA,6CAA4C;AAAnC,oGAAA,QAAQ,OAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gcm-database-local",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A GekiChuMai Metadata database",
|
|
5
|
+
"homepage": "https://github.com/saltcute/gcm-database-local#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/saltcute/gcm-database-local/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/saltcute/gcm-database-local.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "saltcute",
|
|
15
|
+
"type": "commonjs",
|
|
16
|
+
"exports": {
|
|
17
|
+
"./maimai": "./dist/maimai.js",
|
|
18
|
+
"./chunithm": "./dist/chunithm.js",
|
|
19
|
+
"./ongeki": "./dist/ongeki.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist/"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc && tsc-alias",
|
|
26
|
+
"clean": "rimraf dist/*",
|
|
27
|
+
"format": "biome format --write",
|
|
28
|
+
"lint": "biome lint --write",
|
|
29
|
+
"make": "npm run clean && npm run format && npm run lint && npm run build",
|
|
30
|
+
"test": "export LOG_LEVEL=debug && npm run make && node ./test/test.js"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@biomejs/biome": "^2.5.0",
|
|
34
|
+
"@types/memory-cache": "^0.2.6",
|
|
35
|
+
"@types/node": "^25.9.3",
|
|
36
|
+
"rimraf": "^6.1.3",
|
|
37
|
+
"tsc-alias": "^1.8.17",
|
|
38
|
+
"typescript": "^6.0.3"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@loglayer/log-level-manager-global": "^2.2.0",
|
|
42
|
+
"@loglayer/transport-pino": "^3.2.0",
|
|
43
|
+
"loglayer": "^9.3.0",
|
|
44
|
+
"memory-cache": "^0.2.0",
|
|
45
|
+
"pino": "^10.3.1",
|
|
46
|
+
"redis": "^6.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"gcm-database": "^0.0.6"
|
|
50
|
+
}
|
|
51
|
+
}
|