commit 2f2183cd2349530513ca8aa7b2d856827ea9d61e
parent 5df16c096c92cbe1008ed8bb3ee1d0b53bd27762
Author: alex wennerberg <alex@alexwennerberg.com>
Date: Sun, 24 Oct 2021 18:03:20 -0700
Create pinky client
Diffstat:
A | pinky.go | | | 105 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 105 insertions(+), 0 deletions(-)
diff --git a/pinky.go b/pinky.go
@@ -0,0 +1,105 @@
+package main
+
+// A very simple client for the Pinky aggregation format
+// https://alex.flounder.online/tech/pinky.gmi
+// Only supports finger ATM
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "net"
+ "net/url"
+ "os"
+ "strings"
+ "time"
+)
+
+const LAYOUT = "2006-01"
+
+func main() {
+ configPath := "pinky-urls"
+ file, err := os.Open(configPath)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+
+ dates := make(map[string][]string)
+ for scanner.Scan() {
+ t := scanner.Text()
+ // TODO goroutine
+ date, err := getDate(t) // yyyy-mm formatted date
+ if err != nil {
+ // log.Println(err)
+ continue
+ }
+ _, ok := dates[date]
+ if !ok {
+ dates[date] = []string{}
+ }
+ dates[date] = append(dates[date], t)
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ keys := make([]string, 0, len(dates))
+ for k := range dates {
+ keys = append(keys, k)
+ }
+ for _, k := range keys {
+ fmt.Println(k)
+ for _, u := range dates[k] {
+ fmt.Println(u)
+ }
+ }
+}
+
+// returns yyyy-mm
+func getDate(myurl string) (string, error) {
+ log.Println("Getting date for " + myurl)
+ u, err := url.Parse(myurl)
+ if err != nil {
+ return "", err
+ }
+ switch u.Scheme {
+ // This is a draft spec: https://datatracker.ietf.org/doc/html/draft-ietf-uri-url-finger-02
+ case "finger":
+ return getFingerDate(u)
+ }
+ return "", fmt.Errorf("invalid protocol")
+}
+
+func getFingerDate(url *url.URL) (string, error) {
+ conn, err := net.DialTimeout("tcp", url.Host+":79", 5*time.Second)
+ if err != nil {
+ return "", err
+ }
+ defer conn.Close()
+ _, err = conn.Write([]byte(url.Path[1:] + "\r\n"))
+ scanner := bufio.NewScanner(conn)
+ n := 0
+ for scanner.Scan() {
+ t := scanner.Text()
+ // fmt.Println(t)
+ if strings.HasPrefix(t, "Updated: ") {
+ spl := strings.Split(t, " ")
+ u, err := time.Parse(LAYOUT, spl[1])
+ if u.After(time.Now()) {
+ return "", fmt.Errorf("In the future")
+ }
+ if err == nil {
+ return spl[1], nil
+ }
+ }
+ n++
+ if n >= 3 {
+ break
+ }
+ }
+ return "", fmt.Errorf("No valid updated field found")
+}