summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/mappings.go110
-rw-r--r--services/services.go93
2 files changed, 203 insertions, 0 deletions
diff --git a/services/mappings.go b/services/mappings.go
new file mode 100644
index 0000000..53731a6
--- /dev/null
+++ b/services/mappings.go
@@ -0,0 +1,110 @@
+package services
+
+import (
+ "errors"
+ "math/rand"
+ "regexp"
+)
+
+type RegexMapping struct {
+ Pattern *regexp.Regexp
+ Targets []string
+}
+
+var regexMap = []RegexMapping{
+ {
+ // YouTube
+ Pattern: regexp.MustCompile(`youtu(\.be|be\.com)|invidious|piped`),
+ Targets: []string{"piped", "invidious"},
+ },
+ {
+ // Twitter / X
+ Pattern: regexp.MustCompile(`twitter\.com|x\.com|nitter`),
+ Targets: []string{"nitter"},
+ },
+ {
+ // Reddit
+ Pattern: regexp.MustCompile(`reddit\.com|libreddit|redlib`),
+ Targets: []string{"libreddit", "redlib"},
+ },
+ {
+ // Google Search
+ Pattern: regexp.MustCompile(`google\.com|whoogle|searx|searxng`),
+ Targets: []string{"whoogle", "searx", "searxng"},
+ },
+ {
+ // Instagram
+ Pattern: regexp.MustCompile(`instagram\.com|proxigram`),
+ Targets: []string{"proxigram"},
+ },
+ {
+ // Wikipedia
+ Pattern: regexp.MustCompile(`wikipedia\.org|wikiless`),
+ Targets: []string{"wikiless"},
+ },
+ {
+ // Medium
+ Pattern: regexp.MustCompile(`medium\.com|scribe`),
+ Targets: []string{"scribe"},
+ },
+ {
+ // Odysee
+ Pattern: regexp.MustCompile(`odysee\.com|librarian`),
+ Targets: []string{"librarian"},
+ },
+ {
+ // Imgur
+ Pattern: regexp.MustCompile(`imgur\.com|rimgo`),
+ Targets: []string{"rimgo"},
+ },
+ {
+ // Google Translate
+ Pattern: regexp.MustCompile(`translate\.google\.com|lingva`),
+ Targets: []string{"lingva"},
+ },
+ {
+ // TikTok
+ Pattern: regexp.MustCompile(`tiktok\.com|proxitok`),
+ Targets: []string{"proxitok"},
+ },
+ {
+ // Fandom
+ Pattern: regexp.MustCompile(`fandom\.com|breezewiki`),
+ Targets: []string{"breezewiki"},
+ },
+ {
+ // IMDB
+ Pattern: regexp.MustCompile(`imdb\.com|libremdb`),
+ Targets: []string{"libremdb"},
+ },
+ {
+ // Quora
+ Pattern: regexp.MustCompile(`quora\.com|quetre`),
+ Targets: []string{"quetre"},
+ },
+ {
+ // GitHub
+ Pattern: regexp.MustCompile(`github\.com|gothub`),
+ Targets: []string{"gothub"},
+ },
+ {
+ // StackOverflow
+ Pattern: regexp.MustCompile(`stackoverflow\.com|anonymousoverflow`),
+ Targets: []string{"anonymousoverflow"},
+ },
+}
+
+func MatchRequest(service string) (string, error) {
+ for _, mapping := range regexMap {
+ hasMatch := mapping.Pattern.MatchString(service)
+ if !hasMatch {
+ continue
+ }
+
+ index := rand.Intn(len(mapping.Targets))
+ value := mapping.Targets[index]
+ return value, nil
+ }
+
+ return "", errors.New("no match found")
+}
diff --git a/services/services.go b/services/services.go
new file mode 100644
index 0000000..b9e5693
--- /dev/null
+++ b/services/services.go
@@ -0,0 +1,93 @@
+package services
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+ "os"
+)
+
+var (
+ ServiceList []Service
+ FallbackMap map[string]string
+)
+
+const (
+ baseRepoLink = "https://git.sr.ht/~benbusby/farside/blob/main/"
+
+ noCFServicesJSON = "services.json"
+ fullServicesJSON = "services-full.json"
+)
+
+type Service struct {
+ Type string `json:"type"`
+ TestURL string `json:"test_url,omitempty"`
+ Fallback string `json:"fallback,omimtempty"`
+ Instances []string `json:"instances"`
+}
+
+func ingestServicesList(servicesBytes []byte) error {
+ err := json.Unmarshal(servicesBytes, &ServiceList)
+ return err
+}
+
+func GetServicesFileName() string {
+ cloudflareEnabled := false
+
+ cfEnabledVar := os.Getenv("FARSIDE_CF_ENABLED")
+ if len(cfEnabledVar) > 0 && cfEnabledVar == "1" {
+ cloudflareEnabled = true
+ }
+
+ serviceJSON := noCFServicesJSON
+ if cloudflareEnabled {
+ serviceJSON = fullServicesJSON
+ }
+
+ return serviceJSON
+}
+
+
+func FetchServicesFile(serviceJSON string) ([]byte, error) {
+ resp, err := http.Get(baseRepoLink + serviceJSON)
+ if err != nil {
+ return nil, err
+ }
+
+ defer resp.Body.Close()
+
+ bodyBytes, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ err = os.WriteFile(serviceJSON, bodyBytes, 0666)
+ if err != nil {
+ return nil, err
+ }
+
+ return bodyBytes, nil
+}
+
+func InitializeServices() error {
+ serviceJSON := GetServicesFileName()
+ fileBytes, err := os.ReadFile(serviceJSON)
+ if err != nil {
+ fileBytes, err = FetchServicesFile(serviceJSON)
+ if err != nil {
+ return err
+ }
+ }
+
+ err = ingestServicesList(fileBytes)
+ if err != nil {
+ return err
+ }
+
+ FallbackMap = make(map[string]string)
+ for _, serviceElement := range ServiceList {
+ FallbackMap[serviceElement.Type] = serviceElement.Fallback
+ }
+
+ return nil
+}