rc-1
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"html"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
snowflakeMutex sync.Mutex
|
||||
snowflakeMachineID int64
|
||||
snowflakeSequence int64
|
||||
snowflakeTimestamp int64
|
||||
|
||||
// Updates to normalizers here should be mirrored in `GET_Limits.go`!
|
||||
|
||||
RegexSpaces = regexp.MustCompile(`\s{2,}`)
|
||||
RegexUnderscores = regexp.MustCompile(`_+`)
|
||||
RegexNewlines = regexp.MustCompile(`\n{2,}`)
|
||||
RegexMatcherTitle = regexp.MustCompile(`^[\S\s]{1,80}$`)
|
||||
RegexMatcherTag = regexp.MustCompile(`^[\p{L}\p{N}_]{1,32}$`)
|
||||
RegexMatcherComment = regexp.MustCompile(`^[\S\s]{10,240}$`)
|
||||
)
|
||||
|
||||
func NormalizeTitle(str string) (string, bool) {
|
||||
if str == "" {
|
||||
return str, false
|
||||
}
|
||||
if !RegexMatcherTitle.MatchString(str) {
|
||||
return str, false
|
||||
}
|
||||
str = RegexSpaces.ReplaceAllString(str, " ")
|
||||
str = strings.TrimSpace(str)
|
||||
str = html.EscapeString(str)
|
||||
return str, true
|
||||
}
|
||||
|
||||
func NormalizeTag(str string) (string, bool) {
|
||||
if str == "" {
|
||||
return str, false
|
||||
}
|
||||
if !RegexMatcherTag.MatchString(str) {
|
||||
return str, false
|
||||
}
|
||||
str = RegexUnderscores.ReplaceAllString(str, "_")
|
||||
str = strings.Trim(str, "_")
|
||||
str = strings.ToUpper(str)
|
||||
return str, true
|
||||
}
|
||||
|
||||
func NormalizeComment(str string) (string, bool) {
|
||||
if str == "" {
|
||||
return str, false
|
||||
}
|
||||
if !RegexMatcherComment.MatchString(str) {
|
||||
return str, false
|
||||
}
|
||||
str = RegexNewlines.ReplaceAllString(str, " ")
|
||||
str = strings.TrimSpace(str)
|
||||
str = html.EscapeString(str)
|
||||
return str, true
|
||||
}
|
||||
|
||||
func ParseLimit(str string) int {
|
||||
v, _ := strconv.Atoi(str)
|
||||
return min(100, max(1, v))
|
||||
}
|
||||
|
||||
func ParseSnowflake(str string) int64 {
|
||||
v, err := strconv.ParseInt(str, 10, 64)
|
||||
if err != nil || v < 1 {
|
||||
return 0
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func ParseJSON(r io.Reader, v any) error {
|
||||
l := io.LimitReader(r, int64(LIMIT_JSON))
|
||||
d := json.NewDecoder(l)
|
||||
d.DisallowUnknownFields()
|
||||
return d.Decode(v)
|
||||
}
|
||||
|
||||
// Generate a Unique Snowflake
|
||||
func RequestSnowflake() int64 {
|
||||
snowflakeMutex.Lock()
|
||||
defer snowflakeMutex.Unlock()
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
if now != snowflakeTimestamp {
|
||||
snowflakeSequence = 0
|
||||
} else {
|
||||
snowflakeSequence++
|
||||
if snowflakeSequence > SNOWFLAKE_MAX_SEQUENCE {
|
||||
for now <= snowflakeTimestamp {
|
||||
time.Sleep(time.Millisecond)
|
||||
now = time.Now().UnixMilli()
|
||||
}
|
||||
snowflakeSequence = 0
|
||||
}
|
||||
}
|
||||
|
||||
snowflakeTimestamp = now
|
||||
return ((now - SNOWFLAKE_EPOCH_MILLI) << 22) | (snowflakeMachineID << 12) | snowflakeSequence
|
||||
}
|
||||
|
||||
// Generate a Hex String out of random bytes
|
||||
func RequestToken() string {
|
||||
b := make([]byte, 32)
|
||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||
panic("failed to generate enough random bytes")
|
||||
}
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
// Generate a SHA256 Hex String from a given string
|
||||
func RequestHash(str string) string {
|
||||
h := sha256.Sum256([]byte(str))
|
||||
return hex.EncodeToString(h[:])
|
||||
}
|
||||
|
||||
// Get the Client IP Address as a SHA256 Hex String
|
||||
func RequestAddressHash(r *http.Request) string {
|
||||
return RequestHash(RequestAddress(r))
|
||||
}
|
||||
|
||||
// Get the Client IP Address
|
||||
func RequestAddress(r *http.Request) string {
|
||||
if HTTP_PROXY != "" {
|
||||
return r.Header.Get(HTTP_PROXY)
|
||||
}
|
||||
addr, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return addr
|
||||
}
|
||||
Reference in New Issue
Block a user