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 CHANGED
@@ -1,6 +1,6 @@
1
- # OSU!Pplay
1
+ # osu!play
2
2
 
3
- Listen to your favourite [OSU!Lazer](https://lazer.ppy.sh) beatmaps as a spotify playlist from the terminal
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 Show help [boolean]
41
- --version Show version number [boolean]
42
- -r, --reload Reload lazer database [boolean] [default: false]
43
- -d, --osuDataDir Osu!lazer data directory [string] [default: "~/.local/share/osu"]
44
- -c, --configDir Config directory [string] [default: "~/.config/osu-play"]
45
- -l, --loop Loop the playlist on end [boolean] [default: false]
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: 36,
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"]}
@@ -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
  }>;
@@ -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: 36,
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] OSU!list");
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",
@@ -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.4",
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] OSU!list");
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: 36,
24
+ schemaVersion: 41,
25
25
  onMigration: (oldRealm, newRealm) => {
26
26
  console.log(
27
27
  `[onMigration]: Migrating ${oldRealm.path} - ${oldRealm.schemaVersion} -> ${newRealm.path} - ${newRealm.schemaVersion}`,