1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package main
// Redacted release types.
//
// https://redacted.sh/wiki.php?action=article&id=455#_1804298149
//
// The API is inconsistent about whether it reports a release type as its
// numeric key or its display string, so every comparison must accept both. The
// SQL queries take an array containing *both* spellings of each disallowed type
// for the same reason.
import (
"sort"
"strconv"
"strings"
)
type releaseType struct {
IntKey int
StringKey string
}
var (
releaseTypeAlbum = releaseType{1, "Album"}
releaseTypeSoundtrack = releaseType{3, "Soundtrack"}
releaseTypeEP = releaseType{5, "EP"}
releaseTypeAnthology = releaseType{6, "Anthology"}
releaseTypeCompilation = releaseType{7, "Compilation"}
releaseTypeSingle = releaseType{9, "Single"}
releaseTypeLiveAlbum = releaseType{11, "Live album"}
releaseTypeRemix = releaseType{13, "Remix"}
releaseTypeBootleg = releaseType{14, "Bootleg"}
releaseTypeInterview = releaseType{15, "Interview"}
releaseTypeMixtape = releaseType{16, "Mixtape"}
releaseTypeDemo = releaseType{17, "Demo"}
releaseTypeConcertRecording = releaseType{18, "Concert Recording"}
releaseTypeDJMix = releaseType{19, "DJ Mix"}
releaseTypeUnknown = releaseType{21, "Unknown"}
releaseTypeProducedBy = releaseType{1021, "Produced By"}
releaseTypeComposition = releaseType{1022, "Composition"}
releaseTypeRemixedBy = releaseType{1023, "Remixed By"}
releaseTypeGuestAppearance = releaseType{1024, "Guest Appearance"}
)
// allReleaseTypesSorted is in the display order used to group the torrent
// tables; the order is meaningful and is not alphabetical.
var allReleaseTypesSorted = []releaseType{
releaseTypeAlbum,
releaseTypeLiveAlbum,
releaseTypeAnthology,
releaseTypeSoundtrack,
releaseTypeEP,
releaseTypeCompilation,
releaseTypeSingle,
releaseTypeRemix,
releaseTypeBootleg,
releaseTypeInterview,
releaseTypeMixtape,
releaseTypeDemo,
releaseTypeConcertRecording,
releaseTypeDJMix,
releaseTypeUnknown,
releaseTypeProducedBy,
releaseTypeComposition,
releaseTypeRemixedBy,
releaseTypeGuestAppearance,
}
// releaseTypeFromTextOrIntKey resolves either spelling.
//
// Unknown values are preserved verbatim with an IntKey of -1 rather than being
// dropped, so a newly added upstream type still displays.
func releaseTypeFromTextOrIntKey(t string) releaseType {
for _, rt := range allReleaseTypesSorted {
if rt.StringKey == t || strconv.Itoa(rt.IntKey) == t {
return rt
}
}
return releaseType{IntKey: -1, StringKey: t}
}
// releaseTypeSortIndex gives the position in allReleaseTypesSorted, with
// unknown types sorted last.
func releaseTypeSortIndex(rt releaseType) int {
for i, known := range allReleaseTypesSorted {
if known.IntKey == rt.IntKey && known.StringKey == rt.StringKey {
return i
}
}
return len(allReleaseTypesSorted)
}
// disallowedReleaseTypeStrings renders release types for the SQL comparisons,
// which test `<> ALL (...)` against a text array.
//
// Both spellings are emitted because the stored JSON may contain either.
func disallowedReleaseTypeStrings(types []releaseType) []string {
out := make([]string, 0, len(types)*2)
for _, rt := range types {
out = append(out, rt.StringKey, strconv.Itoa(rt.IntKey))
}
return out
}
// releaseTypesOverapproximatedWithout builds the `releasetype` search parameter.
//
// The search API lets us say which release types we want, but not which we do
// not want. So we enumerate a deliberately over-wide range of ids and subtract
// the unwanted ones: new upstream types are then included automatically rather
// than silently disappearing from search results.
func releaseTypesOverapproximatedWithout(disallowed ...releaseType) string {
excluded := map[int]bool{}
for _, rt := range disallowed {
excluded[rt.IntKey] = true
}
var ids []int
for i := 1; i <= 50; i++ {
if !excluded[i] {
ids = append(ids, i)
}
}
for i := 1000; i <= 1050; i++ {
if !excluded[i] {
ids = append(ids, i)
}
}
sort.Ints(ids)
parts := make([]string, len(ids))
for i, id := range ids {
parts[i] = strconv.Itoa(id)
}
return strings.Join(parts, ",")
}
|