diff --git a/main.go b/main.go index 6f0fc71..d1bbec2 100644 --- a/main.go +++ b/main.go @@ -22,13 +22,19 @@ import ( "time" ) +type OriginalBlog struct { + Id string `json:"id"` + Author Account `json:"account"` +} + type Blog struct { - Id string `json:"id"` - Content string `json:"content"` - Date string `json:"created_at"` - Author Account `json:"account"` - Tags []Tag `json:"tags"` - Mentions []Mention `json:"mentions"` + Id string `json:"id"` + Content string `json:"content"` + Date string `json:"created_at"` + Author Account `json:"account"` + Tags []Tag `json:"tags"` + Mentions []Mention `json:"mentions"` + Reblog *OriginalBlog `json:"reblog"` } type Config struct { diff --git a/mastoUtil.go b/mastoUtil.go index cec8cf9..4537ca0 100644 --- a/mastoUtil.go +++ b/mastoUtil.go @@ -25,6 +25,41 @@ import ( "fmt" ) +func getBlogAndReblog(baseURL, account string) ([]Blog, error) { + if baseURL == "" || account == "" { + log.Println("baseURL or account is empty") + return nil, fmt.Errorf("BaseURL or account is empty") + } + + resp, err := http.Get(baseURL + "/api/v1/accounts/" + account + "/statuses?exclude_reblogs=false&exclude_replies=true") + if err != nil { + log.Println("Mastodon API request: %s", err) + return nil, fmt.Errorf("Failed to request Mastodon API") + } + + defer resp.Body.Close() + + if resp.StatusCode != 200 { + log.Println("Mastodon API response: %s", resp.Status) + return nil, fmt.Errorf("Mastodon instance failed") + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println("Mastodon response body: %s", err) + return nil, fmt.Errorf("Failed to read Mastodon response body") + } + + var blogs []Blog + err = json.Unmarshal(body, &blogs) + if err != nil { + log.Println("Mastodon response %s", err) + return nil, fmt.Errorf("Failed to parse Mastodon response") + } + + return blogs, nil +} + func getBlog(baseURL, account string) ([]Blog, error) { if baseURL == "" || account == "" { log.Println("baseURL or account is empty") diff --git a/server.go b/server.go index 6a08c2a..58bccba 100644 --- a/server.go +++ b/server.go @@ -125,22 +125,39 @@ func handleConn(conn *tls.Conn, baseURL, title, home_message string, rateLimit i // profile if strings.HasPrefix(path, "/profile/") { - // skip prefix - path = path[9:] - _, err = strconv.ParseUint(path, 10, 64) - if err != nil { - log.Println("invalid request: %s", err) - _, err = fmt.Fprintf(conn, "59 Can't parse request\r\n") + if strings.HasSuffix(path, "/reblog") { + // skip prefix and suffix + path = path[9:len(path)-len("/reblog")] + _, err = strconv.ParseUint(path, 10, 64) if err != nil { - log.Println("send error: %s", err) + log.Println("invalid request: %s", err) + _, err = fmt.Fprintf(conn, "59 Can't parse request\r\n") + if err != nil { + log.Println("send error: %s", err) + return + } return } - return + + log.Println("Received request for account with reblog " + path) + printProfileWithReblog(conn, baseURL, path) + } else { + // skip prefix + path = path[9:] + _, err = strconv.ParseUint(path, 10, 64) + if err != nil { + log.Println("invalid request: %s", err) + _, err = fmt.Fprintf(conn, "59 Can't parse request\r\n") + if err != nil { + log.Println("send error: %s", err) + return + } + return + } + + log.Println("Received request for account " + path) + printProfile(conn, baseURL, path) } - - log.Println("Received request for account " + path) - - printProfile(conn, baseURL, path) } /* thread */ else if strings.HasPrefix(path, "/thread/") { // skip prefix path = path[8:] @@ -257,7 +274,49 @@ func printProfile(conn *tls.Conn, baseURL, profileID string) { } } - _, err = fmt.Fprintf(conn, "\n=> %s Go to %s account", account.Url, account.Name) + _, err = fmt.Fprintf(conn, "\n=> /profile/%s/reblog This profile with reblog\n=> %s Go to %s account", account.Id, account.Url, account.Name) + if err != nil { + log.Println("add link: %s", err) + return + } +} + +func printProfileWithReblog(conn *tls.Conn, baseURL, profileID string) { + account, err := getAccount(baseURL, profileID) + if err != nil { + _, err = fmt.Fprintf(conn, "40 Remote mastodon instance failed\r\n") + if err != nil { + log.Println("handleConn: %s", err) + return + } + return + } + + blogs, err := getBlogAndReblog(baseURL, profileID) + if err != nil { + _, err = fmt.Fprintf(conn, "40 Remote mastodon instance failed\r\n") + if err != nil { + log.Println("handleConn: %s", err) + return + } + return + } + + _, err = fmt.Fprintf(conn, "20 text/gemini\r\n# Toots for %s account\n", account.Name) + if err != nil { + log.Println("handleConn: %s", err) + return + } + + for _, blog := range blogs { + _, err = fmt.Fprintf(conn, "\n%s\n=> /thread/%s View the thread\n", formatBlog(blog), blog.Id) + if err != nil { + log.Println("read blogs: %s", err) + return + } + } + + _, err = fmt.Fprintf(conn, "\n=> /profile/%s This profile without reblog\n=> %s Go to %s account", account.Id, account.Url, account.Name) if err != nil { log.Println("add link: %s", err) return @@ -283,10 +342,18 @@ func printToot(conn *tls.Conn, baseURL, tootID string) { } // Print toot - _, err = fmt.Fprintf(conn, "# Toot\n\n%s\n=> /thread/%s View the thread\n=> /profile/%s More toots from %s\n", formatBlog(toot), toot.Id, toot.Author.Id, toot.Author.Name) - if err != nil { - log.Println("handleConn: %s", err) - return + if toot.Reblog == nil { + _, err = fmt.Fprintf(conn, "# Toot\n\n%s\n=> /thread/%s View the thread\n=> /profile/%s More toots from %s\n", formatBlog(toot), toot.Id, toot.Author.Id, toot.Author.Name) + if err != nil { + log.Println("handleConn: %s", err) + return + } + } else { + _, err = fmt.Fprintf(conn, "# Toot\n\n%s\n=> /toot/%s Original toot\n=> /thread/%s View the thread\n=> /profile/%s More toots from %s\n=> /profile/%s More toots from %s\n", formatBlog(toot), toot.Reblog.Id, toot.Id, toot.Author.Id, toot.Author.Name, toot.Reblog.Author.Id, toot.Reblog.Author.Name) + if err != nil { + log.Println("handleConn: %s", err) + return + } } // print mentions diff --git a/util.go b/util.go index 96befb6..0e1b89b 100644 --- a/util.go +++ b/util.go @@ -104,7 +104,18 @@ func formatBlog(toot Blog) string { author = toot.Author.DisplayName } - return "### Written by " + author + " on " + toot.Date[0:10] + " at " + toot.Date[11:16] + "\n" + content + "\n=> /toot/" + toot.Id + " More informations about this toot" + if toot.Reblog == nil { + return "### Written by " + author + " on " + toot.Date[0:10] + " at " + toot.Date[11:16] + "\n" + content + "\n=> /toot/" + toot.Id + " More informations about this toot" + } else { + var originalAuthor string + if toot.Reblog.Author.DisplayName == "" { + originalAuthor = toot.Reblog.Author.Name + } else { + originalAuthor = toot.Reblog.Author.DisplayName + } + + return "### Shared by " + author + " on " + toot.Date[0:10] + " at " + toot.Date[11:16] + " (original by " + originalAuthor + ")\n" + content + "\n=> /toot/" + toot.Id + " More informations about this toot" + } } func rateIsOk(tab map[string]Rate, remoteIP string, limit int) bool {