From 51cd907c72dd6bcfb8d77704ed9ee4934b14f7cc Mon Sep 17 00:00:00 2001 From: Yonah Date: Thu, 18 Sep 2025 20:10:32 +0900 Subject: [PATCH] album: zero fields for variants This eliminates code duplication in some areas of the server. Signed-off-by: Yonah --- album.go | 56 ++++++++++++++++++++++ album_test.go | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) diff --git a/album.go b/album.go index 2a5ab43..1ef7727 100644 --- a/album.go +++ b/album.go @@ -39,8 +39,64 @@ type Album struct { Artists []string `json:"artistes"` } +const ( + // AlbumVariantCurrent copies the current variant as-is. + AlbumVariantCurrent = iota + // AlbumVariantFull leaves all fields intact in the copy. + // This variant is not returned by any endpoint and is obtained via [Album.Enrich]. + AlbumVariantFull + // AlbumVariantDetail zeroes [Album.Artists]. + // This variant is returned by /api/album/%s/detail. + AlbumVariantDetail + // AlbumVariantData zeroes [Album.Songs]. + // This variant is returned by /api/album/%d/data. + AlbumVariantData + // AlbumVariantBase zeroes [Album.Intro], [Album.Belong], [Album.CoverDeURL], [Album.Songs]. + // This variant is included in /api/albums. + AlbumVariantBase +) + func (a *Album) IsFull() bool { return a.Belong != "" && len(a.Songs) > 0 } +// Copy makes a copy of [Album]. +// For an [Album] where the IsFull method returns true, Copy zeroes fields to convert the copy into other variants. +// For [Album] where IsFull returns false, any variant other than current is undefined. +func (a *Album) Copy(variant int) *Album { + if a == nil { + return nil + } + + v := *a + if variant == AlbumVariantCurrent { + return &v + } + if !a.IsFull() { + return nil + } + + switch variant { + case AlbumVariantFull: + break + + case AlbumVariantDetail: + a.Artists = nil + + case AlbumVariantData: + a.Songs = nil + + case AlbumVariantBase: + a.Intro = "" + a.Belong = "" + a.CoverDeURL = "" + a.Songs = nil + + default: + return nil + } + + return a +} + // Enrich populates the remaining fields of a non-full [Album]. func (a *Album) Enrich(ctx context.Context, n Net) error { if a == nil || a.IsFull() { diff --git a/album_test.go b/album_test.go index f7fd4c8..a1bb99d 100644 --- a/album_test.go +++ b/album_test.go @@ -27,6 +27,131 @@ func TestAlbum(t *testing.T) { CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, }}, albumDataJSON) + + t.Run("copy", func(t *testing.T) { + testCases := []struct { + name string + a *Album + variant int + want *Album + }{ + {"nil", nil, AlbumVariantDetail, nil}, + {"current", new(Album), AlbumVariantCurrent, new(Album)}, + {"full guard", new(Album), AlbumVariantDetail, nil}, + + {"current full", &Album{ + Belong: "\x00", + Songs: []AlbumSong{{}}, + }, AlbumVariantCurrent, &Album{ + Belong: "\x00", + Songs: []AlbumSong{{}}, + }}, + + {"oob", &Album{ + Belong: "\x00", + Songs: []AlbumSong{{}}, + }, 0xbad, nil}, + + {"full", &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }, AlbumVariantFull, &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }}, + + {"detail", &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }, AlbumVariantDetail, &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + }}, + + {"data", &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }, AlbumVariantData, &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }}, + + {"base", &Album{ + CID: 1030, + Name: "Speed of Light", + Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单,亦或是复杂,大地和天空始终让开始与结束相连。 \n《Speed of Light》,通过乐调铺陈的驰放与内敛感,希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行,如企鹅物流般永不停歇。", + Belong: "arknights", + CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Songs: []AlbumSong{ + {CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}}, + {CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}}, + }, + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }, AlbumVariantBase, &Album{ + CID: 1030, + Name: "Speed of Light", + CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg", + Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}, + }}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if got := tc.a.Copy(tc.variant); !reflect.DeepEqual(got, tc.want) { + t.Errorf("Copy: %#v, want %#v", got, tc.want) + } + }) + } + }) } func TestAlbumEnrich(t *testing.T) {