diff --git a/.example.env b/.example.env index 8255aa7..c994d07 100644 --- a/.example.env +++ b/.example.env @@ -1,2 +1,3 @@ TWITTER_CLIENT_ID=********************************** TWITTER_CLIENT_SECRET=************************************************** +INSTANCES_SOCIAL_TOKEN=******************************************************************************************************************************** diff --git a/components/datalists_options.templ b/components/datalists_options.templ new file mode 100644 index 0000000..230a8cd --- /dev/null +++ b/components/datalists_options.templ @@ -0,0 +1,97 @@ +package components + +import ( + "os" + "net/url" + "net/http" + "encoding/json" + "log" + "slices" + "extrovert/internals" + "fmt" + "errors" +) + +type Instance struct { + Name string `json:"name"` +} + +func fetchInstanceList(limit int) ([]Instance, error) { + + u, err := url.ParseRequestURI("https://instances.social/api/1.0/instances/list") + if err != nil { + return []Instance{}, err + } + + u.Query().Add("min_version", "0.1.0") + u.Query().Add("sort_by", "active_users") + u.Query().Add("count", fmt.Sprintf("%v", limit)) + u.Query().Add("prohibted_content", "nudity_nocw") + u.Query().Add("prohibted_content", "pornography_nocw") + u.Query().Add("prohibted_content", "illegalContentLinks") + u.Query().Add("prohibted_content", "spam") + u.Query().Add("prohibted_content", "advertising") + + req, err := http.NewRequest(http.MethodGet, u.String(), bytes.NewReader([]byte(""))) + if err != nil { + return []Instance{}, err + } + req.Header.Add("Authorization", "Bearer "+os.Getenv("INSTANCES_SOCIAL_TOKEN")) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return []Instance{}, err + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return []Instance{}, err + } else if res.StatusCode != 200 { + return []Instance{}, errors.New(string(body)) + } + + var list struct { + Instances []Instance `json:"instances"` + } + err = json.Unmarshal(body, &list) + + return list.Instances, err +} + +var INSTANCES = []Instance{ + /* + These servers are not endorsed, curated or affiliated by Capytal in any way, shape + or form. All the instances where got from the top 15 listed in https://joinmastodon.org/servers, + at July 8th, 2024 (2024-07-08). + */ + {Name: "mastodon.social"}, + {Name: "mstdn.social"}, + {Name: "mas.to"}, + {Name: "social.vivaldi.net"}, + {Name: "mastodonapp.uk"}, + {Name: "universeodon.com"}, + {Name: "c.im"}, + {Name: "mstdn.party"}, + {Name: "toot.community"}, + {Name: "ohai.social"}, + {Name: "mstdn.business"}, + {Name: "ieji.de"}, + {Name: "toot.io"}, + {Name: "masto.nu"}, + {Name: "mstdn.plus"}, +} + +func getInstanceList(limit int) []Instance { + i, err := fetchInstanceList(limit) + if err != nil { + log.Printf("WARN: Unable to fetch Mastodon instance datalist due to:\n%s\n\nFall backing into static list.", err.Error()) + return INSTANCES + } + return internals.RemoveDuplicates(slices.Concat(INSTANCES, i)) +} + +templ InstancesOptions(limit int) { + for _, v := range getInstanceList(limit) { + + } +} diff --git a/components/logins.templ b/components/logins.templ index a9cfd0f..f97eb83 100644 --- a/components/logins.templ +++ b/components/logins.templ @@ -21,3 +21,32 @@ var loginUrl = fmt.Sprintf("https://x.com/i/oauth2/authorize"+ templ LoginTwitter() { Login on Twitter } + +templ LoginMastodon() { + +
+ +
+
+ + +
+ + + @InstancesOptions(20) + +
+
+
+} diff --git a/internals/helpers.go b/internals/helpers.go index 4188c14..b6bf129 100644 --- a/internals/helpers.go +++ b/internals/helpers.go @@ -6,6 +6,18 @@ import ( "slices" ) +func RemoveDuplicates[T comparable](slice []T) []T { + keys := make(map[T]bool) + list := []T{} + for _, entry := range slice { + if _, value := keys[entry]; !value { + keys[entry] = true + list = append(list, entry) + } + } + return list +} + func GetCookie(name string, w http.ResponseWriter, r *http.Request) *http.Cookie { name = fmt.Sprintf("__Host-%s-%s-%s", APP_NAME, APP_VERSION, name) diff --git a/routes/index.templ b/routes/index.templ index c8bb9d2..a7e69a1 100644 --- a/routes/index.templ +++ b/routes/index.templ @@ -21,13 +21,13 @@ templ IndexPage() {
-
-
+
@components.LoginTwitter() - -
+ @components.LoginMastodon() +
-
+