-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathelement.go
336 lines (292 loc) · 10.4 KB
/
element.go
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
package anitogo
type elementCategory int
// Elements is a struct representing a parsed anime filename.
type Elements struct {
// Slice of strings representing the season of anime. "S1-S3" would be represented as []string{"1", "3"}.
AnimeSeason []string `json:"anime_season,omitempty"`
// Represents the strings prefixing the season in the file, e.g in "SEASON 2" "SEASON" is the AnimeSeasonPrefix.
AnimeSeasonPrefix []string `json:"anime_season_prefix,omitempty"`
// Title of the Anime. e.g in "[HorribleSubs] Boku no Hero Academia - 01 [1080p].mkv",
// "Boku No Hero Academia" is the AnimeTitle.
AnimeTitle string `json:"anime_title,omitempty"`
// Slice of strings representing the types specified in the anime file, e.g ED, OP, Movie, etc.
AnimeType []string `json:"anime_type,omitempty"`
// Year the anime was released.
AnimeYear string `json:"anime_year,omitempty"`
// Slice of strings representing the audio terms included in the filename, e.g FLAC, AAC, etc.
AudioTerm []string `json:"audio_term,omitempty"`
// Slice of strings representing devices the video is compatible with that are mentioned in the filename.
DeviceCompatibility []string `json:"device_compatibility,omitempty"`
// Slice of strings representing the episode numbers. "01-10" would be respresented as []string{"1", "10"}.
EpisodeNumber []string `json:"episode_number,omitempty"`
// Slice of strings representing the alternative episode number.
// This is for cases where you may have an episode number relative to the season,
// but a larger episode number as if it were all one season.
// e.g in [Hatsuyuki]_Kuroko_no_Basuke_S3_-_01_(51)_[720p][10bit][619C57A0].mkv
// 01 would be the EpisodeNumber, and 51 would be the EpisodeNumberAlt.
EpisodeNumberAlt []string `json:"episode_number_alt,omitempty"`
// Slice of strings representing the words prefixing the episode number in the file, e.g in "EPISODE 2", "EPISODE" is the prefix.
EpisodePrefix []string `json:"episode_prefix,omitempty"`
// Title of the episode. e.g in "[BM&T] Toradora! - 07v2 - Pool Opening [720p Hi10 ] [BD] [8F59F2BA]",
// "Pool Opening" is the EpisodeTitle.
EpisodeTitle string `json:"episode_title,omitempty"`
// Checksum of the file, in [BM&T] Toradora! - 07v2 - Pool Opening [720p Hi10 ] [BD] [8F59F2BA],
// "8F59F2BA" would be the FileChecksum.
FileChecksum string `json:"file_checksum,omitempty"`
// File extension, in [HorribleSubs] Boku no Hero Academia - 01 [1080p].mkv,
// "mkv" would be the FileExtension.
FileExtension string `json:"file_extension,omitempty"`
// Full filename that was parsed.
FileName string `json:"file_name,omitempty"`
// Languages specified in the file name, e.g RU, JP, EN etc.
Language []string `json:"language,omitempty"`
// Terms that could not be parsed into other buckets, but were deemed identifiers.
// In [chibi-Doki] Seikon no Qwaser - 13v0 (Uncensored Director's Cut) [988DB090].mkv,
// "Uncensored" is parsed into Other.
Other []string `json:"other,omitempty"`
// The fan sub group that uploaded the file. In [HorribleSubs] Boku no Hero Academia - 01 [1080p],
// "HorribleSubs" is the ReleaseGroup.
ReleaseGroup string `json:"release_group,omitempty"`
// Information about the release that wasn't a version.
// In "[SubDESU-H] Swing out Sisters Complete Version (720p x264 8bit AC3) [3ABD57E6].mp4
// "Complete" is parsed into ReleaseInformation.
ReleaseInformation []string `json:"release_information,omitempty"`
// Slice of strings representing the version of the release.
// In [FBI] Baby Princess 3D Paradise Love 01v0 [BD][720p-AAC][457CC066].mkv, 0 is parsed into ReleaseVersion.
ReleaseVersion []string `json:"release_version,omitempty"`
// Slice of strings representing where the video was ripped from. e.g BLU-RAY, DVD, etc.
Source []string `json:"source,omitempty"`
// Slice of strings representing the type of subtitles included, e.g HARDSUB, BIG5, etc.
Subtitles []string `json:"subtitles,omitempty"`
// Resolution of the video. Can be formatted like 1920x1080, 1080, 1080p, etc depending
// on how it is represented in the filename.
VideoResolution string `json:"video_resolution,omitempty"`
// Slice of strings representing the video terms included in the filename, e.g h264, x264, etc.
VideoTerm []string `json:"video_term,omitempty"`
// Slice of strings represnting the volume numbers. "01-10" would be represented as []string{"1", "10"}.
VolumeNumber []string `json:"volume_number,omitempty"`
// Slice of strings representing the words prefixing the volume number in the file, e.g in "VOLUME 2", "VOLUME" is the prefix.
VolumePrefix []string `json:"volume_prefix,omitempty"`
// Entries that could not be parsed into any other categories.
Unknown []string `json:"unknown,omitempty"`
// Bool determining if "EpisodeNumberAlt" should be parsed or not.
checkAltNumber bool
}
const (
elementCategoryAnimeSeason elementCategory = iota
elementCategoryAnimeSeasonPrefix
elementCategoryAnimeTitle
elementCategoryAnimeType
elementCategoryAnimeYear
elementCategoryAudioTerm
elementCategoryDeviceCompatibility
elementCategoryEpisodeNumber
elementCategoryEpisodeNumberAlt
elementCategoryEpisodePrefix
elementCategoryEpisodeTitle
elementCategoryFileChecksum
elementCategoryFileExtension
elementCategoryFileName
elementCategoryLanguage
elementCategoryOther
elementCategoryReleaseGroup
elementCategoryReleaseInformation
elementCategoryReleaseVersion
elementCategorySource
elementCategorySubtitles
elementCategoryVideoResolution
elementCategoryVideoTerm
elementCategoryVolumeNumber
elementCategoryVolumePrefix
elementCategoryUnknown
)
func (e *Elements) getCheckAltNumber() bool {
return e.checkAltNumber
}
func (e *Elements) setCheckAltNumber(value bool) {
e.checkAltNumber = value
}
func (e *Elements) getSingleElementField(cat elementCategory) (bool, *string) {
switch cat {
case elementCategoryAnimeTitle:
return true, &e.AnimeTitle
case elementCategoryAnimeYear:
return true, &e.AnimeYear
case elementCategoryEpisodeTitle:
return true, &e.EpisodeTitle
case elementCategoryFileChecksum:
return true, &e.FileChecksum
case elementCategoryFileExtension:
return true, &e.FileExtension
case elementCategoryFileName:
return true, &e.FileName
case elementCategoryReleaseGroup:
return true, &e.ReleaseGroup
case elementCategoryVideoResolution:
return true, &e.VideoResolution
}
var s string
return false, &s
}
func (e *Elements) getMultiElementField(cat elementCategory) (bool, *[]string) {
switch cat {
case elementCategoryAnimeSeason:
return true, &e.AnimeSeason
case elementCategoryAnimeSeasonPrefix:
return true, &e.AnimeSeasonPrefix
case elementCategoryAnimeType:
return true, &e.AnimeType
case elementCategoryAudioTerm:
return true, &e.AudioTerm
case elementCategoryDeviceCompatibility:
return true, &e.DeviceCompatibility
case elementCategoryEpisodeNumber:
return true, &e.EpisodeNumber
case elementCategoryEpisodeNumberAlt:
return true, &e.EpisodeNumberAlt
case elementCategoryEpisodePrefix:
return true, &e.EpisodePrefix
case elementCategoryLanguage:
return true, &e.Language
case elementCategoryOther:
return true, &e.Other
case elementCategoryReleaseInformation:
return true, &e.ReleaseInformation
case elementCategoryReleaseVersion:
return true, &e.ReleaseVersion
case elementCategorySource:
return true, &e.Source
case elementCategorySubtitles:
return true, &e.Subtitles
case elementCategoryVideoTerm:
return true, &e.VideoTerm
case elementCategoryVolumeNumber:
return true, &e.VolumeNumber
case elementCategoryVolumePrefix:
return true, &e.VolumePrefix
case elementCategoryUnknown:
return true, &e.Unknown
}
return false, &[]string{}
}
func (e *Elements) insert(cat elementCategory, content string) {
found, targetSingle := e.getSingleElementField(cat)
if found {
*targetSingle = content
return
}
found, targetMulti := e.getMultiElementField(cat)
if found {
if checkInList(*targetMulti, content) {
return
}
*targetMulti = append(*targetMulti, content)
return
}
}
func (e *Elements) erase(cat elementCategory) {
found, targetSingle := e.getSingleElementField(cat)
if found {
*targetSingle = ""
return
}
found, targetMulti := e.getMultiElementField(cat)
if found {
*targetMulti = nil
return
}
}
func (e *Elements) remove(cat elementCategory, content string) {
found, targetSingle := e.getSingleElementField(cat)
if found {
*targetSingle = ""
return
}
found, targetMulti := e.getMultiElementField(cat)
if found {
idx := getIndex(*targetMulti, content)
if idx == -1 {
return
}
*targetMulti = append((*targetMulti)[:idx], (*targetMulti)[idx+1:]...)
return
}
}
func (e *Elements) contains(cat elementCategory) bool {
found, targetSingle := e.getSingleElementField(cat)
if found {
return *targetSingle != ""
}
_, targetMulti := e.getMultiElementField(cat)
return *targetMulti != nil
}
func (e *Elements) get(cat elementCategory) []string {
found, targetSingle := e.getSingleElementField(cat)
if found {
return []string{*targetSingle}
}
_, targetMulti := e.getMultiElementField(cat)
return *targetMulti
}
func (e elementCategory) isSearchable() bool {
searchableCategories := []elementCategory{
elementCategoryAnimeSeasonPrefix,
elementCategoryAnimeType,
elementCategoryAudioTerm,
elementCategoryDeviceCompatibility,
elementCategoryEpisodePrefix,
elementCategoryFileChecksum,
elementCategoryLanguage,
elementCategoryOther,
elementCategoryReleaseGroup,
elementCategoryReleaseInformation,
elementCategoryReleaseVersion,
elementCategorySource,
elementCategorySubtitles,
elementCategoryVideoResolution,
elementCategoryVideoTerm,
elementCategoryVolumePrefix,
}
for _, v := range searchableCategories {
if e == v {
return true
}
}
return false
}
func (e elementCategory) isSingular() bool {
nonSingularCategories := []elementCategory{
elementCategoryAnimeSeason,
elementCategoryAnimeType,
elementCategoryAudioTerm,
elementCategoryDeviceCompatibility,
elementCategoryEpisodeNumber,
elementCategoryLanguage,
elementCategoryOther,
elementCategoryReleaseInformation,
elementCategorySource,
elementCategoryVideoTerm,
}
for _, v := range nonSingularCategories {
if e == v {
return false
}
}
return true
}
func checkInList(arr []string, content string) bool {
for _, v := range arr {
if v == content {
return true
}
}
return false
}
func getIndex(arr []string, content string) int {
for i, v := range arr {
if v == content {
return i
}
}
return -1
}