1
2 package util
3
4 import (
5 "fmt"
6 "html/template"
7 "math"
8 "net/http"
9 "regexp"
10 "sort"
11 "strconv"
12 "strings"
13 "time"
14
15 "golang.org/x/exp/constraints"
16 )
17
18 const NewDirPermission = 0755
19 const NewFilePermission = 0640
20
21 var (
22 AlphaNumericAndSymbols = regexp.MustCompile(`^[0-9A-Za-z_-]+$`)
23
24 QuotePattern = regexp.MustCompile(`^>(.*)$`)
25
26 RefLinkPattern = regexp.MustCompile(`>>([0-9]+)`)
27 BoardLinkPattern = regexp.MustCompile(`>>>\/([0-9A-Za-z_-]+)?\/?`)
28
29 URLPattern = regexp.MustCompile(`(?i)(((f|ht)tp(s)?:\/\/)[-a-zA-Zа-яА-Я()0-9@%\!_+.,~#?&;:|\'\/=]+)`)
30 FixURLPattern1 = regexp.MustCompile(`(?i)\(\<a href\=\"(.*)\)"\ target\=\"\_blank\">(.*)\)\<\/a>`)
31 FixURLPattern2 = regexp.MustCompile(`(?i)\<a href\=\"(.*)\."\ target\=\"\_blank\">(.*)\.\<\/a>`)
32 FixURLPattern3 = regexp.MustCompile(`(?i)\<a href\=\"(.*)\,"\ target\=\"\_blank\">(.*)\,\<\/a>`)
33 )
34
35 func ParseInt(v string) int {
36 i, err := strconv.Atoi(v)
37 if err == nil && i > 0 {
38 return i
39 }
40 return 0
41 }
42
43 func ParseInt64(v string) int64 {
44 i, err := strconv.ParseInt(v, 10, 64)
45 if err == nil && i > 0 {
46 return i
47 }
48 return 0
49 }
50
51 func ParseFloat(v string) float64 {
52 i, err := strconv.ParseFloat(v, 64)
53 if err == nil && i > 0 {
54 return i
55 }
56 return 0
57 }
58
59 func FormString(r *http.Request, key string) string {
60 return strings.TrimSpace(r.FormValue(key))
61 }
62
63 func FormMultiString(r *http.Request, key string) []string {
64 formKeys := make([]string, len(r.Form))
65 var i int
66 for key := range r.Form {
67 formKeys[i] = key
68 i++
69 }
70 sort.Slice(formKeys, func(i, j int) bool {
71 return formKeys[i] < formKeys[j]
72 })
73 var values []string
74 for _, formKey := range formKeys {
75 formValues := r.Form[formKey]
76 if strings.HasPrefix(formKey, key+"_") {
77 for _, v := range formValues {
78 if strings.TrimSpace(v) == "" {
79 continue
80 }
81 values = append(values, v)
82 }
83 }
84 }
85 return values
86 }
87
88 func FormInt(r *http.Request, key string) int {
89 v, err := strconv.Atoi(FormString(r, key))
90 if err == nil && v >= 0 {
91 return v
92 }
93 return 0
94 }
95
96 func FormInt64(r *http.Request, key string) int64 {
97 v, err := strconv.ParseInt(FormString(r, key), 10, 64)
98 if err == nil && v >= 0 {
99 return v
100 }
101 return 0
102 }
103
104 func FormNegInt(r *http.Request, key string) int {
105 v, err := strconv.Atoi(FormString(r, key))
106 if err == nil {
107 return v
108 }
109 return 0
110 }
111
112 func FormBool(r *http.Request, key string) bool {
113 return FormInt(r, key) == 1
114 }
115
116 func FormRange[T constraints.Integer](r *http.Request, key string, min T, max T) T {
117 v := FormInt(r, key)
118 if v >= int(min) && v <= int(max) {
119 return T(v)
120 }
121 return min
122 }
123
124 func PathInt(r *http.Request, prefix string) int {
125 pathValue := PathString(r, prefix)
126 if pathValue != "" {
127 v, err := strconv.Atoi(pathValue)
128 if err == nil && v > 0 {
129 return v
130 }
131 }
132 return 0
133 }
134
135 func PathString(r *http.Request, prefix string) string {
136 if !strings.HasPrefix(r.URL.Path, prefix) {
137 return ""
138 }
139 return strings.TrimPrefix(r.URL.Path, prefix)
140 }
141
142 func MIMEToExt(mimeType string) string {
143 switch mimeType {
144 case "image/jpeg", "image/pjpeg":
145 return "jpg"
146 case "image/gif":
147 return "gif"
148 case "image/png":
149 return "png"
150 default:
151 return ""
152 }
153 }
154
155 func FormatTimestamp(timestamp int64) template.HTML {
156 return template.HTML(time.Unix(timestamp, 0).Format("2006/01/02<wbr>(Mon)<wbr>15:04:05"))
157 }
158
159 func FormatRawTimestamp(timestamp int64) string {
160 return time.Unix(timestamp, 0).Format("2006/01/02(Mon)15:04:05")
161 }
162
163 func FormatFileSize(size int64) string {
164 v := float64(size)
165 for _, unit := range []string{"", "K", "M", "G", "T", "P", "E", "Z"} {
166 if math.Abs(v) < 1024.0 {
167 return fmt.Sprintf("%.0f%sB", v, unit)
168 }
169 v /= 1024.0
170 }
171 return fmt.Sprintf("%.0fYB", v)
172 }
173
View as plain text