Add support for media proxying and use io instead of deprecated io/ioutil

This commit is contained in:
Romain de Laage 2022-04-30 14:32:28 +02:00
parent 1ae21d1c2b
commit 52103bd76d
Signed by: rdelaage
GPG Key ID: 534845FADDF0C329
4 changed files with 111 additions and 10 deletions

View File

@ -35,6 +35,11 @@ type Blog struct {
Tags []Tag `json:"tags"` Tags []Tag `json:"tags"`
Mentions []Mention `json:"mentions"` Mentions []Mention `json:"mentions"`
Reblog *OriginalBlog `json:"reblog"` Reblog *OriginalBlog `json:"reblog"`
Medias []Media `json:"media_attachments"`
}
type Media struct {
Url string `json:"url"`
} }
type Config struct { type Config struct {

View File

@ -21,7 +21,7 @@ import (
"net/http" "net/http"
"log" "log"
"encoding/json" "encoding/json"
"io/ioutil" "io"
"fmt" "fmt"
) )
@ -44,7 +44,7 @@ func getBlogAndReblog(baseURL, account string) ([]Blog, error) {
return nil, fmt.Errorf("Mastodon instance failed") return nil, fmt.Errorf("Mastodon instance failed")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return nil, fmt.Errorf("Failed to read Mastodon response body") return nil, fmt.Errorf("Failed to read Mastodon response body")
@ -79,7 +79,7 @@ func getBlog(baseURL, account string) ([]Blog, error) {
return nil, fmt.Errorf("Mastodon instance failed") return nil, fmt.Errorf("Mastodon instance failed")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return nil, fmt.Errorf("Failed to read Mastodon response body") return nil, fmt.Errorf("Failed to read Mastodon response body")
@ -116,7 +116,7 @@ func getTimeline(baseURL string) ([]Blog, error) {
return toots, fmt.Errorf("API response is not 200") return toots, fmt.Errorf("API response is not 200")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return toots, fmt.Errorf("Failed to read response") return toots, fmt.Errorf("Failed to read response")
@ -150,7 +150,7 @@ func getAccount(baseURL, accountId string) (Account, error) {
return Account{}, fmt.Errorf("API response is not 200") return Account{}, fmt.Errorf("API response is not 200")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return Account{}, fmt.Errorf("Failed to read response") return Account{}, fmt.Errorf("Failed to read response")
@ -185,7 +185,7 @@ func getToot(baseURL, tootId string) (Blog, error) {
return Blog{}, fmt.Errorf("API response is not 200") return Blog{}, fmt.Errorf("API response is not 200")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return Blog{}, fmt.Errorf("Failed to read response") return Blog{}, fmt.Errorf("Failed to read response")
@ -201,6 +201,34 @@ func getToot(baseURL, tootId string) (Blog, error) {
return toot, nil return toot, nil
} }
func getMedia(mediaURL string) (string, []byte, error) {
if mediaURL == "" {
log.Println("mediaURL is empty")
return "", nil, fmt.Errorf("mediaURL is empty")
}
resp, err := http.Get(mediaURL)
if err != nil {
log.Println("Mastodon API request: %s", err)
return "", nil, fmt.Errorf("API request failed")
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
log.Println("Mastodon API response: %s", resp.Status)
return "", nil, fmt.Errorf("API response is not 200")
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Println("Mastodon response body: %s", err)
return "", nil, fmt.Errorf("Failed to read response")
}
return resp.Header["Content-Type"][0], body , nil
}
func getThread(baseURL, tootId string) (Thread, error) { func getThread(baseURL, tootId string) (Thread, error) {
if baseURL == "" || tootId == "" { if baseURL == "" || tootId == "" {
log.Println("baseURL or tootID is empty") log.Println("baseURL or tootID is empty")
@ -220,7 +248,7 @@ func getThread(baseURL, tootId string) (Thread, error) {
return Thread{}, fmt.Errorf("API response is not 200") return Thread{}, fmt.Errorf("API response is not 200")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return Thread{}, fmt.Errorf("Failed to read response") return Thread{}, fmt.Errorf("Failed to read response")
@ -255,7 +283,7 @@ func getTag(baseURL, tag string) ([]Blog, error) {
return nil, fmt.Errorf("API response is not 200") return nil, fmt.Errorf("API response is not 200")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Println("Mastodon response body: %s", err) log.Println("Mastodon response body: %s", err)
return nil, fmt.Errorf("Failed to read response") return nil, fmt.Errorf("Failed to read response")

View File

@ -234,6 +234,19 @@ This capsule use %s Mastodon instance.
log.Println("Received request for timeline") log.Println("Received request for timeline")
printTimeline(conn, baseURL) printTimeline(conn, baseURL)
} /* media */ else if strings.HasPrefix(path, "/media") {
if query == "" {
_, err = fmt.Fprintf(conn, "59 Invalid request\r\n")
if err != nil {
log.Println("send: %s", err)
return
}
return
}
log.Println("Received request for media " + query)
proxyMedia(conn, baseURL, query)
} else { } else {
_, err = fmt.Fprintf(conn, "59 Invalid request\r\n") _, err = fmt.Fprintf(conn, "59 Invalid request\r\n")
if err != nil { if err != nil {
@ -243,6 +256,49 @@ This capsule use %s Mastodon instance.
} }
} }
func proxyMedia(conn *tls.Conn, baseURL, query string) {
mediaURL, err := url.QueryUnescape(query)
if err != nil {
_, err = fmt.Fprintf(conn, "59 Invalid url encoded media\r\n")
if err != nil {
log.Println("handleConn: %s", err)
return
}
return
}
if !strings.HasPrefix(mediaURL, baseURL) {
_, err = fmt.Fprintf(conn, "59 Invalid media url\r\n")
if err != nil {
log.Println("handleConn: %s", err)
return
}
return
}
mime, media, err := getMedia(mediaURL)
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 %s\r\n", mime)
if err != nil {
log.Println("handleConn: %s", err)
return
}
_, err = conn.Write(media)
if err != nil {
log.Println("handleConn: %s", err)
return
}
}
func printProfile(conn *tls.Conn, baseURL, profileID string) { func printProfile(conn *tls.Conn, baseURL, profileID string) {
account, err := getAccount(baseURL, profileID) account, err := getAccount(baseURL, profileID)
if err != nil { if err != nil {

16
util.go
View File

@ -26,6 +26,7 @@ import (
"encoding/json" "encoding/json"
"log" "log"
"time" "time"
"net/url"
) )
func getConfig() Config { func getConfig() Config {
@ -104,8 +105,10 @@ func formatBlog(toot Blog) string {
author = toot.Author.DisplayName author = toot.Author.DisplayName
} }
var header string
if toot.Reblog == nil { 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" header = "### Written by " + author + " on " + toot.Date[0:10] + " at " + toot.Date[11:16]
} else { } else {
var originalAuthor string var originalAuthor string
if toot.Reblog.Author.DisplayName == "" { if toot.Reblog.Author.DisplayName == "" {
@ -114,8 +117,17 @@ func formatBlog(toot Blog) string {
originalAuthor = toot.Reblog.Author.DisplayName 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" header = "### Shared by " + author + " on " + toot.Date[0:10] + " at " + toot.Date[11:16] + " (original by " + originalAuthor + ")"
} }
footer := "\n"
for _, media := range toot.Medias {
mediaURL := url.QueryEscape(media.Url)
footer += "=> /media?" + mediaURL + " View attached media\n"
}
footer += "\n=> /toot/" + toot.Id + " More informations about this toot"
return header + "\n" + content + "\n" + footer
} }
func rateIsOk(tab map[string]Rate, remoteIP string, limit int) bool { func rateIsOk(tab map[string]Rate, remoteIP string, limit int) bool {