osu-play 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -10
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/cli/main.d.ts +4 -0
- package/dist/src/cli/main.js +19 -3
- package/dist/src/cli/main.js.map +1 -1
- package/package.json +9 -9
- package/src/cli/main.ts +19 -2
- package/src/realm/mod.ts +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# osu!play
|
|
2
2
|
|
|
3
|
-
Listen to your favourite [
|
|
3
|
+
Listen to your favourite [osu!lazer](https://lazer.ppy.sh) beatmaps as a spotify playlist from the terminal
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -28,8 +28,6 @@ pnpm i -g osu-play # using pnpm
|
|
|
28
28
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
|
-
### Cli
|
|
32
|
-
|
|
33
31
|
The `osu-play` command can be used with the following options:
|
|
34
32
|
```sh
|
|
35
33
|
➜ korigamik git:(main) ✗ osu-play --help
|
|
@@ -37,12 +35,15 @@ Play music from your osu!lazer beatmaps from the terminal
|
|
|
37
35
|
Usage: osu-play [options]
|
|
38
36
|
|
|
39
37
|
Options:
|
|
40
|
-
--help
|
|
41
|
-
--version
|
|
42
|
-
-r, --reload
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
38
|
+
--help Show help [boolean]
|
|
39
|
+
--version Show version number [boolean]
|
|
40
|
+
-r, --reload Reload lazer database [boolean] [default: false]
|
|
41
|
+
--exportPlaylist Export playlist to a file [string]
|
|
42
|
+
-d, --osuDataDir Osu!lazer data directory
|
|
43
|
+
[string] [default: "/home/origami/.local/share/osu"]
|
|
44
|
+
-c, --configDir Config directory
|
|
45
|
+
[string] [default: "/home/origami/.config/osu-play"]
|
|
46
|
+
-l, --loop Loop the playlist on end [boolean] [default: false]
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
This package can be used as a library or as a cli application. To use the lazer
|
package/dist/index.js
CHANGED
|
@@ -292,7 +292,7 @@ var getLazerDB = async (realmDBPath) => {
|
|
|
292
292
|
RealmUser
|
|
293
293
|
],
|
|
294
294
|
path: realmDBPath,
|
|
295
|
-
schemaVersion:
|
|
295
|
+
schemaVersion: 41,
|
|
296
296
|
onMigration: (oldRealm, newRealm) => {
|
|
297
297
|
console.log(
|
|
298
298
|
`[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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 | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\n}\n\nexport function getConfigDir(): string | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\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 options: {\n osuDataDir: string;\n reload: boolean;\n } = { reload: false, osuDataDir: getDataDir() || \".\" },\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!options.reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(options.osuDataDir, \"client.realm\");\n if (existsSync(osuDBPath)) {\n console.log( `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`);\n mkdirSync(appConfigDir, { recursive: true });\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":"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","names":["mod_exports","Realm","path","Realm","Realm","Realm","Realm","Realm","Realm","path"]}
|
|
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 | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\n}\n\nexport function getConfigDir(): string | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\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 options: {\n osuDataDir: string;\n reload: boolean;\n } = { reload: false, osuDataDir: getDataDir() || \".\" },\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!options.reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(options.osuDataDir, \"client.realm\");\n if (existsSync(osuDBPath)) {\n console.log( `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`);\n mkdirSync(appConfigDir, { recursive: true });\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: 41,\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":"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","names":["mod_exports","Realm","path","Realm","Realm","Realm","Realm","Realm","Realm","path"]}
|
package/dist/src/cli/main.d.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
declare function getArgs(): {
|
|
2
2
|
[x: string]: unknown;
|
|
3
3
|
reload: boolean;
|
|
4
|
+
exportPlaylist: string | undefined;
|
|
4
5
|
osuDataDir: string;
|
|
5
6
|
configDir: string;
|
|
6
7
|
loop: boolean;
|
|
8
|
+
help: boolean | undefined;
|
|
7
9
|
_: (string | number)[];
|
|
8
10
|
$0: string;
|
|
9
11
|
} | Promise<{
|
|
10
12
|
[x: string]: unknown;
|
|
11
13
|
reload: boolean;
|
|
14
|
+
exportPlaylist: string | undefined;
|
|
12
15
|
osuDataDir: string;
|
|
13
16
|
configDir: string;
|
|
14
17
|
loop: boolean;
|
|
18
|
+
help: boolean | undefined;
|
|
15
19
|
_: (string | number)[];
|
|
16
20
|
$0: string;
|
|
17
21
|
}>;
|
package/dist/src/cli/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/cli/main.ts
|
|
2
2
|
import path3 from "path";
|
|
3
|
-
import { existsSync as existsSync2 } from "fs";
|
|
3
|
+
import { existsSync as existsSync2, writeFileSync } from "fs";
|
|
4
4
|
import { execFileSync } from "child_process";
|
|
5
5
|
import Realm8 from "realm";
|
|
6
6
|
import prompts from "prompts";
|
|
@@ -279,7 +279,7 @@ var getLazerDB = async (realmDBPath) => {
|
|
|
279
279
|
RealmUser
|
|
280
280
|
],
|
|
281
281
|
path: realmDBPath,
|
|
282
|
-
schemaVersion:
|
|
282
|
+
schemaVersion: 41,
|
|
283
283
|
onMigration: (oldRealm, newRealm) => {
|
|
284
284
|
console.log(
|
|
285
285
|
`[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`
|
|
@@ -321,6 +321,10 @@ function getArgs() {
|
|
|
321
321
|
alias: "r",
|
|
322
322
|
describe: "Reload lazer database"
|
|
323
323
|
},
|
|
324
|
+
exportPlaylist: {
|
|
325
|
+
type: "string",
|
|
326
|
+
describe: "Export playlist to a file"
|
|
327
|
+
},
|
|
324
328
|
osuDataDir: {
|
|
325
329
|
type: "string",
|
|
326
330
|
default: path3.join(getDataDir() || ".", "osu"),
|
|
@@ -338,13 +342,18 @@ function getArgs() {
|
|
|
338
342
|
default: false,
|
|
339
343
|
alias: "l",
|
|
340
344
|
describe: "Loop the playlist on end"
|
|
345
|
+
},
|
|
346
|
+
help: {
|
|
347
|
+
type: "boolean",
|
|
348
|
+
alias: "h",
|
|
349
|
+
describe: "Show help"
|
|
341
350
|
}
|
|
342
351
|
}).argv;
|
|
343
352
|
return argv;
|
|
344
353
|
}
|
|
345
354
|
async function main() {
|
|
346
355
|
const argv = await getArgs();
|
|
347
|
-
console.log("[INFO]
|
|
356
|
+
console.log("[INFO] osu!play");
|
|
348
357
|
let reload = false;
|
|
349
358
|
let osuDataDir = argv.osuDataDir;
|
|
350
359
|
if (argv.reload) {
|
|
@@ -383,6 +392,13 @@ async function main() {
|
|
|
383
392
|
}
|
|
384
393
|
}
|
|
385
394
|
console.log(`beatmap songs: ${beatmapSets.length}`);
|
|
395
|
+
if (argv.exportPlaylist) {
|
|
396
|
+
console.log(`[INFO] Exporting playlist to ${argv.exportPlaylist}`);
|
|
397
|
+
const playlist = uniqueBeatmaps.map((mp) => mp.path).join("\n");
|
|
398
|
+
writeFileSync(argv.exportPlaylist, playlist);
|
|
399
|
+
console.log(`[INFO] Done. Use something like \`mpv --playlist=${argv.exportPlaylist}\` to play the playlist`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
386
402
|
let selectedBeatmap = (await prompts({
|
|
387
403
|
type: "autocomplete",
|
|
388
404
|
name: "beatmap",
|
package/dist/src/cli/main.js.map
CHANGED
|
@@ -1 +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 { execFileSync } from \"node:child_process\";\n\nimport Realm from \"realm\";\nimport prompts from \"prompts\";\nimport { BeatmapSet } from \"../realm/schema/mod.js\";\nimport { getConfigDir, getDataDir, getRealmDBPath } from \"../utils/mod.js\";\nimport { getLazerDB, getNamedFileHash, hashedFilePath } from \"../realm/mod.js\";\n\nimport yargs from \"yargs/yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nexport function getArgs() {\n const argv = yargs(hideBin(process.argv))\n .usage(\"Play music from your osu!lazer beatmaps from the terminal\\nUsage: $0 [options]\")\n .options({\n reload: {\n type: \"boolean\",\n default: false,\n alias: \"r\",\n describe: \"Reload lazer database\",\n },\n osuDataDir: {\n type: \"string\",\n default: path.join(getDataDir() || \".\", \"osu\"),\n alias: \"d\",\n describe: \"Osu!lazer data directory\",\n },\n configDir: {\n type: \"string\",\n default: path.join(getConfigDir() || \".\", \"osu-play\"),\n alias: \"c\",\n describe: \"Config directory\",\n },\n loop: {\n type: \"boolean\",\n default: false,\n alias: \"l\",\n describe: \"Loop the playlist on end\",\n },\n }).argv;\n return argv;\n}\n\nexport async function main() {\n const argv = await getArgs();\n console.log(\"[INFO] OSU!list\");\n\n let reload = false;\n let osuDataDir = argv.osuDataDir;\n\n if (argv.reload) {\n console.log(\"[INFO] Reloading lazer database\");\n reload = true;\n }\n\n if (argv.osuDataDir !== getDataDir()) {\n console.log(`[INFO] Using osu!lazer data directory: ${argv.osuDataDir}`);\n }\n\n const realmDBPath = getRealmDBPath(argv.configDir, { reload, osuDataDir });\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 const songSet = new Set<string>();\n const uniqueBeatmaps: {\n title: string;\n path: string | null;\n }[] = [];\n\n for (const beatmapSet of beatmapSets) {\n for (const beatmap of beatmapSet.Beatmaps) {\n const fileName = beatmap.Metadata.AudioFile;\n const hash = getNamedFileHash(fileName ?? \"\", beatmapSet);\n if (!hash) continue;\n if (songSet.has(hash)) continue;\n songSet.add(hash);\n const meta = beatmap.Metadata;\n const path = hashedFilePath(hash);\n const title = `${meta.Title} : ${meta.Artist} - ${meta.TitleUnicode} : ${meta.ArtistUnicode}`;\n uniqueBeatmaps.push({ title, path });\n }\n }\n\n console.log(`beatmap songs: ${beatmapSets.length}`);\n\n // Get the map index from the user\n let selectedBeatmap: number = (\n await prompts({\n type: \"autocomplete\",\n name: \"beatmap\",\n message: \"Which map do you want to play:\",\n choices: uniqueBeatmaps.map((mp, index) => ({\n title: mp.title,\n value: index,\n })),\n })\n ).beatmap;\n\n for (let i = selectedBeatmap; i < uniqueBeatmaps.length; ++i) {\n const beatmap = uniqueBeatmaps[i];\n console.log(`Map : ${beatmap.title}`);\n if (beatmap.path && existsSync(beatmap.path)) {\n // Open file using exo-open.\n console.log(`File exists: ${beatmap.path}`);\n console.log(`Playing ${beatmap.title}`);\n try {\n execFileSync(\"exo-open\", [beatmap.path]);\n } catch (err) {\n console.log(`Error: ${err}`);\n break;\n }\n } else {\n console.log(`File does not exist: ${beatmap.path}`);\n }\n if (i < uniqueBeatmaps.length - 1) {\n // Wait 1 second between\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else if (argv.loop) {\n console.log('[INFO] Looping playlist');\n i = 0;\n } else { \n console.log('[INFO] Done. Use --loop to loop the playlist');\n }\n }\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 | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\n}\n\nexport function getConfigDir(): string | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\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 options: {\n osuDataDir: string;\n reload: boolean;\n } = { reload: false, osuDataDir: getDataDir() || \".\" },\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!options.reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(options.osuDataDir, \"client.realm\");\n if (existsSync(osuDBPath)) {\n console.log( `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`);\n mkdirSync(appConfigDir, { recursive: true });\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"]}
|
|
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, writeFileSync } from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\n\nimport Realm from \"realm\";\nimport prompts from \"prompts\";\nimport { BeatmapSet } from \"../realm/schema/mod.js\";\nimport { getConfigDir, getDataDir, getRealmDBPath } from \"../utils/mod.js\";\nimport { getLazerDB, getNamedFileHash, hashedFilePath } from \"../realm/mod.js\";\n\nimport yargs from \"yargs/yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nexport function getArgs() {\n const argv = yargs(hideBin(process.argv))\n .usage(\"Play music from your osu!lazer beatmaps from the terminal\\nUsage: $0 [options]\")\n .options({\n reload: {\n type: \"boolean\",\n default: false,\n alias: \"r\",\n describe: \"Reload lazer database\",\n },\n exportPlaylist: {\n type: \"string\",\n describe: \"Export playlist to a file\",\n },\n osuDataDir: {\n type: \"string\",\n default: path.join(getDataDir() || \".\", \"osu\"),\n alias: \"d\",\n describe: \"Osu!lazer data directory\",\n },\n configDir: {\n type: \"string\",\n default: path.join(getConfigDir() || \".\", \"osu-play\"),\n alias: \"c\",\n describe: \"Config directory\",\n },\n loop: {\n type: \"boolean\",\n default: false,\n alias: \"l\",\n describe: \"Loop the playlist on end\",\n },\n help: {\n type: \"boolean\",\n alias: \"h\",\n describe: \"Show help\",\n }\n }).argv;\n return argv;\n}\n\nexport async function main() {\n const argv = await getArgs();\n console.log(\"[INFO] osu!play\");\n\n let reload = false;\n let osuDataDir = argv.osuDataDir;\n\n if (argv.reload) {\n console.log(\"[INFO] Reloading lazer database\");\n reload = true;\n }\n\n if (argv.osuDataDir !== getDataDir()) {\n console.log(`[INFO] Using osu!lazer data directory: ${argv.osuDataDir}`);\n }\n\n const realmDBPath = getRealmDBPath(argv.configDir, { reload, osuDataDir });\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 const songSet = new Set<string>();\n const uniqueBeatmaps: {\n title: string;\n path: string | null;\n }[] = [];\n\n for (const beatmapSet of beatmapSets) {\n for (const beatmap of beatmapSet.Beatmaps) {\n const fileName = beatmap.Metadata.AudioFile;\n const hash = getNamedFileHash(fileName ?? \"\", beatmapSet);\n if (!hash) continue;\n if (songSet.has(hash)) continue;\n songSet.add(hash);\n const meta = beatmap.Metadata;\n const path = hashedFilePath(hash);\n const title = `${meta.Title} : ${meta.Artist} - ${meta.TitleUnicode} : ${meta.ArtistUnicode}`;\n uniqueBeatmaps.push({ title, path });\n }\n }\n\n console.log(`beatmap songs: ${beatmapSets.length}`);\n\n if (argv.exportPlaylist) {\n console.log(`[INFO] Exporting playlist to ${argv.exportPlaylist}`);\n const playlist = uniqueBeatmaps.map((mp) => mp.path).join(\"\\n\");\n writeFileSync(argv.exportPlaylist, playlist);\n console.log(`[INFO] Done. Use something like \\`mpv --playlist=${argv.exportPlaylist}\\` to play the playlist`);\n return;\n }\n\n // Get the map index from the user\n let selectedBeatmap: number = (\n await prompts({\n type: \"autocomplete\",\n name: \"beatmap\",\n message: \"Which map do you want to play:\",\n choices: uniqueBeatmaps.map((mp, index) => ({\n title: mp.title,\n value: index,\n })),\n })\n ).beatmap;\n\n for (let i = selectedBeatmap; i < uniqueBeatmaps.length; ++i) {\n const beatmap = uniqueBeatmaps[i];\n console.log(`Map : ${beatmap.title}`);\n if (beatmap.path && existsSync(beatmap.path)) {\n // Open file using exo-open.\n console.log(`File exists: ${beatmap.path}`);\n console.log(`Playing ${beatmap.title}`);\n try {\n execFileSync(\"exo-open\", [beatmap.path]);\n } catch (err) {\n console.log(`Error: ${err}`);\n break;\n }\n } else {\n console.log(`File does not exist: ${beatmap.path}`);\n }\n if (i < uniqueBeatmaps.length - 1) {\n // Wait 1 second between\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else if (argv.loop) {\n console.log('[INFO] Looping playlist');\n i = 0;\n } else { \n console.log('[INFO] Done. Use --loop to loop the playlist');\n }\n }\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 | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\n}\n\nexport function getConfigDir(): string | undefined {\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\"] ?? undefined;\n }\n\n return undefined;\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 options: {\n osuDataDir: string;\n reload: boolean;\n } = { reload: false, osuDataDir: getDataDir() || \".\" },\n) {\n const localDBPath = path.join(appConfigDir, \"client.realm\");\n if (!options.reload && existsSync(localDBPath)) return localDBPath;\n\n const osuDBPath = path.join(options.osuDataDir, \"client.realm\");\n if (existsSync(osuDBPath)) {\n console.log( `[getRealmDBPath]: ${osuDBPath} is being imported from osu!lazer to ${localDBPath}`);\n mkdirSync(appConfigDir, { recursive: true });\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: 41,\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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osu-play",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Play music from your osu!lazer beatmaps from the terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/osu-play.js",
|
|
@@ -19,13 +19,6 @@
|
|
|
19
19
|
"bin": {
|
|
20
20
|
"osu-play": "./bin/osu-play.js"
|
|
21
21
|
},
|
|
22
|
-
"scripts": {
|
|
23
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
24
|
-
"build": "tsup",
|
|
25
|
-
"start": "./bin/osu-play.js",
|
|
26
|
-
"dev:start": "tsc && ./bin/osu-play.js",
|
|
27
|
-
"clean": "rm -rf dist"
|
|
28
|
-
},
|
|
29
22
|
"author": "KorigamiK",
|
|
30
23
|
"license": "MIT",
|
|
31
24
|
"devDependencies": {
|
|
@@ -52,5 +45,12 @@
|
|
|
52
45
|
"type": "git",
|
|
53
46
|
"url": "https://github.com/KorigamiK/osu-play"
|
|
54
47
|
},
|
|
55
|
-
"bugs": "https://github.com/KorigamiK/osu-play/issues"
|
|
48
|
+
"bugs": "https://github.com/KorigamiK/osu-play/issues",
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"start": "./bin/osu-play.js",
|
|
53
|
+
"dev:start": "tsc && ./bin/osu-play.js",
|
|
54
|
+
"clean": "rm -rf dist"
|
|
55
|
+
}
|
|
56
56
|
}
|
package/src/cli/main.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
2
|
+
import { existsSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
|
|
5
5
|
import Realm from "realm";
|
|
@@ -21,6 +21,10 @@ export function getArgs() {
|
|
|
21
21
|
alias: "r",
|
|
22
22
|
describe: "Reload lazer database",
|
|
23
23
|
},
|
|
24
|
+
exportPlaylist: {
|
|
25
|
+
type: "string",
|
|
26
|
+
describe: "Export playlist to a file",
|
|
27
|
+
},
|
|
24
28
|
osuDataDir: {
|
|
25
29
|
type: "string",
|
|
26
30
|
default: path.join(getDataDir() || ".", "osu"),
|
|
@@ -39,13 +43,18 @@ export function getArgs() {
|
|
|
39
43
|
alias: "l",
|
|
40
44
|
describe: "Loop the playlist on end",
|
|
41
45
|
},
|
|
46
|
+
help: {
|
|
47
|
+
type: "boolean",
|
|
48
|
+
alias: "h",
|
|
49
|
+
describe: "Show help",
|
|
50
|
+
}
|
|
42
51
|
}).argv;
|
|
43
52
|
return argv;
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
export async function main() {
|
|
47
56
|
const argv = await getArgs();
|
|
48
|
-
console.log("[INFO]
|
|
57
|
+
console.log("[INFO] osu!play");
|
|
49
58
|
|
|
50
59
|
let reload = false;
|
|
51
60
|
let osuDataDir = argv.osuDataDir;
|
|
@@ -99,6 +108,14 @@ export async function main() {
|
|
|
99
108
|
|
|
100
109
|
console.log(`beatmap songs: ${beatmapSets.length}`);
|
|
101
110
|
|
|
111
|
+
if (argv.exportPlaylist) {
|
|
112
|
+
console.log(`[INFO] Exporting playlist to ${argv.exportPlaylist}`);
|
|
113
|
+
const playlist = uniqueBeatmaps.map((mp) => mp.path).join("\n");
|
|
114
|
+
writeFileSync(argv.exportPlaylist, playlist);
|
|
115
|
+
console.log(`[INFO] Done. Use something like \`mpv --playlist=${argv.exportPlaylist}\` to play the playlist`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
102
119
|
// Get the map index from the user
|
|
103
120
|
let selectedBeatmap: number = (
|
|
104
121
|
await prompts({
|
package/src/realm/mod.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const getLazerDB = async (realmDBPath: string) => {
|
|
|
21
21
|
RealmUser,
|
|
22
22
|
],
|
|
23
23
|
path: realmDBPath,
|
|
24
|
-
schemaVersion:
|
|
24
|
+
schemaVersion: 41,
|
|
25
25
|
onMigration: (oldRealm, newRealm) => {
|
|
26
26
|
console.log(
|
|
27
27
|
`[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`,
|