-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathTibiaDataUtils.go
359 lines (304 loc) · 9.69 KB
/
TibiaDataUtils.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
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
package main
import (
"html"
"io"
"log"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang.org/x/text/cases"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/language"
"golang.org/x/text/unicode/norm"
)
// TibiaDataDatetime func
func TibiaDataDatetime(date string) string {
//TODO: Normalization needs to happen above this layer
date = norm.NFKC.String(date)
var (
returnDate time.Time
err error
)
// If statement to determine if date string is filled or empty
if date == "" {
// The string that should be returned is the current timestamp
returnDate = time.Now()
} else {
// timezone use in html: CET/CEST
loc, _ := time.LoadLocation("Europe/Berlin")
// format used in datetime on html: Jan 02 2007, 19:20:30 CET
var formatting string
// parsing and setting format of return
switch dateLength := len(date); {
case dateLength > 19:
// format used in datetime on html: Jan 02 2007, 19:20:30 CET
formatting = "Jan 02 2006, 15:04:05 MST"
case dateLength == 19:
// format used in datetime on html: 03.06.2023 01:19:00
formatting = "02.01.2006 15:04:05"
default:
log.Printf("Weird format detected: %s", date)
}
// parsing html in time with location set in loc
returnDate, err = time.ParseInLocation(formatting, date, loc)
// parsing html in tiem without loc
//returnDate, err = time.Parse("Jan 02 2006, 15:04:05 MST", date)
if err != nil {
log.Println(err)
}
}
// Return of formatted date and time string to functions..
return returnDate.UTC().Format(time.RFC3339)
}
// TibiaDataHTMLRemoveLinebreaks func
func TibiaDataHTMLRemoveLinebreaks(data string) string {
return strings.ReplaceAll(data, "\n", "")
}
var removeUrlRegex = regexp.MustCompile(`<a.*>(.*)<\/a>`)
// TibiaDataRemoveURLs func
func TibiaDataRemoveURLs(data string) string {
// prepare return value
var returnData string
result := removeUrlRegex.FindAllStringSubmatch(data, -1)
if len(result) > 0 {
returnData = result[0][1]
} else {
returnData = ""
}
return returnData
}
// TibiaDataStringWorldFormatToTitle func
func TibiaDataStringWorldFormatToTitle(world string) string {
return cases.Title(language.English).String(world)
}
// TibiaDataQueryEscapeString func - encode string to be correct formatted
func TibiaDataQueryEscapeString(data string) string {
// switching "+" to " "
data = strings.ReplaceAll(data, "+", " ")
// encoding string to latin-1
data, _ = TibiaDataConvertEncodingtoISO88591(data)
// returning with QueryEscape function
return url.QueryEscape(data)
}
// TibiaDataDate func
func TibiaDataDate(date string) string {
// removing weird spacing and comma
date = TibiaDataSanitizeStrings(strings.ReplaceAll(date, ",", ""))
// var time parser
var tmpDate time.Time
// parsing and setting format of return
switch dateLength := len(date); {
case dateLength == 5:
// date that contains special formatting only used in date a world was created
tmpDate, _ = time.Parse("01/06", date)
// we need to return earlier as well, since we don't have the day
return tmpDate.UTC().Format("2006-01")
case dateLength == 11:
// dates that contain first 3 letters in month
tmpDate, _ = time.Parse("Jan 02 2006", date)
case dateLength > 11:
// dates that contain month fully written
tmpDate, _ = time.Parse("January 2 2006", date)
default:
log.Printf("Weird format detected: %s", date)
}
return tmpDate.UTC().Format("2006-01-02")
}
// TibiaDataStringToInteger converts a string to an int
func TibiaDataStringToInteger(data string) int {
str := strings.ReplaceAll(data, ",", "")
returnData, err := strconv.Atoi(str)
if err != nil {
log.Printf("[warning] TibiaDataStringToInteger: couldn't convert string into int. error: %s", err)
}
return returnData
}
const (
htmlTagStart = 60 // Unicode `<`
htmlTagEnd = 62 // Unicode `>`
)
// RemoveHtmlTag replaces all HTML tags with an empty string
//
// Algo from:
// https://stackoverflow.com/questions/55036156/how-to-replace-all-html-tag-with-empty-string-in-golang
func RemoveHtmlTag(s string) string {
// Setup a string builder and allocate enough memory for the new string.
var builder strings.Builder
builder.Grow(len(s) + utf8.UTFMax)
in := false // True if we are inside an HTML tag.
start := 0 // The index of the previous start tag character `<`
end := 0 // The index of the previous end tag character `>`
for i, c := range s {
// If this is the last character and we are not in an HTML tag, save it.
if (i+1) == len(s) && end >= start {
builder.WriteString(s[end:])
}
// Keep going if the character is not `<` or `>`
if c != htmlTagStart && c != htmlTagEnd {
continue
}
if c == htmlTagStart {
// Only update the start if we are not in a tag.
// This make sure we strip out `<<br>` not just `<br>`
if !in {
start = i
}
in = true
// Write the valid string between the close and start of the two tags.
builder.WriteString(s[end:start])
continue
}
// else c == htmlTagEnd
in = false
end = i + 1
}
s = builder.String()
return s
}
// TibiaDataConvertEncodingtoISO88591 func - convert string from UTF-8 to latin1 (ISO 8859-1)
func TibiaDataConvertEncodingtoISO88591(data string) (string, error) {
return charmap.ISO8859_1.NewEncoder().String(data)
}
// TibiaDataConvertEncodingtoUTF8 func - convert string from latin1 (ISO 8859-1) to UTF-8
func TibiaDataConvertEncodingtoUTF8(data io.Reader) io.Reader {
return norm.NFKC.Reader(charmap.ISO8859_1.NewDecoder().Reader(data))
}
// TibiaDataSanitizeEscapedString func - run unescape string on string
func TibiaDataSanitizeEscapedString(data string) string {
return html.UnescapeString(data)
}
// TibiaDataSanitizeDoubleQuoteString func - replaces double quotes to single quotes in strings
func TibiaDataSanitizeDoubleQuoteString(data string) string {
return strings.ReplaceAll(data, "\"", "'")
}
// TibiaDataSanitizeStrings func - replacing various encoded strings to pure html
func TibiaDataSanitizeStrings(data string) string {
// replaces weird \u00A0 string to real space
data = strings.ReplaceAll(data, "\u00A0", " ")
// replaces weird \u0026 string to amp (&)
data = strings.ReplaceAll(data, "\u0026", "&")
// returning string unescaped
return TibiaDataSanitizeEscapedString(data)
}
// TibiaDataSanitize0026String replaces \u0026#39; with '
func TibiaDataSanitize0026String(data string) string {
return strings.ReplaceAll(data, "\u0026#39;", "'")
}
// isEnvExist func - check if environment var is set and not empty
func isEnvExist(key string) bool {
data, ok := os.LookupEnv(key)
return ok && data != ""
}
// getEnv func - read an environment or return a default value
func getEnv(key string, defaultVal string) string {
if value, exists := os.LookupEnv(key); exists && value != "" {
return value
}
return defaultVal
}
// getEnvAsBool func - read an environment variable into a bool or return default value
func getEnvAsBool(name string, defaultVal bool) bool {
valStr := getEnv(name, "")
if val, err := strconv.ParseBool(valStr); err == nil {
return val
}
return defaultVal
}
/*
// getEnvAsFloat func - read an environment variable into a float64 or return default value
func getEnvAsFloat(name string, defaultVal float64) float64 {
valStr := getEnv(name, "")
if val, err := strconv.ParseFloat(valStr, 64); err == nil {
return val
}
return defaultVal
}
// getEnvAsInt func - read an environment variable into integer or return a default value
func getEnvAsInt(name string, defaultVal int) int {
valueStr := getEnv(name, "")
if value, err := strconv.Atoi(valueStr); err == nil {
return value
}
return defaultVal
}
*/
// TibiaDataConvertValuesWithK func - convert price strings that contain k, kk or more to 3x0
func TibiaDataConvertValuesWithK(data string) int {
return TibiaDataStringToInteger(strings.ReplaceAll(data, "k", "") + strings.Repeat("000", strings.Count(data, "k")))
}
// TibiaDataVocationValidator func - return valid vocation string and vocation id
func TibiaDataVocationValidator(vocation string) (string, string) {
// defining return vars
var vocationid string
switch strings.ToLower(vocation) {
case "none":
vocationid = "1"
vocation = "none"
case "knight", "knights":
vocationid = "2"
vocation = "knights"
case "paladin", "paladins":
vocationid = "3"
vocation = "paladins"
case "sorcerer", "sorcerers":
vocationid = "4"
vocation = "sorcerers"
case "druid", "druids":
vocationid = "5"
vocation = "druids"
default:
vocationid = "0"
vocation = "all"
}
// returning vars
return vocation, vocationid
}
// TibiaDataGetNewsCategory func - extract news category by newsicon
func TibiaDataGetNewsCategory(data string) string {
switch {
case strings.Contains(data, "newsicon_cipsoft"):
return "cipsoft"
case strings.Contains(data, "newsicon_community"):
return "community"
case strings.Contains(data, "newsicon_development"):
return "development"
case strings.Contains(data, "newsicon_support"):
return "support"
case strings.Contains(data, "newsicon_technical"):
return "technical"
default:
return "unknown"
}
}
// TibiaDataGetNewsType func - extract news type
func TibiaDataGetNewsType(data string) string {
switch data {
case "News Ticker":
return "ticker"
case "Featured Article":
return "article"
case "News":
return "news"
default:
return "unknown"
}
}
// TibiaDataForumNameValidator func - return valid forum string
func TibiaDataForumNameValidator(name string) string {
switch strings.ToLower(name) {
case "world boards", "world", "worldboards":
return "worldboards"
case "trade boards", "trade", "tradeboards":
return "tradeboards"
case "community boards", "community", "communityboards":
return "communityboards"
case "support boards", "support", "supportboards":
return "supportboards"
default:
return "worldboards"
}
}