diff --git a/deno.json b/deno.json index 4934bce6..1ed85809 100644 --- a/deno.json +++ b/deno.json @@ -4,7 +4,7 @@ "jsxImportSource": "preact" }, "fmt": { - "exclude": ["**/*.svg"], + "exclude": ["**/*.svg", "./testdata/**"], "lineWidth": 120, "proseWrap": "preserve", "singleQuote": true, diff --git a/providers/Mora/__snapshots__/mod.test.ts.snap b/providers/Mora/__snapshots__/mod.test.ts.snap new file mode 100644 index 00000000..088b596c --- /dev/null +++ b/providers/Mora/__snapshots__/mod.test.ts.snap @@ -0,0 +1,777 @@ +export const snapshot = {}; + +snapshot[`Mora provider > release lookup > release with GTIN in distPartNo 1`] = ` +{ + artists: [ + { + creditedName: "Ado", + externalIds: [ + { + id: "1310625", + provider: "mora", + type: "artist", + }, + ], + name: "Ado", + }, + ], + availableIn: [ + "JP", + ], + copyright: "A Virgin Music release; ℗ 2025 UNIVERSAL MUSIC LLC", + externalLinks: [ + { + types: [ + "paid download", + ], + url: "https://mora.jp/package/43000006/00602488058599/", + }, + ], + gtin: "00602488058599", + images: [ + { + types: [ + "front", + ], + url: "https://cf.mora.jp/contents/package/0000/00000083/0042/023/270/0042023270.200.jpg", + }, + ], + info: { + messages: [], + providers: [ + { + apiUrl: "https://cf.mora.jp/contents/package/0000/00000083/0042/023/270/packageMeta.json", + id: "43000006/00602488058599", + internalName: "mora", + lookup: { + method: "id", + value: "43000006/00602488058599", + }, + name: "mora", + url: "https://mora.jp/package/43000006/00602488058599/", + }, + ], + }, + labels: [ + { + name: "Universal Music LLC", + }, + ], + media: [ + { + format: "Digital Media", + tracklist: [ + { + artists: [ + { + creditedName: "Ado", + externalIds: [ + { + id: "1310625", + provider: "mora", + type: "artist", + }, + ], + name: "Ado", + }, + ], + length: 172000, + number: 1, + title: "MAGIC", + type: "audio", + }, + ], + }, + ], + packaging: "None", + releaseDate: { + day: 31, + month: 10, + year: 2025, + }, + status: "Official", + title: "MAGIC", +} +`; + +snapshot[`Mora provider > release lookup > release with GTIN in cdPartNo 1`] = ` +{ + artists: [ + { + creditedName: "Various Artists", + externalIds: [ + { + id: "15340", + provider: "mora", + type: "artist", + }, + ], + name: "Various Artists", + }, + ], + availableIn: [ + "JP", + ], + copyright: "(P)2025 BUSHIROAD MUSIC INC.", + externalLinks: [ + { + types: [ + "paid download", + ], + url: "https://mora.jp/package/43000035/198704758065_F/", + }, + ], + gtin: "198704758065", + images: [ + { + types: [ + "front", + ], + url: "https://cf.mora.jp/contents/package/0000/00000013/0041/921/939/0041921939.200.jpg", + }, + ], + info: { + messages: [], + providers: [ + { + apiUrl: "https://cf.mora.jp/contents/package/0000/00000013/0041/921/939/packageMeta.json", + id: "43000035/198704758065_F", + internalName: "mora", + lookup: { + method: "id", + value: "43000035/198704758065_F", + }, + name: "mora", + url: "https://mora.jp/package/43000035/198704758065_F/", + }, + ], + }, + labels: [ + { + name: "ブシロードミュージック", + }, + ], + media: [ + { + format: "Digital Media", + tracklist: [ + { + artists: [ + { + creditedName: "Poppin'Party", + externalIds: [ + { + id: "2027483", + provider: "mora", + type: "artist", + }, + ], + name: "Poppin'Party", + }, + ], + length: 256000, + number: 1, + title: "心絵 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Poppin'Party", + externalIds: [ + { + id: "2027483", + provider: "mora", + type: "artist", + }, + ], + name: "Poppin'Party", + }, + ], + length: 188000, + number: 2, + title: "ちゅ、多様性。 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Poppin'Party", + externalIds: [ + { + id: "2027483", + provider: "mora", + type: "artist", + }, + ], + name: "Poppin'Party", + }, + ], + length: 232000, + number: 3, + title: "フィクション (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Afterglow", + externalIds: [ + { + id: "2027484", + provider: "mora", + type: "artist", + }, + ], + name: "Afterglow", + }, + ], + length: 233000, + number: 4, + title: "カゲロウデイズ (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Afterglow", + externalIds: [ + { + id: "2027484", + provider: "mora", + type: "artist", + }, + ], + name: "Afterglow", + }, + ], + length: 217000, + number: 5, + title: "Bunny Girl (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Afterglow", + externalIds: [ + { + id: "2027484", + provider: "mora", + type: "artist", + }, + ], + name: "Afterglow", + }, + ], + length: 235000, + number: 6, + title: "オレンジ (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Pastel*Palettes", + externalIds: [ + { + id: "2027485", + provider: "mora", + type: "artist", + }, + ], + name: "Pastel*Palettes", + }, + ], + length: 215000, + number: 7, + title: "サインはB (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Pastel*Palettes", + externalIds: [ + { + id: "2027485", + provider: "mora", + type: "artist", + }, + ], + name: "Pastel*Palettes", + }, + ], + length: 230000, + number: 8, + title: "だから、ひとりじゃない (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Pastel*Palettes", + externalIds: [ + { + id: "2027485", + provider: "mora", + type: "artist", + }, + ], + name: "Pastel*Palettes", + }, + ], + length: 191000, + number: 9, + title: "最上級にかわいいの! (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Roselia", + externalIds: [ + { + id: "2027487", + provider: "mora", + type: "artist", + }, + ], + name: "Roselia", + }, + ], + length: 220000, + number: 10, + title: "ファタール (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Roselia", + externalIds: [ + { + id: "2027487", + provider: "mora", + type: "artist", + }, + ], + name: "Roselia", + }, + ], + length: 205000, + number: 11, + title: "ヒバナ -Reloaded- (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Roselia", + externalIds: [ + { + id: "2027487", + provider: "mora", + type: "artist", + }, + ], + name: "Roselia", + }, + ], + length: 238000, + number: 12, + title: "Reweave (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Poppin'Party, 高松 燈(CV:羊宮妃那)", + externalIds: [ + { + id: "2255981", + provider: "mora", + type: "artist", + }, + ], + name: "Poppin'Party, 高松 燈(CV:羊宮妃那)", + }, + ], + length: 275000, + number: 13, + title: "幾億光年 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Pastel*Palettes, 美竹 蘭(CV:佐倉綾音)", + externalIds: [ + { + id: "2255982", + provider: "mora", + type: "artist", + }, + ], + name: "Pastel*Palettes, 美竹 蘭(CV:佐倉綾音)", + }, + ], + length: 222000, + number: 14, + title: "愛包ダンスホール (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "ハロー、ハッピーワールド!", + externalIds: [ + { + id: "2027488", + provider: "mora", + type: "artist", + }, + ], + name: "ハロー、ハッピーワールド!", + }, + ], + length: 226000, + number: 15, + title: "最高到達点 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "ハロー、ハッピーワールド!", + externalIds: [ + { + id: "2027488", + provider: "mora", + type: "artist", + }, + ], + name: "ハロー、ハッピーワールド!", + }, + ], + length: 135000, + number: 16, + title: "強風オールバック (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "ハロー、ハッピーワールド!", + externalIds: [ + { + id: "2027488", + provider: "mora", + type: "artist", + }, + ], + name: "ハロー、ハッピーワールド!", + }, + ], + length: 160000, + number: 17, + title: "はいよろこんで (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Morfonica", + externalIds: [ + { + id: "2013168", + provider: "mora", + type: "artist", + }, + ], + name: "Morfonica", + }, + ], + length: 273000, + number: 18, + title: "輪舞-revolution (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Morfonica", + externalIds: [ + { + id: "2013168", + provider: "mora", + type: "artist", + }, + ], + name: "Morfonica", + }, + ], + length: 145000, + number: 19, + title: "QUEEN (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Morfonica", + externalIds: [ + { + id: "2013168", + provider: "mora", + type: "artist", + }, + ], + name: "Morfonica", + }, + ], + length: 250000, + number: 20, + title: "again (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "RAISE A SUILEN", + externalIds: [ + { + id: "2027489", + provider: "mora", + type: "artist", + }, + ], + name: "RAISE A SUILEN", + }, + ], + length: 168000, + number: 21, + title: "Bling-Bang-Bang-Born (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "RAISE A SUILEN", + externalIds: [ + { + id: "2027489", + provider: "mora", + type: "artist", + }, + ], + name: "RAISE A SUILEN", + }, + ], + length: 193000, + number: 22, + title: "第六感 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "MyGO!!!!!", + externalIds: [ + { + id: "2007263", + provider: "mora", + type: "artist", + }, + ], + name: "MyGO!!!!!", + }, + ], + length: 188000, + number: 23, + title: "雑踏、僕らの街 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "MyGO!!!!!", + externalIds: [ + { + id: "2007263", + provider: "mora", + type: "artist", + }, + ], + name: "MyGO!!!!!", + }, + ], + length: 249000, + number: 24, + title: "遥か彼方 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "MyGO!!!!!", + externalIds: [ + { + id: "2007263", + provider: "mora", + type: "artist", + }, + ], + name: "MyGO!!!!!", + }, + ], + length: 236000, + number: 25, + title: "だれかの心臓になれたなら (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "Roselia, レイヤ(CV:Raychell)", + externalIds: [ + { + id: "2255983", + provider: "mora", + type: "artist", + }, + ], + name: "Roselia, レイヤ(CV:Raychell)", + }, + ], + length: 227000, + number: 26, + title: "悪魔の子 (Cover)", + type: "audio", + }, + { + artists: [ + { + creditedName: "ハロー、ハッピーワールド!, 倉田ましろ(CV:進藤あまね)", + externalIds: [ + { + id: "2255984", + provider: "mora", + type: "artist", + }, + ], + name: "ハロー、ハッピーワールド!, 倉田ましろ(CV:進藤あまね)", + }, + ], + length: 202000, + number: 27, + title: "シカ色デイズ (Cover)", + type: "audio", + }, + ], + }, + ], + packaging: "None", + releaseDate: { + day: 15, + month: 10, + year: 2025, + }, + status: "Official", + title: "バンドリ! ガールズバンドパーティ! カバーコレクションVol.10", +} +`; + +snapshot[`Mora provider > release lookup > video release 1`] = ` +{ + artists: [ + { + creditedName: "The Last Dinner Party", + externalIds: [ + { + id: "1739884", + provider: "mora", + type: "artist", + }, + ], + name: "The Last Dinner Party", + }, + ], + availableIn: [ + "JP", + ], + copyright: "© 2025 The Last Dinner Party, under exclusive licence to Universal Music Operations Limited", + externalLinks: [ + { + types: [ + "paid download", + ], + url: "https://mora.jp/package/43000006/00199957093194/", + }, + ], + gtin: "00199957093194", + images: [ + { + types: [ + "front", + ], + url: "https://cf.mora.jp/contents/package/0000/00000083/0042/738/339/0042738339.200.jpg", + }, + ], + info: { + messages: [], + providers: [ + { + apiUrl: "https://cf.mora.jp/contents/package/0000/00000083/0042/738/339/packageMeta.json", + id: "43000006/00199957093194", + internalName: "mora", + lookup: { + method: "id", + value: "43000006/00199957093194", + }, + name: "mora", + url: "https://mora.jp/package/43000006/00199957093194/", + }, + ], + }, + labels: [ + { + name: "Universal-Island Records Ltd.", + }, + ], + media: [ + { + format: "Digital Media", + tracklist: [ + { + artists: [ + { + creditedName: "The Last Dinner Party", + externalIds: [ + { + id: "1739884", + provider: "mora", + type: "artist", + }, + ], + name: "The Last Dinner Party", + }, + ], + length: 239000, + number: 1, + title: "Woman is a Tree", + type: "video", + }, + ], + }, + ], + packaging: "None", + releaseDate: { + day: 22, + month: 11, + year: 2025, + }, + status: "Official", + title: "Woman is a Tree", +} +`; diff --git a/providers/Mora/json_types.ts b/providers/Mora/json_types.ts new file mode 100644 index 00000000..7f0cafb9 --- /dev/null +++ b/providers/Mora/json_types.ts @@ -0,0 +1,52 @@ +export interface ApiArgs { + mountPoint: string; + labelId: string; + materialNo: string; +} + +export interface PackageMeta { + artistName: string; + artistNo: number; + cdPartNo: string | null; + fullsizeimage: string; + title: string; + labelCode: string; + labelcompanyname: string; + master: string; + distPartNo: string; + startDate: string; + mediaFormatNo: MediaFormat; + mediaType: MediaType; + trackList: Track[]; +} + +export interface Track { + arranger: string | null; + composer: string | null; + /** Lyricist name */ + lyrics: string | null; + + artistName: string; + artistNo: number; + /** Track duration in seconds */ + duration: number; + mediaFormatNo: MediaFormat; + mediaType: MediaType; + title: string; + trackNo: number; +} + +export enum MediaFormat { + Music = 10, + Video = 11, + HiRes = 12, + Lossless = 15, +} + +export enum MediaType { + AAC = 6, + AVC_H264 = 7, + FLAC = 8, + DSD_DSF = 9, + DSD_DFF = 10, +} diff --git a/providers/Mora/mod.test.ts b/providers/Mora/mod.test.ts new file mode 100644 index 00000000..4d516fee --- /dev/null +++ b/providers/Mora/mod.test.ts @@ -0,0 +1,59 @@ +import { describeProvider, makeProviderOptions } from '@/providers/test_spec.ts'; +import { stubProviderLookups } from '@/providers/test_stubs.ts'; +import { afterAll, describe } from '@std/testing/bdd'; +import { assertSnapshot } from '@std/testing/snapshot'; + +import MoraProvider from './mod.ts'; +import { assertEquals } from 'std/assert/assert_equals.ts'; + +describe('Mora provider', () => { + const mora = new MoraProvider(makeProviderOptions()); + const lookupStub = stubProviderLookups(mora); + + describeProvider(mora, { + urls: [{ + description: 'package page', + url: new URL('https://mora.jp/package/43000006/00602488058599/'), + id: { type: 'package', id: '43000006/00602488058599' }, + isCanonical: true, + }, { + description: 'package page with tracking parameter', + url: new URL('https://mora.jp/package/43000087/SEXX03051B00Z/?fmid=TOPRNKS'), + id: { type: 'package', id: '43000087/SEXX03051B00Z' }, + }, { + description: 'artist page', + url: new URL('https://mora.jp/artist/1739884/'), + id: { type: 'artist', id: '1739884' }, + isCanonical: true, + }], + releaseLookup: [{ + description: 'release with GTIN in distPartNo', + release: '43000006/00602488058599', + assert: async (release, ctx) => { + await assertSnapshot(ctx, release); + assertEquals(release.gtin, '00602488058599'); + }, + }, { + description: 'release with GTIN in cdPartNo', + release: '43000035/198704758065_F', + assert: async (release, ctx) => { + await assertSnapshot(ctx, release); + assertEquals(release.gtin, '198704758065'); + }, + }, { + description: 'video release', + release: '43000006/00199957093194', + assert: async (release, ctx) => { + await assertSnapshot(ctx, release); + + const trackCount = release.media.flatMap((medium) => medium.tracklist).length; + assertEquals(trackCount, 1, 'Release should have 1 track'); + assertEquals(release.media[0].tracklist[0].type, 'video'); + }, + }], + }); + + afterAll(() => { + lookupStub.restore(); + }); +}); diff --git a/providers/Mora/mod.ts b/providers/Mora/mod.ts new file mode 100644 index 00000000..e19a331b --- /dev/null +++ b/providers/Mora/mod.ts @@ -0,0 +1,234 @@ +import type { ApiArgs, PackageMeta, Track } from './json_types.ts'; +import { MediaFormat } from './json_types.ts'; +import type { + ArtistCreditName, + Artwork, + EntityId, + HarmonyRelease, + HarmonyTrack, + LinkType, +} from '@/harmonizer/types.ts'; +import { type CacheEntry, MetadataProvider, ReleaseLookup } from '@/providers/base.ts'; +import { DurationPrecision, FeatureQuality, FeatureQualityMap } from '@/providers/features.ts'; +import { parseISODateTime, PartialDate } from '@/utils/date.ts'; +import { ProviderError, ResponseError } from '@/utils/errors.ts'; +import { extractMetadataTag } from '@/utils/html.ts'; +import { isValidGTIN } from '@/utils/gtin.ts'; + +export default class MoraProvider extends MetadataProvider { + readonly name = 'mora'; + + readonly supportedUrls = new URLPattern({ + hostname: 'mora.jp', + pathname: '/package/:labelCode([0-9]+)/:packageId{/}?', + }); + + readonly artistUrlPattern = new URLPattern({ + hostname: this.supportedUrls.hostname, + pathname: '/artist/:id{/}?', + }); + + override readonly features: FeatureQualityMap = { + // The API returns a "full size" image of at most 200x200 + 'cover size': 200, + 'duration precision': DurationPrecision.SECONDS, + 'GTIN lookup': FeatureQuality.MISSING, + 'MBID resolving': FeatureQuality.PRESENT, + 'release label': FeatureQuality.GOOD, + }; + + readonly entityTypeMap = { + artist: 'artist', + release: 'package', + }; + + override readonly launchDate: PartialDate = { + year: 2004, + month: 4, + }; + + readonly releaseLookup = MoraReleaseLookup; + + constructUrl(entity: EntityId): URL { + return new URL(`https://mora.jp/${entity.type}/${entity.id}/`); + } + + override extractEntityFromUrl(url: URL): EntityId | undefined { + const releaseResult = this.supportedUrls.exec(url); + if (releaseResult) { + const { labelCode, packageId } = releaseResult.pathname.groups; + if (!labelCode || !packageId) { + return undefined; + } + + return { + type: 'package', + id: [labelCode, packageId].join('/'), + }; + } + + const artistResult = this.artistUrlPattern.exec(url); + if (artistResult) { + return { + type: 'artist', + id: artistResult.pathname.groups.id!, + }; + } + + return undefined; + } + + override getLinkTypesForEntity(_entity: EntityId): LinkType[] { + return ['paid download']; + } + + extractEmbeddedJson(webUrl: URL, maxTimestamp?: number): Promise> { + return this.fetchJSON(webUrl, { + policy: { maxTimestamp }, + responseMutator: async (response) => { + if (!webUrl.pathname.startsWith('/package')) { + return response; + } + + const html = await response.text(); + const apiArgsRaw = extractMetadataTag(html, 'msApplication-Arguments'); + if (!apiArgsRaw) { + throw new ResponseError(this.name, 'Response is missing the expected tag', webUrl); + } + + try { + const apiArgs: Data = JSON.parse(apiArgsRaw); + + if (apiArgs) { + return new Response(JSON.stringify(apiArgs), response); + } + } catch (_error) { + throw new ResponseError(this.name, 'Failed to extract API arguments', webUrl); + } + + throw new ResponseError(this.name, 'Failed to extract API arguments', webUrl); + }, + }); + } +} + +export class MoraReleaseLookup extends ReleaseLookup { + rawReleaseUrl: URL | undefined; + mountPoint: string | undefined; + labelId: string | undefined; + materialNo: string | undefined; + + apiUrl(): URL { + const paddedMaterialNo = this.materialNo!.padStart(10, '0'); + const slicedMaterialNo = `${paddedMaterialNo.slice(0, 4)}/${paddedMaterialNo.slice(4, 7)}/${ + paddedMaterialNo.slice(7) + }`; + + return new URL(`https://cf.mora.jp/contents/package/${this.mountPoint!}/${this.labelId!}/${slicedMaterialNo}/`); + } + + constructReleaseApiUrl(): URL { + const apiBase = this.apiUrl(); + + const packageMetaUrl = new URL(apiBase); + packageMetaUrl.pathname += 'packageMeta.json'; + + return packageMetaUrl; + } + + async getRawRelease(): Promise { + if (this.lookup.method === 'gtin') { + throw new ProviderError(this.provider.name, 'GTIN lookups are not supported'); + } + + // Entity is already defined for ID/URL lookups. + const webUrl = this.provider.constructUrl(this.entity!); + this.rawReleaseUrl = webUrl; + const { content: apiArgs, timestamp: apiArgsTimestamp } = await this.provider.extractEmbeddedJson( + webUrl, + this.options.snapshotMaxTimestamp, + ); + this.updateCacheTime(apiArgsTimestamp); + + this.mountPoint = apiArgs.mountPoint; + this.labelId = apiArgs.labelId; + this.materialNo = apiArgs.materialNo; + + const { content: release, timestamp } = await this.provider.extractEmbeddedJson( + this.constructReleaseApiUrl(), + this.options.snapshotMaxTimestamp, + ); + this.updateCacheTime(timestamp); + + return release; + } + + convertRawRelease(albumPage: PackageMeta): HarmonyRelease { + const label = { name: albumPage.labelcompanyname }; + const tracklist = albumPage.trackList.map(this.convertRawTrack.bind(this)); + + // `distPartNo` *might* contain the GTIN, but will oftentimes contain either label-specific catalog numbers, or + // some package-specific code for mora (e.g. _F for FLAC releases) + let gtin = isValidGTIN(albumPage.distPartNo) ? albumPage.distPartNo : undefined; + if (!gtin) { + // If we're lucky, the GTIN might be in `cdPartNo`. In testing, the field seems to be `null` most of the time. + if (albumPage.cdPartNo && isValidGTIN(albumPage.cdPartNo)) { + gtin = albumPage.cdPartNo; + } else { + this.addMessage('Failed to determine GTIN', 'warning'); + } + } + + const release: HarmonyRelease = { + title: albumPage.title, + artists: [this.makeArtistCreditName(albumPage.artistName, albumPage.artistNo)], + labels: [label], + gtin, + releaseDate: parseISODateTime(albumPage.startDate + ' +0'), + availableIn: ['JP'], + media: [{ + format: 'Digital Media', + tracklist, + }], + status: 'Official', + packaging: 'None', + externalLinks: [{ + url: this.rawReleaseUrl!.href, + types: ['paid download'], + }], + images: [this.getArtwork(albumPage)], + copyright: albumPage.master, + info: this.generateReleaseInfo(), + }; + + return release; + } + + convertRawTrack(rawTrack: Track): HarmonyTrack { + return { + number: rawTrack.trackNo, + title: rawTrack.title, + type: rawTrack.mediaFormatNo == MediaFormat.Video ? 'video' : 'audio', + artists: [this.makeArtistCreditName(rawTrack.artistName, rawTrack.artistNo)], + length: rawTrack.duration * 1000, + }; + } + + makeArtistCreditName(artist: string, artistNo: number): ArtistCreditName { + return { + name: artist, + creditedName: artist, + externalIds: this.provider.makeExternalIds({ type: 'artist', id: artistNo.toString() }), + }; + } + + getArtwork(albumPage: PackageMeta): Artwork { + const imageUrl = this.apiUrl(); + imageUrl.pathname += albumPage.fullsizeimage; + + return { + url: imageUrl.href, + types: ['front'], + }; + } +} diff --git a/providers/mod.ts b/providers/mod.ts index 534eac7c..89582687 100644 --- a/providers/mod.ts +++ b/providers/mod.ts @@ -10,6 +10,7 @@ import iTunesProvider from './iTunes/mod.ts'; import MusicBrainzProvider from './MusicBrainz/mod.ts'; import SpotifyProvider from './Spotify/mod.ts'; import TidalProvider from './Tidal/mod.ts'; +import MoraProvider from './Mora/mod.ts'; /** Registry with all supported providers. */ export const providers = new ProviderRegistry({ @@ -26,6 +27,7 @@ providers.addMultiple( TidalProvider, BandcampProvider, BeatportProvider, + MoraProvider, ); /** Internal names of providers which are enabled by default (for GTIN lookups). */ diff --git a/server/components/ProviderIcon.tsx b/server/components/ProviderIcon.tsx index 91a30cb8..4fc14c73 100644 --- a/server/components/ProviderIcon.tsx +++ b/server/components/ProviderIcon.tsx @@ -8,6 +8,7 @@ const providerIconMap: Record = { deezer: 'brand-deezer', itunes: 'brand-apple', musicbrainz: 'brand-metabrainz', + mora: 'brand-mora', spotify: 'brand-spotify', tidal: 'brand-tidal', }; diff --git a/server/icons/BrandMora.tsx b/server/icons/BrandMora.tsx new file mode 100644 index 00000000..0c59c8ad --- /dev/null +++ b/server/icons/BrandMora.tsx @@ -0,0 +1,19 @@ +export default function IconBrandMora({ + size = 24, + color = 'currentColor', + ...props +}) { + return ( + + + + ); +} diff --git a/server/routes/icon-sprite.svg.tsx b/server/routes/icon-sprite.svg.tsx index 40872c37..3f8541d3 100644 --- a/server/routes/icon-sprite.svg.tsx +++ b/server/routes/icon-sprite.svg.tsx @@ -1,6 +1,7 @@ import IconBrandBeatport from '@/server/icons/BrandBeatport.tsx'; import IconBrandIfpi from '@/server/icons/BrandIfpi.tsx'; import IconBrandMetaBrainz from '@/server/icons/BrandMetaBrainz.tsx'; +import IconBrandMora from '@/server/icons/BrandMora.tsx'; import IconBrandApple from 'tabler-icons/brand-apple.tsx'; import IconBrandBandcamp from 'tabler-icons/brand-bandcamp.tsx'; import IconBrandDeezer from 'tabler-icons/brand-deezer.tsx'; @@ -59,6 +60,7 @@ const icons: Icon[] = [ IconBrandGit, IconBrandIfpi, IconBrandMetaBrainz, + IconBrandMora, IconBrandSpotify, IconBrandTidal, IconPuzzle, diff --git a/server/static/harmony.css b/server/static/harmony.css index cd1b5840..674a1bcc 100644 --- a/server/static/harmony.css +++ b/server/static/harmony.css @@ -31,6 +31,7 @@ --beatport: #00e586; --brainz: #eb743b; --deezer: #a238ff; + --mora: #02082a; --musicbrainz: #ba478f; --spotify: #1db954; --tidal: #000000; @@ -461,6 +462,9 @@ label.deezer, td.deezer { label.itunes, td.itunes { background-color: var(--apple); } +label.mora, td.mora { + background-color: var(--mora); +} label.musicbrainz, td.musicbrainz { background-color: var(--musicbrainz); } diff --git a/testdata/https!/jp.mora.cf/contents/package/0000/00000013/0041/921/939/packageMeta.json b/testdata/https!/jp.mora.cf/contents/package/0000/00000013/0041/921/939/packageMeta.json new file mode 100644 index 00000000..83469049 --- /dev/null +++ b/testdata/https!/jp.mora.cf/contents/package/0000/00000013/0041/921/939/packageMeta.json @@ -0,0 +1 @@ +{"artistName":"Various Artists","artistNameKana":"ヴァリアスアーティスト","artistNameNo":0,"artistNo":15340,"bannerLinkUrl0":"https://mora.jp/etc/highreso","bannerLinkUrl1":null,"bannerLinkUrl2":null,"bannerLinkUrl3":null,"bannerTargetBlank0":"1","bannerTargetBlank1":null,"bannerTargetBlank2":null,"bannerTargetBlank3":null,"bannerimage0":"hires_tanoshimikata.png","bannerimage1":null,"bannerimage2":null,"bannerimage3":null,"bitPerSample":"24","callCoupon":"0","catchcopy":null,"cdPartNo":"198704758065","channelConf":"2","comingSoon":null,"containCoupon":"0","couponProduct":"0","dispFlg":"0","dispStartDate":"2025/10/15 00:00:00","dispStartDateStr":"2025.10.15","displayLabelname":"","distFlg":"0","distPartNo":"15198300","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921939.200.jpg","includedMedia":4,"labelCode":"43000035","labelId":"00000013","labelcompanyname":"ブシロードミュージック","labelname":"クリムゾンテクノロジー株式会社","listimage":"0041921939.80.jpg","master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921939,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"metaDescription":null,"msin":null,"musicType":"0","packageComment":null,"packageId":"198704758065_F","packageUrl":"https://cf.mora.jp/contents/package/0000/00000013/0041/921/939/","packageimage":"0041921939.100.jpg","prFlg":"0","price":6111,"priceWithoutTax":5556,"productTypeNo":9,"qualityClass":1,"relatedPackage":[],"samplingFreq":96000,"special":null,"specialPageUrl":null,"startDate":"2025/10/15 00:00:00","tie":"","title":"バンドリ! ガールズバンドパーティ! カバーコレクションVol.10","titleKana":"バンドリガールズバンドパーティカバーコレクションボリュームテン","trackList":[{"arranger":null,"arrangerKana":null,"artistName":"Poppin'Party","artistNameKana":"ポッピンパーティ","artistNameNo":0,"artistNo":2027483,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"北川賢一","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198301","duration":256,"durationStr":"4:16","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921941.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921941.80.jpg","lyrics":"北川賢一","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921941,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921941","packageimage":"0041921941.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"心絵 (Cover)","titleKana":"ココロエ","trackNo":1,"weblistsizeimage":"0041921941.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Poppin'Party","artistNameKana":"ポッピンパーティ","artistNameNo":0,"artistNo":2027483,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"真部脩一","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198302","duration":188,"durationStr":"3:08","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921945.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921945.80.jpg","lyrics":"真部脩一 / あの","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921945,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921945","packageimage":"0041921945.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"ちゅ、多様性。 (Cover)","titleKana":"チュタヨウセイ","trackNo":2,"weblistsizeimage":"0041921945.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Poppin'Party","artistNameKana":"ポッピンパーティ","artistNameNo":0,"artistNo":2027483,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"片岡健太","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198303","duration":232,"durationStr":"3:52","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921948.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921948.80.jpg","lyrics":"片岡健太","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921948,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921948","packageimage":"0041921948.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"フィクション (Cover)","titleKana":"フィクション","trackNo":3,"weblistsizeimage":"0041921948.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Afterglow","artistNameKana":"アフターグロウ","artistNameNo":0,"artistNo":2027484,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"じん","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198304","duration":233,"durationStr":"3:53","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921951.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921951.80.jpg","lyrics":"じん","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921951,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921951","packageimage":"0041921951.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"カゲロウデイズ (Cover)","titleKana":"カゲロウデイズ","trackNo":4,"weblistsizeimage":"0041921951.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Afterglow","artistNameKana":"アフターグロウ","artistNameNo":0,"artistNo":2027484,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"AKASAKI","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198305","duration":217,"durationStr":"3:37","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921955.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921955.80.jpg","lyrics":"AKASAKI","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921955,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921955","packageimage":"0041921955.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"Bunny Girl (Cover)","titleKana":"バニーガール","trackNo":5,"weblistsizeimage":"0041921955.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Afterglow","artistNameKana":"アフターグロウ","artistNameNo":0,"artistNo":2027484,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"UZ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198306","duration":235,"durationStr":"3:55","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921959.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921959.80.jpg","lyrics":"MOMIKEN","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921959,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921959","packageimage":"0041921959.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"オレンジ (Cover)","titleKana":"オレンジ","trackNo":6,"weblistsizeimage":"0041921959.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Pastel*Palettes","artistNameKana":"パステルパレット","artistNameNo":0,"artistNo":2027485,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"大石昌良","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198307","duration":215,"durationStr":"3:35","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921963.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921963.80.jpg","lyrics":"大石昌良","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921963,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921963","packageimage":"0041921963.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"サインはB (Cover)","titleKana":"サインハビー","trackNo":7,"weblistsizeimage":"0041921963.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Pastel*Palettes","artistNameKana":"パステルパレット","artistNameNo":0,"artistNo":2027485,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Carlos K. / 加賀爪タッド","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198308","duration":230,"durationStr":"3:50","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921964.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921964.80.jpg","lyrics":"Carlos K. / KANATA OKAJIMA","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921964,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921964","packageimage":"0041921964.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"だから、ひとりじゃない (Cover)","titleKana":"ダカラヒトリジャナイ","trackNo":8,"weblistsizeimage":"0041921964.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Pastel*Palettes","artistNameKana":"パステルパレット","artistNameNo":0,"artistNo":2027485,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"コレサワ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198309","duration":191,"durationStr":"3:11","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921969.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921969.80.jpg","lyrics":"コレサワ","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921969,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921969","packageimage":"0041921969.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"最上級にかわいいの! (Cover)","titleKana":"サイジョウキュウニカワイイノ","trackNo":9,"weblistsizeimage":"0041921969.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Roselia","artistNameKana":"ロゼリア","artistNameNo":0,"artistNo":2027487,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"キタニタツヤ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198310","duration":220,"durationStr":"3:40","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921972.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921972.80.jpg","lyrics":"キタニタツヤ","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921972,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921972","packageimage":"0041921972.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"ファタール (Cover)","titleKana":"ファタール","trackNo":10,"weblistsizeimage":"0041921972.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Roselia","artistNameKana":"ロゼリア","artistNameNo":0,"artistNo":2027487,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"DECO*27","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198311","duration":205,"durationStr":"3:25","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921975.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921975.80.jpg","lyrics":"DECO*27","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921975,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921975","packageimage":"0041921975.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"ヒバナ -Reloaded- (Cover)","titleKana":"ヒバナリローデッド","trackNo":11,"weblistsizeimage":"0041921975.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Roselia","artistNameKana":"ロゼリア","artistNameNo":0,"artistNo":2027487,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Tom-H@ck","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198312","duration":238,"durationStr":"3:58","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921977.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921977.80.jpg","lyrics":"烏屋茶房","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921977,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921977","packageimage":"0041921977.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"Reweave (Cover)","titleKana":"リウィーブ","trackNo":12,"weblistsizeimage":"0041921977.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Poppin'Party, 高松 燈(CV:羊宮妃那)","artistNameKana":"ポッピンパーティタカマツトモリヨウミヤヒナ","artistNameNo":0,"artistNo":2255981,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"藤井怜央","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198313","duration":275,"durationStr":"4:35","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921980.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921980.80.jpg","lyrics":"福島智朗","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921980,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921980","packageimage":"0041921980.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":null,"startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"幾億光年 (Cover)","titleKana":"イクオクコウネン","trackNo":13,"weblistsizeimage":"0041921980.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Pastel*Palettes, 美竹 蘭(CV:佐倉綾音)","artistNameKana":"パステルパレットミタケランサクラアヤネ","artistNameNo":0,"artistNo":2255982,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Gohgo / 涼木シンジ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198314","duration":222,"durationStr":"3:42","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921983.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921983.80.jpg","lyrics":"Gohgo","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921983,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921983","packageimage":"0041921983.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":null,"startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"愛包ダンスホール (Cover)","titleKana":"アイパイダンスホール","trackNo":14,"weblistsizeimage":"0041921983.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"ハロー、ハッピーワールド!","artistNameKana":"ハローハッピーワールド","artistNameNo":0,"artistNo":2027488,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Nakajin","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198315","duration":226,"durationStr":"3:46","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921987.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921987.80.jpg","lyrics":"Fukase","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921987,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921987","packageimage":"0041921987.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"最高到達点 (Cover)","titleKana":"サイコウトウタツテン","trackNo":15,"weblistsizeimage":"0041921987.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"ハロー、ハッピーワールド!","artistNameKana":"ハローハッピーワールド","artistNameNo":0,"artistNo":2027488,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"ゆこぴ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198316","duration":135,"durationStr":"2:15","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921989.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921989.80.jpg","lyrics":"ゆこぴ","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921989,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921989","packageimage":"0041921989.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"強風オールバック (Cover)","titleKana":"キョウフウオールバック","trackNo":16,"weblistsizeimage":"0041921989.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"ハロー、ハッピーワールド!","artistNameKana":"ハローハッピーワールド","artistNameNo":0,"artistNo":2027488,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"こっちのけんと / GRP","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198317","duration":160,"durationStr":"2:40","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921993.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921993.80.jpg","lyrics":"こっちのけんと","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921993,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921993","packageimage":"0041921993.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"はいよろこんで (Cover)","titleKana":"ハイヨロコンデ","trackNo":17,"weblistsizeimage":"0041921993.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Morfonica","artistNameKana":"モルフォニカ","artistNameNo":0,"artistNo":2013168,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"矢吹俊郎","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198318","duration":273,"durationStr":"4:33","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921994.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921994.80.jpg","lyrics":"奥井雅美","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921994,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921994","packageimage":"0041921994.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"輪舞-revolution (Cover)","titleKana":"ロンドレボリューション","trackNo":18,"weblistsizeimage":"0041921994.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Morfonica","artistNameKana":"モルフォニカ","artistNameNo":0,"artistNo":2013168,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Kanaria","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198319","duration":145,"durationStr":"2:25","endDate":null,"explicitFlg":"0","fullsizeimage":"0041921998.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041921998.80.jpg","lyrics":"Kanaria","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41921998,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041921998","packageimage":"0041921998.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"QUEEN (Cover)","titleKana":"クイーン","trackNo":19,"weblistsizeimage":"0041921998.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Morfonica","artistNameKana":"モルフォニカ","artistNameNo":0,"artistNo":2013168,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"YUI","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198320","duration":250,"durationStr":"4:10","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922001.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922001.80.jpg","lyrics":"YUI","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922001,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922001","packageimage":"0041922001.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"again (Cover)","titleKana":"アゲイン","trackNo":20,"weblistsizeimage":"0041922001.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"RAISE A SUILEN","artistNameKana":"レイズアスイレン","artistNameNo":0,"artistNo":2027489,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"DJ松永","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198321","duration":168,"durationStr":"2:48","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922004.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922004.80.jpg","lyrics":"R-指定","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922004,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922004","packageimage":"0041922004.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"Bling-Bang-Bang-Born (Cover)","titleKana":"ブリンバンバンボーン","trackNo":21,"weblistsizeimage":"0041922004.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"RAISE A SUILEN","artistNameKana":"レイズアスイレン","artistNameNo":0,"artistNo":2027489,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"Reol / Giga","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198322","duration":193,"durationStr":"3:13","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922007.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922007.80.jpg","lyrics":"Reol","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922007,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922007","packageimage":"0041922007.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"第六感 (Cover)","titleKana":"ダイロッカン","trackNo":22,"weblistsizeimage":"0041922007.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"MyGO!!!!!","artistNameKana":"マイゴ","artistNameNo":0,"artistNo":2007263,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"大濱健悟","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198323","duration":188,"durationStr":"3:08","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922009.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922009.80.jpg","lyrics":"大濱健悟","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922009,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922009","packageimage":"0041922009.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"雑踏、僕らの街 (Cover)","titleKana":"ザットウボクラノマチ","trackNo":23,"weblistsizeimage":"0041922009.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"MyGO!!!!!","artistNameKana":"マイゴ","artistNameNo":0,"artistNo":2007263,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"後藤正文","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198324","duration":249,"durationStr":"4:09","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922013.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922013.80.jpg","lyrics":"後藤正文","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922013,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922013","packageimage":"0041922013.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"遥か彼方 (Cover)","titleKana":"ハルカカナタ","trackNo":24,"weblistsizeimage":"0041922013.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"MyGO!!!!!","artistNameKana":"マイゴ","artistNameNo":0,"artistNo":2007263,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"ユリイ・カノン","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198325","duration":236,"durationStr":"3:56","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922014.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922014.80.jpg","lyrics":"ユリイ・カノン","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922014,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922014","packageimage":"0041922014.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":"","startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"だれかの心臓になれたなら (Cover)","titleKana":"ダレカノシンゾウニナレタナラ","trackNo":25,"weblistsizeimage":"0041922014.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"Roselia, レイヤ(CV:Raychell)","artistNameKana":"ロゼリアレイヤレイチェル","artistNameNo":0,"artistNo":2255983,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"ヒグチアイ","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198326","duration":227,"durationStr":"3:47","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922017.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922017.80.jpg","lyrics":"ヒグチアイ","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922017,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922017","packageimage":"0041922017.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":null,"startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"悪魔の子 (Cover)","titleKana":"アクマノコ","trackNo":26,"weblistsizeimage":"0041922017.130.jpg"},{"arranger":null,"arrangerKana":null,"artistName":"ハロー、ハッピーワールド!, 倉田ましろ(CV:進藤あまね)","artistNameKana":"ハローハッピーワールドクラタマシロシンドウアマネ","artistNameNo":0,"artistNo":2255984,"bitPerSample":"24","callCoupon":"0","channelConf":"2","composer":"和賀裕希","composerKana":null,"couponProduct":"0","distFlg":"0","distPartNo":"15198327","duration":202,"durationStr":"3:22","endDate":null,"explicitFlg":"0","fullsizeimage":"0041922018.200.jpg","labelCode":"43000035","labelId":"00000013","labelname":"ブシロードミュージック","listenDuration":90,"listenFlg":"1","listenStartDate":null,"listimage":"0041922018.80.jpg","lyrics":"やぎぬまかな","lyricsKana":null,"master":"(P)2025 BUSHIROAD MUSIC INC.","materialNo":41922018,"mediaFlg":"1","mediaFormatNo":12,"mediaType":8,"msin":null,"musicComment":null,"musicId":"PX0041922018","packageimage":"0041922018.100.jpg","prFlg":"0","price":550,"priceWithoutTax":500,"producer":null,"producerKana":null,"productTypeNo":9,"qualityClass":1,"samplingFreq":96000,"specialPageUrl":null,"startDate":"2025/10/15 00:00:00","tid":null,"tie":null,"tieType":null,"title":"シカ色デイズ (Cover)","titleKana":"シカイロデイズ","trackNo":27,"weblistsizeimage":"0041922018.130.jpg"}],"weblistsizeimage":"0041921939.130.jpg"} diff --git a/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/023/270/packageMeta.json b/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/023/270/packageMeta.json new file mode 100644 index 00000000..64702f67 --- /dev/null +++ b/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/023/270/packageMeta.json @@ -0,0 +1 @@ +{"artistName":"Ado","artistNameKana":"アド","artistNameNo":0,"artistNo":1310625,"bannerLinkUrl0":null,"bannerLinkUrl1":null,"bannerLinkUrl2":null,"bannerLinkUrl3":null,"bannerTargetBlank0":null,"bannerTargetBlank1":null,"bannerTargetBlank2":null,"bannerTargetBlank3":null,"bannerimage0":null,"bannerimage1":null,"bannerimage2":null,"bannerimage3":null,"bitPerSample":null,"callCoupon":"0","catchcopy":null,"cdPartNo":null,"channelConf":"2","comingSoon":null,"containCoupon":"0","couponProduct":"0","dispFlg":"0","dispStartDate":"2025/10/31 00:00:00","dispStartDateStr":"2025.10.31","displayLabelname":"ユニバーサル ミュージック合同会社","distFlg":"1","distPartNo":"00602488058599","endDate":null,"explicitFlg":"0","fullsizeimage":"0042023270.200.jpg","includedMedia":1,"labelCode":"43000006","labelId":"00000083","labelcompanyname":"Universal Music LLC","labelname":"ユニバーサル ミュージック合同会社","listimage":"0042023270.80.jpg","master":"A Virgin Music release; ℗ 2025 UNIVERSAL MUSIC LLC","materialNo":42023270,"mediaFlg":"1","mediaFormatNo":10,"mediaType":6,"metaDescription":null,"msin":null,"musicType":"0","packageComment":null,"packageId":"00602488058599","packageUrl":"https://cf.mora.jp/contents/package/0000/00000083/0042/023/270/","packageimage":"0042023270.100.jpg","prFlg":"0","price":null,"priceWithoutTax":null,"productTypeNo":9,"qualityClass":0,"relatedPackage":[],"samplingFreq":44100,"special":null,"specialPageUrl":"","startDate":"2025/10/31 00:00:00","tie":"","title":"MAGIC","titleKana":"マジック","trackList":[{"arranger":null,"arrangerKana":"","artistName":"Ado","artistNameKana":"アド","artistNameNo":0,"artistNo":1310625,"bitPerSample":null,"callCoupon":"0","channelConf":"2","composer":"ツミキ","composerKana":"","couponProduct":"0","distFlg":"0","distPartNo":"00602488058599-S01001","duration":172,"durationStr":"2:52","endDate":null,"explicitFlg":"0","fullsizeimage":"0042023271.200.jpg","labelCode":"43000006","labelId":"00000083","labelname":"Universal Music LLC","listenDuration":30,"listenFlg":"1","listenStartDate":null,"listimage":"0042023271.80.jpg","lyrics":"ツミキ","lyricsKana":"","master":"A Virgin Music release; ℗ 2025 UNIVERSAL MUSIC LLC","materialNo":42023271,"mediaFlg":"1","mediaFormatNo":10,"mediaType":6,"msin":null,"musicComment":null,"musicId":"PX0042023271","packageimage":"0042023271.100.jpg","prFlg":"0","price":261,"priceWithoutTax":238,"producer":null,"producerKana":"","productTypeNo":9,"qualityClass":0,"samplingFreq":44100,"specialPageUrl":"","startDate":"2025/10/31 00:00:00","tid":"381653","tie":null,"tieType":null,"title":"MAGIC","titleKana":"マジック","trackNo":1,"weblistsizeimage":"0042023271.130.jpg"}],"weblistsizeimage":"0042023270.130.jpg"} diff --git a/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/738/339/packageMeta.json b/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/738/339/packageMeta.json new file mode 100644 index 00000000..e15f5021 --- /dev/null +++ b/testdata/https!/jp.mora.cf/contents/package/0000/00000083/0042/738/339/packageMeta.json @@ -0,0 +1 @@ +{"artistName":"The Last Dinner Party","artistNameKana":"ザラストディナーパーティー","artistNameNo":0,"artistNo":1739884,"bannerLinkUrl0":null,"bannerLinkUrl1":null,"bannerLinkUrl2":null,"bannerLinkUrl3":null,"bannerTargetBlank0":null,"bannerTargetBlank1":null,"bannerTargetBlank2":null,"bannerTargetBlank3":null,"bannerimage0":null,"bannerimage1":null,"bannerimage2":null,"bannerimage3":null,"bitPerSample":null,"callCoupon":"0","catchcopy":null,"cdPartNo":null,"channelConf":"2","comingSoon":null,"containCoupon":"0","couponProduct":"0","dispFlg":"0","dispStartDate":"2025/11/22 00:00:00","dispStartDateStr":"2025.11.22","displayLabelname":"ユニバーサル ミュージック合同会社","distFlg":"1","distPartNo":"00199957093194","endDate":null,"explicitFlg":"0","fullsizeimage":"0042738339.200.jpg","includedMedia":2,"labelCode":"43000006","labelId":"00000083","labelcompanyname":"Universal-Island Records Ltd.","labelname":"ユニバーサル ミュージック合同会社","listimage":"0042738339.80.jpg","master":"© 2025 The Last Dinner Party, under exclusive licence to Universal Music Operations Limited","materialNo":42738339,"mediaFlg":"2","mediaFormatNo":11,"mediaType":7,"metaDescription":null,"msin":null,"musicType":"1","packageComment":null,"packageId":"00199957093194","packageUrl":"https://cf.mora.jp/contents/package/0000/00000083/0042/738/339/","packageimage":"0042738339.100.jpg","prFlg":"0","price":null,"priceWithoutTax":null,"productTypeNo":9,"qualityClass":0,"relatedPackage":[],"samplingFreq":48000,"special":null,"specialPageUrl":null,"startDate":"2025/11/22 00:00:00","tie":"","title":"Woman is a Tree","titleKana":"ウーマンイズアツリー","trackList":[{"arranger":null,"arrangerKana":"","artistName":"The Last Dinner Party","artistNameKana":"ザラストディナーパーティー","artistNameNo":0,"artistNo":1739884,"bitPerSample":null,"callCoupon":"0","channelConf":"2","composer":"Abigail Morris, Emily Roberts, Lizzie Mayland, Georgia Davies, Aurora Nishevci, Casper Miles, James Ford","composerKana":"","couponProduct":"0","distFlg":"0","distPartNo":"00199957093194-S01001","duration":239,"durationStr":"3:59","endDate":null,"explicitFlg":"0","fullsizeimage":"0042738340.200.jpg","labelCode":"43000006","labelId":"00000083","labelname":"Universal-Island Records Ltd.","listenDuration":null,"listenFlg":"0","listenStartDate":null,"listimage":"0042738340.80.jpg","lyrics":"Abigail Morris, Emily Roberts, Lizzie Mayland, Georgia Davies, Aurora Nishevci, Casper Miles, James Ford","lyricsKana":"","master":"© 2025 The Last Dinner Party, under exclusive licence to Universal Music Operations Limited","materialNo":42738340,"mediaFlg":"2","mediaFormatNo":11,"mediaType":7,"msin":null,"musicComment":null,"musicId":"PX0042738340","packageimage":"0042738340.100.jpg","prFlg":"0","price":419,"priceWithoutTax":381,"producer":null,"producerKana":"","productTypeNo":9,"qualityClass":0,"samplingFreq":48000,"specialPageUrl":null,"startDate":"2025/11/22 00:00:00","tid":null,"tie":null,"tieType":null,"title":"Woman is a Tree","titleKana":"ウーマンイズアツリー","trackNo":1,"weblistsizeimage":"0042738340.130.jpg"}],"weblistsizeimage":"0042738339.130.jpg"} diff --git a/testdata/https!/jp.mora/package/43000006/00199957093194 b/testdata/https!/jp.mora/package/43000006/00199957093194 new file mode 100644 index 00000000..0def3ca9 --- /dev/null +++ b/testdata/https!/jp.mora/package/43000006/00199957093194 @@ -0,0 +1 @@ +{"type":"package","mountPoint":"0000","labelId":"00000083","materialNo":"42738339"} \ No newline at end of file diff --git a/testdata/https!/jp.mora/package/43000006/00602488058599 b/testdata/https!/jp.mora/package/43000006/00602488058599 new file mode 100644 index 00000000..92eb3f3e --- /dev/null +++ b/testdata/https!/jp.mora/package/43000006/00602488058599 @@ -0,0 +1 @@ +{"type":"package","mountPoint":"0000","labelId":"00000083","materialNo":"42023270"} \ No newline at end of file diff --git a/testdata/https!/jp.mora/package/43000035/198704758065_F b/testdata/https!/jp.mora/package/43000035/198704758065_F new file mode 100644 index 00000000..c9bab658 --- /dev/null +++ b/testdata/https!/jp.mora/package/43000035/198704758065_F @@ -0,0 +1 @@ +{"type":"package","mountPoint":"0000","labelId":"00000013","materialNo":"41921939"} \ No newline at end of file