osu-play 1.0.1 → 1.0.3
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/bin/osu-play.js +1 -1
- package/dist/index.d.ts +121 -0
- package/dist/index.js +335 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli/main.d.ts +3 -0
- package/dist/src/cli/main.js +365 -0
- package/dist/src/cli/main.js.map +1 -0
- package/index.ts +1 -0
- package/package.json +20 -5
- package/src/{main.ts → cli/main.ts} +6 -5
- package/src/mod.ts +2 -0
- package/tsconfig.json +7 -3
package/bin/osu-play.js
CHANGED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import Realm, { ObjectSchema } from 'realm';
|
|
2
|
+
|
|
3
|
+
declare function getDataDir(): string | null;
|
|
4
|
+
declare function getConfigDir(): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Get Realm for the app, import to the config if it doesn't exist
|
|
7
|
+
*/
|
|
8
|
+
declare function getRealmDBPath(appConfigDir: string, osuDataDir?: string, reload?: boolean): string | null;
|
|
9
|
+
|
|
10
|
+
declare const mod$1_getConfigDir: typeof getConfigDir;
|
|
11
|
+
declare const mod$1_getDataDir: typeof getDataDir;
|
|
12
|
+
declare const mod$1_getRealmDBPath: typeof getRealmDBPath;
|
|
13
|
+
declare namespace mod$1 {
|
|
14
|
+
export {
|
|
15
|
+
mod$1_getConfigDir as getConfigDir,
|
|
16
|
+
mod$1_getDataDir as getDataDir,
|
|
17
|
+
mod$1_getRealmDBPath as getRealmDBPath,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare class RealmUser extends Realm.Object<RealmUser> {
|
|
22
|
+
OnlineID: number;
|
|
23
|
+
Username?: string;
|
|
24
|
+
CountryCode?: string;
|
|
25
|
+
static embedded: boolean;
|
|
26
|
+
static schema: ObjectSchema;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare class BeatmapMetadata extends Realm.Object<BeatmapMetadata> {
|
|
30
|
+
Title?: string;
|
|
31
|
+
TitleUnicode?: string;
|
|
32
|
+
Artist?: string;
|
|
33
|
+
ArtistUnicode?: string;
|
|
34
|
+
Author?: RealmUser;
|
|
35
|
+
Source?: string;
|
|
36
|
+
Tags?: string;
|
|
37
|
+
PreviewTime?: number;
|
|
38
|
+
AudioFile?: string;
|
|
39
|
+
BackgroundFile?: string;
|
|
40
|
+
static schema: ObjectSchema;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare class Beatmap extends Realm.Object<Beatmap> {
|
|
44
|
+
ID: string;
|
|
45
|
+
DifficultyName?: string;
|
|
46
|
+
Ruleset: any;
|
|
47
|
+
Difficulty: any;
|
|
48
|
+
Metadata: BeatmapMetadata;
|
|
49
|
+
UserSettings: any;
|
|
50
|
+
BeatmapSet: any;
|
|
51
|
+
Status: number;
|
|
52
|
+
OnlineID: number;
|
|
53
|
+
Length: number;
|
|
54
|
+
BPM: number;
|
|
55
|
+
Hash?: string;
|
|
56
|
+
StarRating: number;
|
|
57
|
+
MD5Hash?: string;
|
|
58
|
+
OnlineMD5Hash?: string;
|
|
59
|
+
LastLocalUpdate?: Date;
|
|
60
|
+
LastOnlineUpdate?: Date;
|
|
61
|
+
Hidden: boolean;
|
|
62
|
+
AudioLeadIn: number;
|
|
63
|
+
StackLeniency: number;
|
|
64
|
+
SpecialStyle: boolean;
|
|
65
|
+
LetterboxInBreaks: boolean;
|
|
66
|
+
WidescreenStoryboard: boolean;
|
|
67
|
+
EpilepsyWarning: boolean;
|
|
68
|
+
SamplesMatchPlaybackRate: boolean;
|
|
69
|
+
LastPlayed?: Date;
|
|
70
|
+
DistanceSpacing: number;
|
|
71
|
+
BeatDivisor: number;
|
|
72
|
+
GridSize: number;
|
|
73
|
+
TimelineZoom: number;
|
|
74
|
+
EditorTimestamp?: number;
|
|
75
|
+
CountdownOffset: number;
|
|
76
|
+
static schema: ObjectSchema;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
declare class RealmFile extends Realm.Object<RealmFile> {
|
|
80
|
+
Hash?: string;
|
|
81
|
+
static schema: ObjectSchema;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
declare class RealmNamedFileUsage extends Realm.Object<RealmNamedFileUsage> {
|
|
85
|
+
File: RealmFile;
|
|
86
|
+
Filename?: string;
|
|
87
|
+
static embedded: boolean;
|
|
88
|
+
static schema: ObjectSchema;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare class BeatmapSet extends Realm.Object<BeatmapSet> {
|
|
92
|
+
ID: string;
|
|
93
|
+
OnlineID: number;
|
|
94
|
+
DateAdded: Date;
|
|
95
|
+
DateSubmitted?: Date;
|
|
96
|
+
DateRanked?: Date;
|
|
97
|
+
Beatmaps: Array<Beatmap>;
|
|
98
|
+
Files: Array<RealmNamedFileUsage>;
|
|
99
|
+
Status: number;
|
|
100
|
+
DeletePending: boolean;
|
|
101
|
+
Hash?: string;
|
|
102
|
+
Protected: boolean;
|
|
103
|
+
static schema: ObjectSchema;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
declare const getLazerDB: (realmDBPath: string) => Promise<Realm>;
|
|
107
|
+
declare const hashedFilePath: (hash: string) => string | null;
|
|
108
|
+
declare const getNamedFileHash: (fileName: string, beatmapSet: BeatmapSet) => string | undefined;
|
|
109
|
+
|
|
110
|
+
declare const mod_getLazerDB: typeof getLazerDB;
|
|
111
|
+
declare const mod_getNamedFileHash: typeof getNamedFileHash;
|
|
112
|
+
declare const mod_hashedFilePath: typeof hashedFilePath;
|
|
113
|
+
declare namespace mod {
|
|
114
|
+
export {
|
|
115
|
+
mod_getLazerDB as getLazerDB,
|
|
116
|
+
mod_getNamedFileHash as getNamedFileHash,
|
|
117
|
+
mod_hashedFilePath as hashedFilePath,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { mod as lazer, mod$1 as utils };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/utils/mod.ts
|
|
8
|
+
var mod_exports = {};
|
|
9
|
+
__export(mod_exports, {
|
|
10
|
+
getConfigDir: () => getConfigDir,
|
|
11
|
+
getDataDir: () => getDataDir,
|
|
12
|
+
getRealmDBPath: () => getRealmDBPath
|
|
13
|
+
});
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { copyFileSync, existsSync, mkdirSync } from "fs";
|
|
16
|
+
function getDataDir() {
|
|
17
|
+
switch (process.platform) {
|
|
18
|
+
case "linux":
|
|
19
|
+
case "openbsd":
|
|
20
|
+
case "freebsd": {
|
|
21
|
+
const xdg = process.env["XDG_DATA_HOME"];
|
|
22
|
+
if (xdg)
|
|
23
|
+
return xdg;
|
|
24
|
+
const home = process.env["HOME"];
|
|
25
|
+
if (home)
|
|
26
|
+
return path.join(home, ".local", "share");
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case "darwin": {
|
|
30
|
+
const home = process.env["HOME"];
|
|
31
|
+
if (home)
|
|
32
|
+
return path.join(home, "Library", "Application Support");
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case "win32":
|
|
36
|
+
return process.env["LOCALAPPDATA"] ?? null;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function getConfigDir() {
|
|
41
|
+
switch (process.platform) {
|
|
42
|
+
case "openbsd":
|
|
43
|
+
case "freebsd":
|
|
44
|
+
case "linux": {
|
|
45
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
46
|
+
if (xdg)
|
|
47
|
+
return xdg;
|
|
48
|
+
const home = process.env["HOME"];
|
|
49
|
+
if (home)
|
|
50
|
+
return path.join(home, ".config");
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "darwin": {
|
|
54
|
+
const home = process.env["HOME"];
|
|
55
|
+
if (home)
|
|
56
|
+
return path.join(home, "Library", "Preferences");
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case "win32":
|
|
60
|
+
return process.env["APPDATA"] ?? null;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function getRealmDBPath(appConfigDir, osuDataDir, reload = false) {
|
|
65
|
+
const localDBPath = path.join(appConfigDir, "client.realm");
|
|
66
|
+
if (!reload && existsSync(localDBPath))
|
|
67
|
+
return localDBPath;
|
|
68
|
+
const osuDBPath = path.join(
|
|
69
|
+
osuDataDir || getDataDir() || ".",
|
|
70
|
+
"osu",
|
|
71
|
+
"client.realm"
|
|
72
|
+
);
|
|
73
|
+
if (existsSync(osuDBPath)) {
|
|
74
|
+
console.log(
|
|
75
|
+
`[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`
|
|
76
|
+
);
|
|
77
|
+
mkdirSync(appConfigDir);
|
|
78
|
+
copyFileSync(osuDBPath, localDBPath);
|
|
79
|
+
return localDBPath;
|
|
80
|
+
} else {
|
|
81
|
+
console.log(`[getRealmDBPath]: ${osuDBPath} not found`);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/realm/mod.ts
|
|
87
|
+
var mod_exports2 = {};
|
|
88
|
+
__export(mod_exports2, {
|
|
89
|
+
getLazerDB: () => getLazerDB,
|
|
90
|
+
getNamedFileHash: () => getNamedFileHash,
|
|
91
|
+
hashedFilePath: () => hashedFilePath
|
|
92
|
+
});
|
|
93
|
+
import Realm7 from "realm";
|
|
94
|
+
import path2 from "path";
|
|
95
|
+
|
|
96
|
+
// src/realm/schema/beatmap.ts
|
|
97
|
+
import Realm from "realm";
|
|
98
|
+
var Beatmap = class extends Realm.Object {
|
|
99
|
+
ID;
|
|
100
|
+
DifficultyName;
|
|
101
|
+
Ruleset;
|
|
102
|
+
Difficulty;
|
|
103
|
+
Metadata;
|
|
104
|
+
UserSettings;
|
|
105
|
+
BeatmapSet;
|
|
106
|
+
Status;
|
|
107
|
+
OnlineID;
|
|
108
|
+
Length;
|
|
109
|
+
BPM;
|
|
110
|
+
Hash;
|
|
111
|
+
StarRating;
|
|
112
|
+
MD5Hash;
|
|
113
|
+
OnlineMD5Hash;
|
|
114
|
+
LastLocalUpdate;
|
|
115
|
+
LastOnlineUpdate;
|
|
116
|
+
Hidden;
|
|
117
|
+
AudioLeadIn;
|
|
118
|
+
StackLeniency;
|
|
119
|
+
SpecialStyle;
|
|
120
|
+
LetterboxInBreaks;
|
|
121
|
+
WidescreenStoryboard;
|
|
122
|
+
EpilepsyWarning;
|
|
123
|
+
SamplesMatchPlaybackRate;
|
|
124
|
+
LastPlayed;
|
|
125
|
+
DistanceSpacing;
|
|
126
|
+
BeatDivisor;
|
|
127
|
+
GridSize;
|
|
128
|
+
TimelineZoom;
|
|
129
|
+
EditorTimestamp;
|
|
130
|
+
CountdownOffset;
|
|
131
|
+
static schema = {
|
|
132
|
+
name: "Beatmap",
|
|
133
|
+
primaryKey: "ID",
|
|
134
|
+
properties: {
|
|
135
|
+
ID: { type: "uuid", default: "" },
|
|
136
|
+
DifficultyName: { type: "string", default: "", optional: true },
|
|
137
|
+
// Ruleset: { type: "object", objectType: "Ruleset", default: null },
|
|
138
|
+
// Difficulty: { type: "object", objectType: "BeatmapDifficulty", default: null },
|
|
139
|
+
Metadata: {
|
|
140
|
+
type: "object",
|
|
141
|
+
objectType: "BeatmapMetadata",
|
|
142
|
+
default: null
|
|
143
|
+
},
|
|
144
|
+
// UserSettings: { type: "object", objectType: "BeatmapUserSettings", default: null },
|
|
145
|
+
BeatmapSet: { type: "object", objectType: "BeatmapSet", default: null },
|
|
146
|
+
Status: { type: "int", default: -3 },
|
|
147
|
+
OnlineID: { type: "int", default: -1 },
|
|
148
|
+
Length: { type: "double", default: 0 },
|
|
149
|
+
BPM: { type: "double", default: 0 },
|
|
150
|
+
Hash: { type: "string", default: "", optional: true },
|
|
151
|
+
StarRating: { type: "double", default: -1 },
|
|
152
|
+
MD5Hash: { type: "string", default: "", optional: true },
|
|
153
|
+
OnlineMD5Hash: {
|
|
154
|
+
type: "string",
|
|
155
|
+
default: "",
|
|
156
|
+
optional: true
|
|
157
|
+
},
|
|
158
|
+
LastLocalUpdate: { type: "date", optional: true },
|
|
159
|
+
LastOnlineUpdate: { type: "date", optional: true },
|
|
160
|
+
Hidden: { type: "bool", default: false },
|
|
161
|
+
AudioLeadIn: { type: "double", default: 0 },
|
|
162
|
+
StackLeniency: { type: "float", default: 0.7 },
|
|
163
|
+
SpecialStyle: { type: "bool", default: false },
|
|
164
|
+
LetterboxInBreaks: { type: "bool", default: false },
|
|
165
|
+
WidescreenStoryboard: { type: "bool", default: false },
|
|
166
|
+
EpilepsyWarning: { type: "bool", default: false },
|
|
167
|
+
SamplesMatchPlaybackRate: { type: "bool", default: false },
|
|
168
|
+
LastPlayed: { type: "date", optional: true },
|
|
169
|
+
DistanceSpacing: { type: "double", default: 0 },
|
|
170
|
+
BeatDivisor: { type: "int", default: 0 },
|
|
171
|
+
GridSize: { type: "int", default: 0 },
|
|
172
|
+
TimelineZoom: { type: "double", default: 0 },
|
|
173
|
+
EditorTimestamp: { type: "double", optional: true },
|
|
174
|
+
CountdownOffset: { type: "int", default: 0 }
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// src/realm/schema/beatmapMetadata.ts
|
|
180
|
+
import Realm2 from "realm";
|
|
181
|
+
var BeatmapMetadata = class extends Realm2.Object {
|
|
182
|
+
Title;
|
|
183
|
+
TitleUnicode;
|
|
184
|
+
Artist;
|
|
185
|
+
ArtistUnicode;
|
|
186
|
+
Author;
|
|
187
|
+
Source;
|
|
188
|
+
Tags;
|
|
189
|
+
PreviewTime;
|
|
190
|
+
AudioFile;
|
|
191
|
+
BackgroundFile;
|
|
192
|
+
static schema = {
|
|
193
|
+
name: "BeatmapMetadata",
|
|
194
|
+
properties: {
|
|
195
|
+
Title: { type: "string", default: "", optional: true },
|
|
196
|
+
TitleUnicode: { type: "string", default: "", optional: true },
|
|
197
|
+
Artist: { type: "string", default: "", optional: true },
|
|
198
|
+
ArtistUnicode: { type: "string", default: "", optional: true },
|
|
199
|
+
Author: { type: "object", objectType: "RealmUser", default: null },
|
|
200
|
+
Source: { type: "string", default: "", optional: true },
|
|
201
|
+
Tags: { type: "string", default: "", optional: true },
|
|
202
|
+
PreviewTime: { type: "int", default: 0 },
|
|
203
|
+
AudioFile: { type: "string", default: "", optional: true },
|
|
204
|
+
BackgroundFile: { type: "string", default: "", optional: true }
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/realm/schema/beatmapSet.ts
|
|
210
|
+
import Realm3 from "realm";
|
|
211
|
+
var BeatmapSet = class extends Realm3.Object {
|
|
212
|
+
ID;
|
|
213
|
+
OnlineID;
|
|
214
|
+
DateAdded;
|
|
215
|
+
DateSubmitted;
|
|
216
|
+
DateRanked;
|
|
217
|
+
Beatmaps;
|
|
218
|
+
Files;
|
|
219
|
+
Status;
|
|
220
|
+
DeletePending;
|
|
221
|
+
Hash;
|
|
222
|
+
Protected;
|
|
223
|
+
static schema = {
|
|
224
|
+
name: "BeatmapSet",
|
|
225
|
+
primaryKey: "ID",
|
|
226
|
+
properties: {
|
|
227
|
+
ID: { type: "uuid", default: "" },
|
|
228
|
+
OnlineID: { type: "int", default: -1 },
|
|
229
|
+
DateAdded: { type: "date" },
|
|
230
|
+
DateSubmitted: { type: "date", optional: true },
|
|
231
|
+
DateRanked: { type: "date", optional: true },
|
|
232
|
+
Beatmaps: { type: "list", objectType: "Beatmap", default: [] },
|
|
233
|
+
Files: { type: "list", objectType: "RealmNamedFileUsage", default: [] },
|
|
234
|
+
Status: { type: "int", default: -3 },
|
|
235
|
+
DeletePending: { type: "bool", default: false },
|
|
236
|
+
Hash: { type: "string", default: "", optional: true },
|
|
237
|
+
Protected: { type: "bool", default: false }
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/realm/schema/realmFile.ts
|
|
243
|
+
import Realm4 from "realm";
|
|
244
|
+
var RealmFile = class extends Realm4.Object {
|
|
245
|
+
Hash;
|
|
246
|
+
static schema = {
|
|
247
|
+
name: "File",
|
|
248
|
+
primaryKey: "Hash",
|
|
249
|
+
properties: {
|
|
250
|
+
Hash: { type: "string", default: "", optional: true }
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// src/realm/schema/realmUser.ts
|
|
256
|
+
import Realm5 from "realm";
|
|
257
|
+
var RealmUser = class extends Realm5.Object {
|
|
258
|
+
OnlineID;
|
|
259
|
+
Username;
|
|
260
|
+
CountryCode;
|
|
261
|
+
static embedded = true;
|
|
262
|
+
static schema = {
|
|
263
|
+
name: "RealmUser",
|
|
264
|
+
embedded: true,
|
|
265
|
+
properties: {
|
|
266
|
+
OnlineID: { type: "int", default: 1 },
|
|
267
|
+
Username: { type: "string", default: "", optional: true },
|
|
268
|
+
CountryCode: { type: "string", optional: true }
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// src/realm/schema/realmNamedFileUsage.ts
|
|
274
|
+
import Realm6 from "realm";
|
|
275
|
+
var RealmNamedFileUsage = class extends Realm6.Object {
|
|
276
|
+
File;
|
|
277
|
+
Filename;
|
|
278
|
+
static embedded = true;
|
|
279
|
+
static schema = {
|
|
280
|
+
name: "RealmNamedFileUsage",
|
|
281
|
+
embedded: true,
|
|
282
|
+
properties: {
|
|
283
|
+
File: "File",
|
|
284
|
+
Filename: { type: "string", optional: true }
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/realm/mod.ts
|
|
290
|
+
var getLazerDB = async (realmDBPath) => {
|
|
291
|
+
const realm = await Realm7.open({
|
|
292
|
+
schema: [
|
|
293
|
+
BeatmapSet,
|
|
294
|
+
RealmFile,
|
|
295
|
+
RealmNamedFileUsage,
|
|
296
|
+
Beatmap,
|
|
297
|
+
BeatmapMetadata,
|
|
298
|
+
RealmUser
|
|
299
|
+
],
|
|
300
|
+
path: realmDBPath,
|
|
301
|
+
schemaVersion: 36,
|
|
302
|
+
onMigration: (oldRealm, newRealm) => {
|
|
303
|
+
console.log(
|
|
304
|
+
`[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return realm;
|
|
309
|
+
};
|
|
310
|
+
var hashedFilePath = (hash) => {
|
|
311
|
+
const dataDir = getDataDir();
|
|
312
|
+
if (!dataDir)
|
|
313
|
+
return null;
|
|
314
|
+
return path2.join(
|
|
315
|
+
dataDir,
|
|
316
|
+
"osu",
|
|
317
|
+
"files",
|
|
318
|
+
hash.slice(0, 1),
|
|
319
|
+
hash.slice(0, 2),
|
|
320
|
+
hash
|
|
321
|
+
);
|
|
322
|
+
};
|
|
323
|
+
var getNamedFileHash = (fileName, beatmapSet) => {
|
|
324
|
+
const files = beatmapSet.Files;
|
|
325
|
+
for (const file of files) {
|
|
326
|
+
if (file.Filename == fileName)
|
|
327
|
+
return file.File.Hash;
|
|
328
|
+
}
|
|
329
|
+
return void 0;
|
|
330
|
+
};
|
|
331
|
+
export {
|
|
332
|
+
mod_exports2 as lazer,
|
|
333
|
+
mod_exports as utils
|
|
334
|
+
};
|
|
335
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/mod.ts","../src/realm/mod.ts","../src/realm/schema/beatmap.ts","../src/realm/schema/beatmapMetadata.ts","../src/realm/schema/beatmapSet.ts","../src/realm/schema/realmFile.ts","../src/realm/schema/realmUser.ts","../src/realm/schema/realmNamedFileUsage.ts"],"sourcesContent":["import path from \"node:path\";\nimport { copyFileSync, existsSync, mkdirSync } from \"node:fs\";\n\nexport function getDataDir(): string | null {\n switch (process.platform) {\n case \"linux\":\n case \"openbsd\":\n case \"freebsd\": {\n const xdg = process.env[\"XDG_DATA_HOME\"];\n if (xdg) return xdg;\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \".local\", \"share\");\n break;\n }\n\n case \"darwin\": {\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \"Library\", \"Application Support\");\n break;\n }\n\n case \"win32\":\n return process.env[\"LOCALAPPDATA\"] ?? null;\n }\n\n return null;\n}\n\nexport function getConfigDir(): string | null {\n switch (process.platform) {\n case \"openbsd\":\n case \"freebsd\":\n case \"linux\": {\n const xdg = process.env[\"XDG_CONFIG_HOME\"];\n if (xdg) return xdg;\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \".config\");\n break;\n }\n\n case \"darwin\": {\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \"Library\", \"Preferences\");\n break;\n }\n\n case \"win32\":\n return process.env[\"APPDATA\"] ?? null;\n }\n\n return null;\n}\n\n/**\n * Get Realm for the app, import to the config if it doesn't exist\n */\nexport function getRealmDBPath(\n appConfigDir: string,\n osuDataDir?: string,\n reload: boolean = false,\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(\n osuDataDir || getDataDir()! || \".\",\n \"osu\",\n \"client.realm\",\n );\n if (existsSync(osuDBPath)) {\n console.log(\n `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`,\n );\n mkdirSync(appConfigDir);\n copyFileSync(osuDBPath, localDBPath);\n return localDBPath;\n } else {\n console.log(`[getRealmDBPath]: ${osuDBPath} not found`);\n return null;\n }\n}\n","import Realm from \"realm\";\nimport path from \"node:path\";\nimport { getDataDir } from \"../utils/mod.js\";\nimport {\n Beatmap,\n BeatmapMetadata,\n BeatmapSet,\n RealmFile,\n RealmNamedFileUsage,\n RealmUser,\n} from \"./schema/mod.js\";\n\nexport const getLazerDB = async (realmDBPath: string) => {\n const realm = await Realm.open({\n schema: [\n BeatmapSet,\n RealmFile,\n RealmNamedFileUsage,\n Beatmap,\n BeatmapMetadata,\n RealmUser,\n ],\n path: realmDBPath,\n schemaVersion: 36,\n onMigration: (oldRealm, newRealm) => {\n console.log(\n `[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`,\n );\n },\n });\n\n return realm;\n};\n\nexport const hashedFilePath = (hash: string) => {\n const dataDir = getDataDir();\n if (!dataDir) return null;\n return path.join(\n dataDir,\n \"osu\",\n \"files\",\n hash.slice(0, 1),\n hash.slice(0, 2),\n hash,\n );\n};\n\nexport const getNamedFileHash = (fileName: string, beatmapSet: BeatmapSet) => {\n const files = beatmapSet.Files;\n for (const file of files) {\n if (file.Filename == fileName) return file.File.Hash;\n }\n return undefined;\n};\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { BeatmapMetadata } from \"./beatmapMetadata.js\";\n\nexport class Beatmap extends Realm.Object<Beatmap> {\n ID!: string;\n DifficultyName?: string;\n Ruleset!: any;\n Difficulty!: any;\n Metadata!: BeatmapMetadata;\n UserSettings!: any;\n BeatmapSet!: any;\n Status!: number;\n OnlineID!: number;\n Length!: number;\n BPM!: number;\n Hash?: string;\n StarRating!: number;\n MD5Hash?: string;\n OnlineMD5Hash?: string;\n LastLocalUpdate?: Date;\n LastOnlineUpdate?: Date;\n Hidden!: boolean;\n AudioLeadIn!: number;\n StackLeniency!: number;\n SpecialStyle!: boolean;\n LetterboxInBreaks!: boolean;\n WidescreenStoryboard!: boolean;\n EpilepsyWarning!: boolean;\n SamplesMatchPlaybackRate!: boolean;\n LastPlayed?: Date;\n DistanceSpacing!: number;\n BeatDivisor!: number;\n GridSize!: number;\n TimelineZoom!: number;\n EditorTimestamp?: number;\n CountdownOffset!: number;\n\n static schema: ObjectSchema = {\n name: \"Beatmap\",\n primaryKey: \"ID\",\n properties: {\n ID: { type: \"uuid\", default: \"\" },\n DifficultyName: { type: \"string\", default: \"\", optional: true },\n // Ruleset: { type: \"object\", objectType: \"Ruleset\", default: null },\n // Difficulty: { type: \"object\", objectType: \"BeatmapDifficulty\", default: null },\n Metadata: {\n type: \"object\",\n objectType: \"BeatmapMetadata\",\n default: null,\n },\n // UserSettings: { type: \"object\", objectType: \"BeatmapUserSettings\", default: null },\n BeatmapSet: { type: \"object\", objectType: \"BeatmapSet\", default: null },\n Status: { type: \"int\", default: -3 },\n OnlineID: { type: \"int\", default: -1 },\n Length: { type: \"double\", default: 0 },\n BPM: { type: \"double\", default: 0 },\n Hash: { type: \"string\", default: \"\", optional: true },\n StarRating: { type: \"double\", default: -1 },\n MD5Hash: { type: \"string\", default: \"\", optional: true },\n OnlineMD5Hash: {\n type: \"string\",\n default: \"\",\n optional: true,\n },\n LastLocalUpdate: { type: \"date\", optional: true },\n LastOnlineUpdate: { type: \"date\", optional: true },\n Hidden: { type: \"bool\", default: false },\n AudioLeadIn: { type: \"double\", default: 0 },\n StackLeniency: { type: \"float\", default: 0.7 },\n SpecialStyle: { type: \"bool\", default: false },\n LetterboxInBreaks: { type: \"bool\", default: false },\n WidescreenStoryboard: { type: \"bool\", default: false },\n EpilepsyWarning: { type: \"bool\", default: false },\n SamplesMatchPlaybackRate: { type: \"bool\", default: false },\n LastPlayed: { type: \"date\", optional: true },\n DistanceSpacing: { type: \"double\", default: 0 },\n BeatDivisor: { type: \"int\", default: 0 },\n GridSize: { type: \"int\", default: 0 },\n TimelineZoom: { type: \"double\", default: 0 },\n EditorTimestamp: { type: \"double\", optional: true },\n CountdownOffset: { type: \"int\", default: 0 },\n },\n };\n}\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { RealmUser } from \"./realmUser.js\";\n\nexport class BeatmapMetadata extends Realm.Object<BeatmapMetadata> {\n Title?: string;\n TitleUnicode?: string;\n Artist?: string;\n ArtistUnicode?: string;\n Author?: RealmUser;\n Source?: string;\n Tags?: string;\n PreviewTime?: number;\n AudioFile?: string;\n BackgroundFile?: string;\n\n static schema: ObjectSchema = {\n name: \"BeatmapMetadata\",\n properties: {\n Title: { type: \"string\", default: \"\", optional: true },\n TitleUnicode: { type: \"string\", default: \"\", optional: true },\n Artist: { type: \"string\", default: \"\", optional: true },\n ArtistUnicode: { type: \"string\", default: \"\", optional: true },\n Author: { type: \"object\", objectType: \"RealmUser\", default: null },\n Source: { type: \"string\", default: \"\", optional: true },\n Tags: { type: \"string\", default: \"\", optional: true },\n PreviewTime: { type: \"int\", default: 0 },\n AudioFile: { type: \"string\", default: \"\", optional: true },\n BackgroundFile: { type: \"string\", default: \"\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { Beatmap } from \"./beatmap.js\";\nimport { RealmNamedFileUsage } from \"./realmNamedFileUsage.js\";\n\nexport class BeatmapSet extends Realm.Object<BeatmapSet> {\n ID!: string;\n OnlineID!: number;\n DateAdded!: Date;\n DateSubmitted?: Date;\n DateRanked?: Date;\n Beatmaps!: Array<Beatmap>;\n Files!: Array<RealmNamedFileUsage>;\n Status!: number;\n DeletePending!: boolean;\n Hash?: string;\n Protected!: boolean;\n\n static schema: ObjectSchema = {\n name: \"BeatmapSet\",\n primaryKey: \"ID\",\n properties: {\n ID: { type: \"uuid\", default: \"\" },\n OnlineID: { type: \"int\", default: -1 },\n DateAdded: { type: \"date\" },\n DateSubmitted: { type: \"date\", optional: true },\n DateRanked: { type: \"date\", optional: true },\n Beatmaps: { type: \"list\", objectType: \"Beatmap\", default: [] },\n Files: { type: \"list\", objectType: \"RealmNamedFileUsage\", default: [] },\n Status: { type: \"int\", default: -3 },\n DeletePending: { type: \"bool\", default: false },\n Hash: { type: \"string\", default: \"\", optional: true },\n Protected: { type: \"bool\", default: false },\n },\n };\n}\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\n\nexport class RealmFile extends Realm.Object<RealmFile> {\n Hash?: string;\n\n static schema: ObjectSchema = {\n name: \"File\",\n primaryKey: \"Hash\",\n properties: {\n Hash: { type: \"string\", default: \"\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\n\nexport class RealmUser extends Realm.Object<RealmUser> {\n OnlineID!: number;\n Username?: string;\n CountryCode?: string;\n\n static embedded = true;\n\n static schema: ObjectSchema = {\n name: \"RealmUser\",\n embedded: true,\n properties: {\n OnlineID: { type: \"int\", default: 1 },\n Username: { type: \"string\", default: \"\", optional: true },\n CountryCode: { type: \"string\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { RealmFile } from \"./realmFile.js\";\n\nexport class RealmNamedFileUsage extends Realm.Object<RealmNamedFileUsage> {\n File!: RealmFile;\n Filename?: string;\n\n static embedded = true;\n\n static schema: ObjectSchema = {\n name: \"RealmNamedFileUsage\",\n embedded: true,\n properties: {\n File: \"File\",\n Filename: { type: \"string\", optional: true },\n },\n };\n}\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAO,UAAU;AACjB,SAAS,cAAc,YAAY,iBAAiB;AAE7C,SAAS,aAA4B;AAC1C,UAAQ,QAAQ,UAAU;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,WAAW;AACd,YAAM,MAAM,QAAQ,IAAI,eAAe;AACvC,UAAI;AAAK,eAAO;AAChB,YAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,UAAI;AAAM,eAAO,KAAK,KAAK,MAAM,UAAU,OAAO;AAClD;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,UAAI;AAAM,eAAO,KAAK,KAAK,MAAM,WAAW,qBAAqB;AACjE;AAAA,IACF;AAAA,IAEA,KAAK;AACH,aAAO,QAAQ,IAAI,cAAc,KAAK;AAAA,EAC1C;AAEA,SAAO;AACT;AAEO,SAAS,eAA8B;AAC5C,UAAQ,QAAQ,UAAU;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,YAAM,MAAM,QAAQ,IAAI,iBAAiB;AACzC,UAAI;AAAK,eAAO;AAChB,YAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,UAAI;AAAM,eAAO,KAAK,KAAK,MAAM,SAAS;AAC1C;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,UAAI;AAAM,eAAO,KAAK,KAAK,MAAM,WAAW,aAAa;AACzD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,aAAO,QAAQ,IAAI,SAAS,KAAK;AAAA,EACrC;AAEA,SAAO;AACT;AAKO,SAAS,eACd,cACA,YACA,SAAkB,OAClB;AACA,QAAM,cAAc,KAAK,KAAK,cAAc,cAAc;AAC1D,MAAI,CAAC,UAAU,WAAW,WAAW;AAAG,WAAO;AAE/C,QAAM,YAAY,KAAK;AAAA,IACrB,cAAc,WAAW,KAAM;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ;AAAA,MACN,qBAAqB,SAAS,wCAAwC,WAAW;AAAA,IACnF;AACA,cAAU,YAAY;AACtB,iBAAa,WAAW,WAAW;AACnC,WAAO;AAAA,EACT,OAAO;AACL,YAAQ,IAAI,qBAAqB,SAAS,YAAY;AACtD,WAAO;AAAA,EACT;AACF;;;AChFA,IAAAA,eAAA;AAAA,SAAAA,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAOC,YAAW;AAClB,OAAOC,WAAU;;;ACDjB,OAAO,WAAW;AAIX,IAAM,UAAN,cAAsB,MAAM,OAAgB;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,YAAY;AAAA,MACV,IAAI,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MAChC,gBAAgB,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA;AAAA;AAAA,MAG9D,UAAU;AAAA,QACR,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA;AAAA,MAEA,YAAY,EAAE,MAAM,UAAU,YAAY,cAAc,SAAS,KAAK;AAAA,MACtE,QAAQ,EAAE,MAAM,OAAO,SAAS,GAAG;AAAA,MACnC,UAAU,EAAE,MAAM,OAAO,SAAS,GAAG;AAAA,MACrC,QAAQ,EAAE,MAAM,UAAU,SAAS,EAAE;AAAA,MACrC,KAAK,EAAE,MAAM,UAAU,SAAS,EAAE;AAAA,MAClC,MAAM,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACpD,YAAY,EAAE,MAAM,UAAU,SAAS,GAAG;AAAA,MAC1C,SAAS,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACvD,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,MACA,iBAAiB,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,MAChD,kBAAkB,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,MACjD,QAAQ,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MACvC,aAAa,EAAE,MAAM,UAAU,SAAS,EAAE;AAAA,MAC1C,eAAe,EAAE,MAAM,SAAS,SAAS,IAAI;AAAA,MAC7C,cAAc,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MAC7C,mBAAmB,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MAClD,sBAAsB,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MACrD,iBAAiB,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MAChD,0BAA0B,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MACzD,YAAY,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,MAC3C,iBAAiB,EAAE,MAAM,UAAU,SAAS,EAAE;AAAA,MAC9C,aAAa,EAAE,MAAM,OAAO,SAAS,EAAE;AAAA,MACvC,UAAU,EAAE,MAAM,OAAO,SAAS,EAAE;AAAA,MACpC,cAAc,EAAE,MAAM,UAAU,SAAS,EAAE;AAAA,MAC3C,iBAAiB,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,MAClD,iBAAiB,EAAE,MAAM,OAAO,SAAS,EAAE;AAAA,IAC7C;AAAA,EACF;AACF;;;ACpFA,OAAOC,YAAW;AAIX,IAAM,kBAAN,cAA8BA,OAAM,OAAwB;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,YAAY;AAAA,MACV,OAAO,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACrD,cAAc,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MAC5D,QAAQ,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACtD,eAAe,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MAC7D,QAAQ,EAAE,MAAM,UAAU,YAAY,aAAa,SAAS,KAAK;AAAA,MACjE,QAAQ,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACtD,MAAM,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACpD,aAAa,EAAE,MAAM,OAAO,SAAS,EAAE;AAAA,MACvC,WAAW,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACzD,gBAAgB,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,IAChE;AAAA,EACF;AACF;;;AC/BA,OAAOC,YAAW;AAKX,IAAM,aAAN,cAAyBA,OAAM,OAAmB;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,YAAY;AAAA,MACV,IAAI,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MAChC,UAAU,EAAE,MAAM,OAAO,SAAS,GAAG;AAAA,MACrC,WAAW,EAAE,MAAM,OAAO;AAAA,MAC1B,eAAe,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,MAC9C,YAAY,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,MAC3C,UAAU,EAAE,MAAM,QAAQ,YAAY,WAAW,SAAS,CAAC,EAAE;AAAA,MAC7D,OAAO,EAAE,MAAM,QAAQ,YAAY,uBAAuB,SAAS,CAAC,EAAE;AAAA,MACtE,QAAQ,EAAE,MAAM,OAAO,SAAS,GAAG;AAAA,MACnC,eAAe,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,MAC9C,MAAM,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACpD,WAAW,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,IAC5C;AAAA,EACF;AACF;;;ACnCA,OAAOC,YAAW;AAGX,IAAM,YAAN,cAAwBA,OAAM,OAAkB;AAAA,EACrD;AAAA,EAEA,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,YAAY;AAAA,MACV,MAAM,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,IACtD;AAAA,EACF;AACF;;;ACbA,OAAOC,YAAW;AAGX,IAAM,YAAN,cAAwBA,OAAM,OAAkB;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EAEA,OAAO,WAAW;AAAA,EAElB,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,MACV,UAAU,EAAE,MAAM,OAAO,SAAS,EAAE;AAAA,MACpC,UAAU,EAAE,MAAM,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,MACxD,aAAa,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,IAChD;AAAA,EACF;AACF;;;ACnBA,OAAOC,YAAW;AAIX,IAAM,sBAAN,cAAkCA,OAAM,OAA4B;AAAA,EACzE;AAAA,EACA;AAAA,EAEA,OAAO,WAAW;AAAA,EAElB,OAAO,SAAuB;AAAA,IAC5B,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,IAC7C;AAAA,EACF;AACF;;;ANNO,IAAM,aAAa,OAAO,gBAAwB;AACvD,QAAM,QAAQ,MAAMC,OAAM,KAAK;AAAA,IAC7B,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,eAAe;AAAA,IACf,aAAa,CAAC,UAAU,aAAa;AACnC,cAAQ;AAAA,QACN,4BAA4B,SAAS,IAAI,MAAM,SAAS,aAAa,OAAO,SAAS,IAAI,MAAM,SAAS,aAAa;AAAA,MACvH;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEO,IAAM,iBAAiB,CAAC,SAAiB;AAC9C,QAAM,UAAU,WAAW;AAC3B,MAAI,CAAC;AAAS,WAAO;AACrB,SAAOC,MAAK;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,MAAM,GAAG,CAAC;AAAA,IACf,KAAK,MAAM,GAAG,CAAC;AAAA,IACf;AAAA,EACF;AACF;AAEO,IAAM,mBAAmB,CAAC,UAAkB,eAA2B;AAC5E,QAAM,QAAQ,WAAW;AACzB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,YAAY;AAAU,aAAO,KAAK,KAAK;AAAA,EAClD;AACA,SAAO;AACT;","names":["mod_exports","Realm","path","Realm","Realm","Realm","Realm","Realm","Realm","path"]}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// src/cli/main.ts
|
|
2
|
+
import path3 from "path";
|
|
3
|
+
import { existsSync as existsSync2 } from "fs";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import Realm8 from "realm";
|
|
6
|
+
import prompts from "prompts";
|
|
7
|
+
|
|
8
|
+
// src/realm/schema/beatmap.ts
|
|
9
|
+
import Realm from "realm";
|
|
10
|
+
var Beatmap = class extends Realm.Object {
|
|
11
|
+
ID;
|
|
12
|
+
DifficultyName;
|
|
13
|
+
Ruleset;
|
|
14
|
+
Difficulty;
|
|
15
|
+
Metadata;
|
|
16
|
+
UserSettings;
|
|
17
|
+
BeatmapSet;
|
|
18
|
+
Status;
|
|
19
|
+
OnlineID;
|
|
20
|
+
Length;
|
|
21
|
+
BPM;
|
|
22
|
+
Hash;
|
|
23
|
+
StarRating;
|
|
24
|
+
MD5Hash;
|
|
25
|
+
OnlineMD5Hash;
|
|
26
|
+
LastLocalUpdate;
|
|
27
|
+
LastOnlineUpdate;
|
|
28
|
+
Hidden;
|
|
29
|
+
AudioLeadIn;
|
|
30
|
+
StackLeniency;
|
|
31
|
+
SpecialStyle;
|
|
32
|
+
LetterboxInBreaks;
|
|
33
|
+
WidescreenStoryboard;
|
|
34
|
+
EpilepsyWarning;
|
|
35
|
+
SamplesMatchPlaybackRate;
|
|
36
|
+
LastPlayed;
|
|
37
|
+
DistanceSpacing;
|
|
38
|
+
BeatDivisor;
|
|
39
|
+
GridSize;
|
|
40
|
+
TimelineZoom;
|
|
41
|
+
EditorTimestamp;
|
|
42
|
+
CountdownOffset;
|
|
43
|
+
static schema = {
|
|
44
|
+
name: "Beatmap",
|
|
45
|
+
primaryKey: "ID",
|
|
46
|
+
properties: {
|
|
47
|
+
ID: { type: "uuid", default: "" },
|
|
48
|
+
DifficultyName: { type: "string", default: "", optional: true },
|
|
49
|
+
// Ruleset: { type: "object", objectType: "Ruleset", default: null },
|
|
50
|
+
// Difficulty: { type: "object", objectType: "BeatmapDifficulty", default: null },
|
|
51
|
+
Metadata: {
|
|
52
|
+
type: "object",
|
|
53
|
+
objectType: "BeatmapMetadata",
|
|
54
|
+
default: null
|
|
55
|
+
},
|
|
56
|
+
// UserSettings: { type: "object", objectType: "BeatmapUserSettings", default: null },
|
|
57
|
+
BeatmapSet: { type: "object", objectType: "BeatmapSet", default: null },
|
|
58
|
+
Status: { type: "int", default: -3 },
|
|
59
|
+
OnlineID: { type: "int", default: -1 },
|
|
60
|
+
Length: { type: "double", default: 0 },
|
|
61
|
+
BPM: { type: "double", default: 0 },
|
|
62
|
+
Hash: { type: "string", default: "", optional: true },
|
|
63
|
+
StarRating: { type: "double", default: -1 },
|
|
64
|
+
MD5Hash: { type: "string", default: "", optional: true },
|
|
65
|
+
OnlineMD5Hash: {
|
|
66
|
+
type: "string",
|
|
67
|
+
default: "",
|
|
68
|
+
optional: true
|
|
69
|
+
},
|
|
70
|
+
LastLocalUpdate: { type: "date", optional: true },
|
|
71
|
+
LastOnlineUpdate: { type: "date", optional: true },
|
|
72
|
+
Hidden: { type: "bool", default: false },
|
|
73
|
+
AudioLeadIn: { type: "double", default: 0 },
|
|
74
|
+
StackLeniency: { type: "float", default: 0.7 },
|
|
75
|
+
SpecialStyle: { type: "bool", default: false },
|
|
76
|
+
LetterboxInBreaks: { type: "bool", default: false },
|
|
77
|
+
WidescreenStoryboard: { type: "bool", default: false },
|
|
78
|
+
EpilepsyWarning: { type: "bool", default: false },
|
|
79
|
+
SamplesMatchPlaybackRate: { type: "bool", default: false },
|
|
80
|
+
LastPlayed: { type: "date", optional: true },
|
|
81
|
+
DistanceSpacing: { type: "double", default: 0 },
|
|
82
|
+
BeatDivisor: { type: "int", default: 0 },
|
|
83
|
+
GridSize: { type: "int", default: 0 },
|
|
84
|
+
TimelineZoom: { type: "double", default: 0 },
|
|
85
|
+
EditorTimestamp: { type: "double", optional: true },
|
|
86
|
+
CountdownOffset: { type: "int", default: 0 }
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/realm/schema/beatmapMetadata.ts
|
|
92
|
+
import Realm2 from "realm";
|
|
93
|
+
var BeatmapMetadata = class extends Realm2.Object {
|
|
94
|
+
Title;
|
|
95
|
+
TitleUnicode;
|
|
96
|
+
Artist;
|
|
97
|
+
ArtistUnicode;
|
|
98
|
+
Author;
|
|
99
|
+
Source;
|
|
100
|
+
Tags;
|
|
101
|
+
PreviewTime;
|
|
102
|
+
AudioFile;
|
|
103
|
+
BackgroundFile;
|
|
104
|
+
static schema = {
|
|
105
|
+
name: "BeatmapMetadata",
|
|
106
|
+
properties: {
|
|
107
|
+
Title: { type: "string", default: "", optional: true },
|
|
108
|
+
TitleUnicode: { type: "string", default: "", optional: true },
|
|
109
|
+
Artist: { type: "string", default: "", optional: true },
|
|
110
|
+
ArtistUnicode: { type: "string", default: "", optional: true },
|
|
111
|
+
Author: { type: "object", objectType: "RealmUser", default: null },
|
|
112
|
+
Source: { type: "string", default: "", optional: true },
|
|
113
|
+
Tags: { type: "string", default: "", optional: true },
|
|
114
|
+
PreviewTime: { type: "int", default: 0 },
|
|
115
|
+
AudioFile: { type: "string", default: "", optional: true },
|
|
116
|
+
BackgroundFile: { type: "string", default: "", optional: true }
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/realm/schema/beatmapSet.ts
|
|
122
|
+
import Realm3 from "realm";
|
|
123
|
+
var BeatmapSet = class extends Realm3.Object {
|
|
124
|
+
ID;
|
|
125
|
+
OnlineID;
|
|
126
|
+
DateAdded;
|
|
127
|
+
DateSubmitted;
|
|
128
|
+
DateRanked;
|
|
129
|
+
Beatmaps;
|
|
130
|
+
Files;
|
|
131
|
+
Status;
|
|
132
|
+
DeletePending;
|
|
133
|
+
Hash;
|
|
134
|
+
Protected;
|
|
135
|
+
static schema = {
|
|
136
|
+
name: "BeatmapSet",
|
|
137
|
+
primaryKey: "ID",
|
|
138
|
+
properties: {
|
|
139
|
+
ID: { type: "uuid", default: "" },
|
|
140
|
+
OnlineID: { type: "int", default: -1 },
|
|
141
|
+
DateAdded: { type: "date" },
|
|
142
|
+
DateSubmitted: { type: "date", optional: true },
|
|
143
|
+
DateRanked: { type: "date", optional: true },
|
|
144
|
+
Beatmaps: { type: "list", objectType: "Beatmap", default: [] },
|
|
145
|
+
Files: { type: "list", objectType: "RealmNamedFileUsage", default: [] },
|
|
146
|
+
Status: { type: "int", default: -3 },
|
|
147
|
+
DeletePending: { type: "bool", default: false },
|
|
148
|
+
Hash: { type: "string", default: "", optional: true },
|
|
149
|
+
Protected: { type: "bool", default: false }
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/realm/schema/realmFile.ts
|
|
155
|
+
import Realm4 from "realm";
|
|
156
|
+
var RealmFile = class extends Realm4.Object {
|
|
157
|
+
Hash;
|
|
158
|
+
static schema = {
|
|
159
|
+
name: "File",
|
|
160
|
+
primaryKey: "Hash",
|
|
161
|
+
properties: {
|
|
162
|
+
Hash: { type: "string", default: "", optional: true }
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// src/realm/schema/realmUser.ts
|
|
168
|
+
import Realm5 from "realm";
|
|
169
|
+
var RealmUser = class extends Realm5.Object {
|
|
170
|
+
OnlineID;
|
|
171
|
+
Username;
|
|
172
|
+
CountryCode;
|
|
173
|
+
static embedded = true;
|
|
174
|
+
static schema = {
|
|
175
|
+
name: "RealmUser",
|
|
176
|
+
embedded: true,
|
|
177
|
+
properties: {
|
|
178
|
+
OnlineID: { type: "int", default: 1 },
|
|
179
|
+
Username: { type: "string", default: "", optional: true },
|
|
180
|
+
CountryCode: { type: "string", optional: true }
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// src/realm/schema/realmNamedFileUsage.ts
|
|
186
|
+
import Realm6 from "realm";
|
|
187
|
+
var RealmNamedFileUsage = class extends Realm6.Object {
|
|
188
|
+
File;
|
|
189
|
+
Filename;
|
|
190
|
+
static embedded = true;
|
|
191
|
+
static schema = {
|
|
192
|
+
name: "RealmNamedFileUsage",
|
|
193
|
+
embedded: true,
|
|
194
|
+
properties: {
|
|
195
|
+
File: "File",
|
|
196
|
+
Filename: { type: "string", optional: true }
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/utils/mod.ts
|
|
202
|
+
import path from "path";
|
|
203
|
+
import { copyFileSync, existsSync, mkdirSync } from "fs";
|
|
204
|
+
function getDataDir() {
|
|
205
|
+
switch (process.platform) {
|
|
206
|
+
case "linux":
|
|
207
|
+
case "openbsd":
|
|
208
|
+
case "freebsd": {
|
|
209
|
+
const xdg = process.env["XDG_DATA_HOME"];
|
|
210
|
+
if (xdg)
|
|
211
|
+
return xdg;
|
|
212
|
+
const home = process.env["HOME"];
|
|
213
|
+
if (home)
|
|
214
|
+
return path.join(home, ".local", "share");
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case "darwin": {
|
|
218
|
+
const home = process.env["HOME"];
|
|
219
|
+
if (home)
|
|
220
|
+
return path.join(home, "Library", "Application Support");
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case "win32":
|
|
224
|
+
return process.env["LOCALAPPDATA"] ?? null;
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
function getConfigDir() {
|
|
229
|
+
switch (process.platform) {
|
|
230
|
+
case "openbsd":
|
|
231
|
+
case "freebsd":
|
|
232
|
+
case "linux": {
|
|
233
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
234
|
+
if (xdg)
|
|
235
|
+
return xdg;
|
|
236
|
+
const home = process.env["HOME"];
|
|
237
|
+
if (home)
|
|
238
|
+
return path.join(home, ".config");
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
case "darwin": {
|
|
242
|
+
const home = process.env["HOME"];
|
|
243
|
+
if (home)
|
|
244
|
+
return path.join(home, "Library", "Preferences");
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
case "win32":
|
|
248
|
+
return process.env["APPDATA"] ?? null;
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
function getRealmDBPath(appConfigDir, osuDataDir, reload = false) {
|
|
253
|
+
const localDBPath = path.join(appConfigDir, "client.realm");
|
|
254
|
+
if (!reload && existsSync(localDBPath))
|
|
255
|
+
return localDBPath;
|
|
256
|
+
const osuDBPath = path.join(
|
|
257
|
+
osuDataDir || getDataDir() || ".",
|
|
258
|
+
"osu",
|
|
259
|
+
"client.realm"
|
|
260
|
+
);
|
|
261
|
+
if (existsSync(osuDBPath)) {
|
|
262
|
+
console.log(
|
|
263
|
+
`[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`
|
|
264
|
+
);
|
|
265
|
+
mkdirSync(appConfigDir);
|
|
266
|
+
copyFileSync(osuDBPath, localDBPath);
|
|
267
|
+
return localDBPath;
|
|
268
|
+
} else {
|
|
269
|
+
console.log(`[getRealmDBPath]: ${osuDBPath} not found`);
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/realm/mod.ts
|
|
275
|
+
import Realm7 from "realm";
|
|
276
|
+
import path2 from "path";
|
|
277
|
+
var getLazerDB = async (realmDBPath) => {
|
|
278
|
+
const realm = await Realm7.open({
|
|
279
|
+
schema: [
|
|
280
|
+
BeatmapSet,
|
|
281
|
+
RealmFile,
|
|
282
|
+
RealmNamedFileUsage,
|
|
283
|
+
Beatmap,
|
|
284
|
+
BeatmapMetadata,
|
|
285
|
+
RealmUser
|
|
286
|
+
],
|
|
287
|
+
path: realmDBPath,
|
|
288
|
+
schemaVersion: 36,
|
|
289
|
+
onMigration: (oldRealm, newRealm) => {
|
|
290
|
+
console.log(
|
|
291
|
+
`[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
return realm;
|
|
296
|
+
};
|
|
297
|
+
var hashedFilePath = (hash) => {
|
|
298
|
+
const dataDir = getDataDir();
|
|
299
|
+
if (!dataDir)
|
|
300
|
+
return null;
|
|
301
|
+
return path2.join(
|
|
302
|
+
dataDir,
|
|
303
|
+
"osu",
|
|
304
|
+
"files",
|
|
305
|
+
hash.slice(0, 1),
|
|
306
|
+
hash.slice(0, 2),
|
|
307
|
+
hash
|
|
308
|
+
);
|
|
309
|
+
};
|
|
310
|
+
var getNamedFileHash = (fileName, beatmapSet) => {
|
|
311
|
+
const files = beatmapSet.Files;
|
|
312
|
+
for (const file of files) {
|
|
313
|
+
if (file.Filename == fileName)
|
|
314
|
+
return file.File.Hash;
|
|
315
|
+
}
|
|
316
|
+
return void 0;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// src/cli/main.ts
|
|
320
|
+
async function main() {
|
|
321
|
+
console.log("[INFO] OSU!list");
|
|
322
|
+
const realmDBPath = getRealmDBPath(
|
|
323
|
+
path3.join(getConfigDir() || ".", "osu-play")
|
|
324
|
+
);
|
|
325
|
+
if (realmDBPath == null) {
|
|
326
|
+
console.log("[ERROR] Realm DB not found");
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
const currentSchema = Realm8.schemaVersion(realmDBPath);
|
|
330
|
+
console.log(`currentSchema: ${currentSchema}`);
|
|
331
|
+
Realm8.flags.ALLOW_CLEAR_TEST_STATE = true;
|
|
332
|
+
const realm = await getLazerDB(realmDBPath);
|
|
333
|
+
console.log(`realm.isClosed: ${realm.isClosed}`);
|
|
334
|
+
const beatmapSets = realm.objects(BeatmapSet);
|
|
335
|
+
console.log(`beatmaps: ${beatmapSets.length}`);
|
|
336
|
+
const selectedBeatmapSet = (await prompts({
|
|
337
|
+
type: "autocomplete",
|
|
338
|
+
name: "beatmapSet",
|
|
339
|
+
message: "Which map do you want to play:",
|
|
340
|
+
choices: beatmapSets.map((beatmapSet) => {
|
|
341
|
+
const meta = beatmapSet.Beatmaps[0].Metadata;
|
|
342
|
+
return {
|
|
343
|
+
title: `${meta.Title} : ${meta.Artist} - ${meta.TitleUnicode} : ${meta.ArtistUnicode}`,
|
|
344
|
+
value: beatmapSet
|
|
345
|
+
};
|
|
346
|
+
})
|
|
347
|
+
})).beatmapSet;
|
|
348
|
+
console.log(`Map : ${selectedBeatmapSet.Beatmaps[0].Metadata.Title}`);
|
|
349
|
+
const fileName = selectedBeatmapSet.Beatmaps[0].Metadata.AudioFile;
|
|
350
|
+
const fileHash = fileName ? getNamedFileHash(fileName, selectedBeatmapSet) : void 0;
|
|
351
|
+
const filePath = fileHash ? hashedFilePath(fileHash) : void 0;
|
|
352
|
+
if (filePath && existsSync2(filePath)) {
|
|
353
|
+
console.log(`File exists: ${filePath}`);
|
|
354
|
+
} else {
|
|
355
|
+
console.log(`File does not exist: ${filePath}`);
|
|
356
|
+
}
|
|
357
|
+
console.log(`Playing file ${selectedBeatmapSet.Beatmaps[0].Metadata.Title}`);
|
|
358
|
+
filePath && execSync(`exo-open ${filePath}`);
|
|
359
|
+
realm.close();
|
|
360
|
+
console.log(`realm.isClosed: ${realm.isClosed}`);
|
|
361
|
+
}
|
|
362
|
+
export {
|
|
363
|
+
main
|
|
364
|
+
};
|
|
365
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/main.ts","../../../src/realm/schema/beatmap.ts","../../../src/realm/schema/beatmapMetadata.ts","../../../src/realm/schema/beatmapSet.ts","../../../src/realm/schema/realmFile.ts","../../../src/realm/schema/realmUser.ts","../../../src/realm/schema/realmNamedFileUsage.ts","../../../src/utils/mod.ts","../../../src/realm/mod.ts"],"sourcesContent":["import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\n\nimport Realm from \"realm\";\nimport prompts from \"prompts\";\nimport { BeatmapSet } from \"../realm/schema/mod.js\";\nimport { getConfigDir, getRealmDBPath } from \"../utils/mod.js\";\nimport { getLazerDB, getNamedFileHash, hashedFilePath } from \"../realm/mod.js\";\n\nexport async function main() {\n console.log(\"[INFO] OSU!list\");\n\n const realmDBPath = getRealmDBPath(\n path.join(getConfigDir() || \".\", \"osu-play\"),\n );\n\n if (realmDBPath == null) {\n console.log(\"[ERROR] Realm DB not found\");\n process.exit(1);\n }\n\n const currentSchema = Realm.schemaVersion(realmDBPath);\n console.log(`currentSchema: ${currentSchema}`);\n\n Realm.flags.ALLOW_CLEAR_TEST_STATE = true;\n\n const realm: Realm = await getLazerDB(realmDBPath);\n\n console.log(`realm.isClosed: ${realm.isClosed}`);\n\n const beatmapSets = realm.objects(BeatmapSet);\n\n console.log(`beatmaps: ${beatmapSets.length}`);\n\n // Get the map index from the user\n const selectedBeatmapSet = (\n await prompts({\n type: \"autocomplete\",\n name: \"beatmapSet\",\n message: \"Which map do you want to play:\",\n choices: beatmapSets.map((beatmapSet) => {\n const meta = beatmapSet.Beatmaps[0].Metadata;\n return {\n title:\n `${meta.Title} : ${meta.Artist} - ${meta.TitleUnicode} : ${meta.ArtistUnicode}`,\n value: beatmapSet,\n };\n }),\n })\n ).beatmapSet;\n\n console.log(`Map : ${selectedBeatmapSet.Beatmaps[0].Metadata.Title}`);\n const fileName = selectedBeatmapSet.Beatmaps[0].Metadata.AudioFile;\n const fileHash = fileName\n ? getNamedFileHash(fileName, selectedBeatmapSet)\n : undefined;\n const filePath = fileHash ? hashedFilePath(fileHash) : undefined;\n if (filePath && existsSync(filePath)) {\n console.log(`File exists: ${filePath}`);\n } else {\n console.log(`File does not exist: ${filePath}`);\n }\n\n // Open file using exo-open.\n console.log(`Playing file ${selectedBeatmapSet.Beatmaps[0].Metadata.Title}`);\n filePath && execSync(`exo-open ${filePath}`);\n\n realm.close();\n console.log(`realm.isClosed: ${realm.isClosed}`);\n\n // Realm.clearTestState();\n}\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { BeatmapMetadata } from \"./beatmapMetadata.js\";\n\nexport class Beatmap extends Realm.Object<Beatmap> {\n ID!: string;\n DifficultyName?: string;\n Ruleset!: any;\n Difficulty!: any;\n Metadata!: BeatmapMetadata;\n UserSettings!: any;\n BeatmapSet!: any;\n Status!: number;\n OnlineID!: number;\n Length!: number;\n BPM!: number;\n Hash?: string;\n StarRating!: number;\n MD5Hash?: string;\n OnlineMD5Hash?: string;\n LastLocalUpdate?: Date;\n LastOnlineUpdate?: Date;\n Hidden!: boolean;\n AudioLeadIn!: number;\n StackLeniency!: number;\n SpecialStyle!: boolean;\n LetterboxInBreaks!: boolean;\n WidescreenStoryboard!: boolean;\n EpilepsyWarning!: boolean;\n SamplesMatchPlaybackRate!: boolean;\n LastPlayed?: Date;\n DistanceSpacing!: number;\n BeatDivisor!: number;\n GridSize!: number;\n TimelineZoom!: number;\n EditorTimestamp?: number;\n CountdownOffset!: number;\n\n static schema: ObjectSchema = {\n name: \"Beatmap\",\n primaryKey: \"ID\",\n properties: {\n ID: { type: \"uuid\", default: \"\" },\n DifficultyName: { type: \"string\", default: \"\", optional: true },\n // Ruleset: { type: \"object\", objectType: \"Ruleset\", default: null },\n // Difficulty: { type: \"object\", objectType: \"BeatmapDifficulty\", default: null },\n Metadata: {\n type: \"object\",\n objectType: \"BeatmapMetadata\",\n default: null,\n },\n // UserSettings: { type: \"object\", objectType: \"BeatmapUserSettings\", default: null },\n BeatmapSet: { type: \"object\", objectType: \"BeatmapSet\", default: null },\n Status: { type: \"int\", default: -3 },\n OnlineID: { type: \"int\", default: -1 },\n Length: { type: \"double\", default: 0 },\n BPM: { type: \"double\", default: 0 },\n Hash: { type: \"string\", default: \"\", optional: true },\n StarRating: { type: \"double\", default: -1 },\n MD5Hash: { type: \"string\", default: \"\", optional: true },\n OnlineMD5Hash: {\n type: \"string\",\n default: \"\",\n optional: true,\n },\n LastLocalUpdate: { type: \"date\", optional: true },\n LastOnlineUpdate: { type: \"date\", optional: true },\n Hidden: { type: \"bool\", default: false },\n AudioLeadIn: { type: \"double\", default: 0 },\n StackLeniency: { type: \"float\", default: 0.7 },\n SpecialStyle: { type: \"bool\", default: false },\n LetterboxInBreaks: { type: \"bool\", default: false },\n WidescreenStoryboard: { type: \"bool\", default: false },\n EpilepsyWarning: { type: \"bool\", default: false },\n SamplesMatchPlaybackRate: { type: \"bool\", default: false },\n LastPlayed: { type: \"date\", optional: true },\n DistanceSpacing: { type: \"double\", default: 0 },\n BeatDivisor: { type: \"int\", default: 0 },\n GridSize: { type: \"int\", default: 0 },\n TimelineZoom: { type: \"double\", default: 0 },\n EditorTimestamp: { type: \"double\", optional: true },\n CountdownOffset: { type: \"int\", default: 0 },\n },\n };\n}\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { RealmUser } from \"./realmUser.js\";\n\nexport class BeatmapMetadata extends Realm.Object<BeatmapMetadata> {\n Title?: string;\n TitleUnicode?: string;\n Artist?: string;\n ArtistUnicode?: string;\n Author?: RealmUser;\n Source?: string;\n Tags?: string;\n PreviewTime?: number;\n AudioFile?: string;\n BackgroundFile?: string;\n\n static schema: ObjectSchema = {\n name: \"BeatmapMetadata\",\n properties: {\n Title: { type: \"string\", default: \"\", optional: true },\n TitleUnicode: { type: \"string\", default: \"\", optional: true },\n Artist: { type: \"string\", default: \"\", optional: true },\n ArtistUnicode: { type: \"string\", default: \"\", optional: true },\n Author: { type: \"object\", objectType: \"RealmUser\", default: null },\n Source: { type: \"string\", default: \"\", optional: true },\n Tags: { type: \"string\", default: \"\", optional: true },\n PreviewTime: { type: \"int\", default: 0 },\n AudioFile: { type: \"string\", default: \"\", optional: true },\n BackgroundFile: { type: \"string\", default: \"\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { Beatmap } from \"./beatmap.js\";\nimport { RealmNamedFileUsage } from \"./realmNamedFileUsage.js\";\n\nexport class BeatmapSet extends Realm.Object<BeatmapSet> {\n ID!: string;\n OnlineID!: number;\n DateAdded!: Date;\n DateSubmitted?: Date;\n DateRanked?: Date;\n Beatmaps!: Array<Beatmap>;\n Files!: Array<RealmNamedFileUsage>;\n Status!: number;\n DeletePending!: boolean;\n Hash?: string;\n Protected!: boolean;\n\n static schema: ObjectSchema = {\n name: \"BeatmapSet\",\n primaryKey: \"ID\",\n properties: {\n ID: { type: \"uuid\", default: \"\" },\n OnlineID: { type: \"int\", default: -1 },\n DateAdded: { type: \"date\" },\n DateSubmitted: { type: \"date\", optional: true },\n DateRanked: { type: \"date\", optional: true },\n Beatmaps: { type: \"list\", objectType: \"Beatmap\", default: [] },\n Files: { type: \"list\", objectType: \"RealmNamedFileUsage\", default: [] },\n Status: { type: \"int\", default: -3 },\n DeletePending: { type: \"bool\", default: false },\n Hash: { type: \"string\", default: \"\", optional: true },\n Protected: { type: \"bool\", default: false },\n },\n };\n}\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\n\nexport class RealmFile extends Realm.Object<RealmFile> {\n Hash?: string;\n\n static schema: ObjectSchema = {\n name: \"File\",\n primaryKey: \"Hash\",\n properties: {\n Hash: { type: \"string\", default: \"\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\n\nexport class RealmUser extends Realm.Object<RealmUser> {\n OnlineID!: number;\n Username?: string;\n CountryCode?: string;\n\n static embedded = true;\n\n static schema: ObjectSchema = {\n name: \"RealmUser\",\n embedded: true,\n properties: {\n OnlineID: { type: \"int\", default: 1 },\n Username: { type: \"string\", default: \"\", optional: true },\n CountryCode: { type: \"string\", optional: true },\n },\n };\n}\n\n","import Realm from \"realm\";\nimport type { ObjectSchema } from \"realm\";\nimport { RealmFile } from \"./realmFile.js\";\n\nexport class RealmNamedFileUsage extends Realm.Object<RealmNamedFileUsage> {\n File!: RealmFile;\n Filename?: string;\n\n static embedded = true;\n\n static schema: ObjectSchema = {\n name: \"RealmNamedFileUsage\",\n embedded: true,\n properties: {\n File: \"File\",\n Filename: { type: \"string\", optional: true },\n },\n };\n}\n","import path from \"node:path\";\nimport { copyFileSync, existsSync, mkdirSync } from \"node:fs\";\n\nexport function getDataDir(): string | null {\n switch (process.platform) {\n case \"linux\":\n case \"openbsd\":\n case \"freebsd\": {\n const xdg = process.env[\"XDG_DATA_HOME\"];\n if (xdg) return xdg;\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \".local\", \"share\");\n break;\n }\n\n case \"darwin\": {\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \"Library\", \"Application Support\");\n break;\n }\n\n case \"win32\":\n return process.env[\"LOCALAPPDATA\"] ?? null;\n }\n\n return null;\n}\n\nexport function getConfigDir(): string | null {\n switch (process.platform) {\n case \"openbsd\":\n case \"freebsd\":\n case \"linux\": {\n const xdg = process.env[\"XDG_CONFIG_HOME\"];\n if (xdg) return xdg;\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \".config\");\n break;\n }\n\n case \"darwin\": {\n const home = process.env[\"HOME\"];\n if (home) return path.join(home, \"Library\", \"Preferences\");\n break;\n }\n\n case \"win32\":\n return process.env[\"APPDATA\"] ?? null;\n }\n\n return null;\n}\n\n/**\n * Get Realm for the app, import to the config if it doesn't exist\n */\nexport function getRealmDBPath(\n appConfigDir: string,\n osuDataDir?: string,\n reload: boolean = false,\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(\n osuDataDir || getDataDir()! || \".\",\n \"osu\",\n \"client.realm\",\n );\n if (existsSync(osuDBPath)) {\n console.log(\n `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`,\n );\n mkdirSync(appConfigDir);\n copyFileSync(osuDBPath, localDBPath);\n return localDBPath;\n } else {\n console.log(`[getRealmDBPath]: ${osuDBPath} not found`);\n return null;\n }\n}\n","import Realm from \"realm\";\nimport path from \"node:path\";\nimport { getDataDir } from \"../utils/mod.js\";\nimport {\n Beatmap,\n BeatmapMetadata,\n BeatmapSet,\n RealmFile,\n RealmNamedFileUsage,\n RealmUser,\n} from \"./schema/mod.js\";\n\nexport const getLazerDB = async (realmDBPath: string) => {\n const realm = await Realm.open({\n schema: [\n BeatmapSet,\n RealmFile,\n RealmNamedFileUsage,\n Beatmap,\n BeatmapMetadata,\n RealmUser,\n ],\n path: realmDBPath,\n schemaVersion: 36,\n onMigration: (oldRealm, newRealm) => {\n console.log(\n `[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`,\n );\n },\n });\n\n return realm;\n};\n\nexport const hashedFilePath = (hash: string) => {\n const dataDir = getDataDir();\n if (!dataDir) return null;\n return path.join(\n dataDir,\n \"osu\",\n \"files\",\n hash.slice(0, 1),\n hash.slice(0, 2),\n hash,\n );\n};\n\nexport const getNamedFileHash = (fileName: string, beatmapSet: BeatmapSet) => {\n const files = beatmapSet.Files;\n for (const file of files) {\n if (file.Filename == fileName) return file.File.Hash;\n }\n return undefined;\n};\n"],"mappings":"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","names":["path","existsSync","Realm","Realm","Realm","Realm","Realm","Realm","Realm","path","Realm","path","path","Realm","existsSync"]}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src/mod.js";
|
package/package.json
CHANGED
|
@@ -1,23 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osu-play",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Play
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Play music from your osu!lazer beatmaps from the terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/osu-play.js",
|
|
7
|
+
"module": "index.ts",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"dist",
|
|
12
|
+
"src",
|
|
13
|
+
"index.ts",
|
|
14
|
+
"package.json",
|
|
15
|
+
"README.md",
|
|
16
|
+
"tsconfig.json",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
7
19
|
"bin": {
|
|
8
20
|
"osu-play": "./bin/osu-play.js"
|
|
9
21
|
},
|
|
10
22
|
"scripts": {
|
|
11
23
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
-
"
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"start": "./bin/osu-play.js",
|
|
26
|
+
"dev:start": "tsc && ./bin/osu-play.js",
|
|
13
27
|
"clean": "rm -rf dist"
|
|
14
28
|
},
|
|
15
29
|
"author": "KorigamiK",
|
|
16
30
|
"license": "MIT",
|
|
17
31
|
"devDependencies": {
|
|
18
|
-
"
|
|
32
|
+
"@types/node": "^20.8.9",
|
|
19
33
|
"@types/prompts": "^2.4.7",
|
|
20
|
-
"
|
|
34
|
+
"tsup": "^7.2.0",
|
|
35
|
+
"typescript": "^5.2.2"
|
|
21
36
|
},
|
|
22
37
|
"dependencies": {
|
|
23
38
|
"prompts": "^2.4.2",
|
|
@@ -4,11 +4,11 @@ import { execSync } from "node:child_process";
|
|
|
4
4
|
|
|
5
5
|
import Realm from "realm";
|
|
6
6
|
import prompts from "prompts";
|
|
7
|
-
import { BeatmapSet } from "
|
|
8
|
-
import { getConfigDir, getRealmDBPath } from "
|
|
9
|
-
import { getLazerDB, getNamedFileHash, hashedFilePath } from "
|
|
7
|
+
import { BeatmapSet } from "../realm/schema/mod.js";
|
|
8
|
+
import { getConfigDir, getRealmDBPath } from "../utils/mod.js";
|
|
9
|
+
import { getLazerDB, getNamedFileHash, hashedFilePath } from "../realm/mod.js";
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export async function main() {
|
|
12
12
|
console.log("[INFO] OSU!list");
|
|
13
13
|
|
|
14
14
|
const realmDBPath = getRealmDBPath(
|
|
@@ -42,7 +42,8 @@ export default async function main() {
|
|
|
42
42
|
choices: beatmapSets.map((beatmapSet) => {
|
|
43
43
|
const meta = beatmapSet.Beatmaps[0].Metadata;
|
|
44
44
|
return {
|
|
45
|
-
title:
|
|
45
|
+
title:
|
|
46
|
+
`${meta.Title} : ${meta.Artist} - ${meta.TitleUnicode} : ${meta.ArtistUnicode}`,
|
|
46
47
|
value: beatmapSet,
|
|
47
48
|
};
|
|
48
49
|
}),
|
package/src/mod.ts
ADDED
package/tsconfig.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
+
"exclude": [
|
|
3
|
+
"node_modules"
|
|
4
|
+
],
|
|
5
|
+
"include": [
|
|
6
|
+
"./src/**/*"
|
|
7
|
+
],
|
|
2
8
|
"compilerOptions": {
|
|
3
9
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
|
4
10
|
/* Projects */
|
|
@@ -100,6 +106,4 @@
|
|
|
100
106
|
/* Completeness */
|
|
101
107
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
|
102
108
|
},
|
|
103
|
-
|
|
104
|
-
"include": ["./src/**/*"]
|
|
105
|
-
}
|
|
109
|
+
}
|