-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoperations.go
120 lines (97 loc) · 3.36 KB
/
operations.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
package main
import (
"fmt"
"io"
"regexp"
"strings"
"github.com/patrickmn/go-cache"
"github.com/thecsw/rei"
)
// MonokumaStatusCode is an enum for the status of a Monokuma request.
type MonokumaStatusCode uint8
const (
// LinkFound indicates that the link was found.
LinkFound MonokumaStatusCode = iota
// LinkNotFound indicates that the link was not found.
LinkNotFound
// BadKey indicates that the key was bad.
BadKey
// BadLink indicates that the link was bad.
BadLink
// LinkRetrievalError indicates that the link retrieval failed.
LinkRetrievalError
// Uncategorized indicates that the error was uncategorized.
Uncategorized
// Success indicates that the operation was successful.
Success
)
// keyRegexpPattern is the regular expression pattern for a key.
const keyRegexpPattern = `[-0-9a-zA-Z]{3,37}`
// keyRegexp is the regular expression for a key.
var keyRegexp = regexp.MustCompile(`^` + keyRegexpPattern + `$`)
// operationCreateLink takes a link and returns a key.
func operationCreateLink(linkReader io.Reader, customKey string) (string, MonokumaStatusCode, error) {
// Read the link.
linkBytes, err := io.ReadAll(linkReader)
if err != nil {
return "", Uncategorized, fmt.Errorf("reading the link: %v", err)
}
// Trim the link, a dirty sanitization.
link := strings.TrimSpace(string(linkBytes))
// If the link is empty, return an error.
if len(link) < 1 {
return "", BadLink, fmt.Errorf("link is empty")
}
// If the link is too long, return an error.
if len(strings.Split(link, "\n")) > 1 {
return "", BadLink, fmt.Errorf("link contains newlines")
}
// If the link does not match the regular expression, return an error.
if !URLRegexp.MatchString(link) {
return "", BadLink, fmt.Errorf("link is invalid, it needs to match regex: %s", URLRegexpPattern)
}
// Try to write the link.
key, err := monomi.writeLink(rei.Btao([]byte(link)), customKey)
if err != nil {
return "", Uncategorized, fmt.Errorf("shortening the link: %v", err)
}
// Return the key.
return key, Success, nil
}
// operationKeyToLink takes a key and returns the final link.
func operationKeyToLink(key string) (string, MonokumaStatusCode, error) {
// Check the key against the regular expression.
if !keyRegexp.MatchString(key) {
return "", BadKey, fmt.Errorf("key %s is invalid, needs to match %s", key, keyRegexpPattern)
}
// Check the cache for the key.
if finalUrl, found := keyToUrl.Get(key); found {
return finalUrl.(string), LinkFound, nil
}
// If the key is empty, return an error.
linkb64, found, err := monomi.getLink(key)
if err != nil {
return "", LinkRetrievalError, fmt.Errorf("critical failure during retrieval: %v", err)
}
// If the key is not found, return an error.
if !found {
return "", LinkNotFound, fmt.Errorf("short url for %s not found", key)
}
// Decode the link.
finalUrl := string(rei.AtobMust(linkb64))
// Add the mapping to the cache.
keyToUrl.Add(key, finalUrl, cache.DefaultExpiration)
// Return the final link after it's been cached.
return finalUrl, LinkFound, nil
}
// operationExportLinks exports all links.
func operationExportLinks() ([]string, MonokumaStatusCode, error) {
// Get the links.
links, err := monomi.exportLinks()
// Return a generic error if possible.
if err != nil {
return nil, Uncategorized, fmt.Errorf("critical failure during export: %v", err)
}
// Got the links.
return links, Success, nil
}