package main import ( "database/sql" "fmt" "log" "net/http" "humungus.tedunangst.com/r/webs/junk" "humungus.tedunangst.com/r/webs/login" ) type MastoApp struct { Name string `db:"clientname"` RedirectURI string `db:"redirecturis"` ClientID string `db:"clientid"` ClientSecret string `db:"clientsecret"` VapidKey string `db:"vapidkey"` AuthToken string `db:"authtoken"` Scopes string `db:"scopes"` } func showoauthlogin(rw http.ResponseWriter, r *http.Request) { templinfo := make(map[string]interface{}) templinfo = getInfo(r) templinfo["ClientID"] = r.URL.Query().Get("client_id") templinfo["RedirectURI"] = r.URL.Query().Get("redirect_uri") if err := readviews.Execute(rw, "oauthlogin.html", templinfo); err != nil { elog.Println(err) } } // https://docs.joinmastodon.org/methods/apps/#create func apiapps(rw http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(rw, "invalid input", http.StatusUnprocessableEntity) elog.Println(err) return } clientName := r.Form.Get("client_name") redirectURI := r.Form.Get("redirect_uris") scopes := r.Form.Get("scopes") website := r.Form.Get("website") clientID := tokengen() clientSecret := tokengen() vapidKey := tokengen() _, err := stmtSaveMastoApp.Exec(clientName, redirectURI, scopes, clientID, clientSecret, vapidKey, "") if err != nil { elog.Printf("error saving masto app: %v", err) http.Error(rw, "error saving masto app", http.StatusUnprocessableEntity) return } j := junk.New() j["id"] = "19" j["website"] = website j["name"] = clientName j["redirect_uri"] = redirectURI j["client_id"] = clientID j["client_secret"] = clientSecret j["vapid_key"] = vapidKey fmt.Println(j.ToString()) goodjunk(rw, j) } // https://docs.joinmastodon.org/methods/oauth/#authorize func oauthorize(rw http.ResponseWriter, r *http.Request) { clientID := r.FormValue("client_id") redirectURI := r.FormValue("redirect_uri") if !checkClientID(clientID) { elog.Println("oauth: no such client:", clientID) rw.WriteHeader(http.StatusUnauthorized) return } var nrw NotResponseWriter login.LoginFunc(&nrw, r) _, err := stmtSaveMastoAppToken.Exec(nrw.auth) if err != nil { elog.Println("oauth: failed to save masto app token", err) rw.WriteHeader(http.StatusInternalServerError) return } uri := fmt.Sprintf("%s?code=%s", redirectURI, nrw.auth) log.Println("redirecting to", uri) rw.Header().Set("Content-Type", "") rw.Header().Set("Location", uri) rw.WriteHeader(302) } // https://docs.joinmastodon.org/methods/oauth/#token func oauthtoken(rw http.ResponseWriter, r *http.Request) { // grantType := r.FormValue("grant_type") // code := r.FormValue("code") clientID := r.FormValue("client_id") clientSecret := r.FormValue("client_Secret") // redirectURI := r.FormValue("redirect_uri") // gotScopes := r.FormValue("scopes") if !checkClient(clientID, clientSecret) { elog.Println("oauth: no such client:", clientID) rw.WriteHeader(http.StatusUnauthorized) return } app := MastoApp{} row := stmtGetMastoApp.QueryRowx(clientID) err := row.StructScan(&app) if err == sql.ErrNoRows { elog.Printf("oauth: invalid client: %s", clientID) rw.WriteHeader(http.StatusUnauthorized) return } fmt.Printf("%#v", app) } // https://docs.joinmastodon.org/methods/instance/#v2 func instance(rw http.ResponseWriter, r *http.Request) { j := junk.New() var servername string if err := getconfig("servername", &servername); err != nil { http.Error(rw, "getting servername", http.StatusInternalServerError) return } j["uri"] = servername j["title"] = "honk" j["description"] = "federated honk conveyance" j["version"] = "develop" thumbnail := junk.New() thumbnail["url"] = fmt.Sprintf("https://%s/icon.png", servername) j["thumbnail"] = thumbnail j["languages"] = []string{"en"} config := junk.New() a := junk.New() a["max_featured_tags"] = 10 config["accounts"] = a s := junk.New() s["max_characters"] = 5000 s["max_media_attachments"] = 1 s["characters_reserved_per_url"] = 23 config["statuses"] = s m := junk.New() m["supported_mime_types"] = []string{ "image/jpeg", "image/png", "image/gif", "image/heic", "image/heif", "image/webp", "image/avif", "video/webm", "video/mp4", "video/quicktime", "video/ogg", "audio/wave", "audio/wav", "audio/x-wav", "audio/x-pn-wave", "audio/vnd.wave", "audio/ogg", "audio/vorbis", "audio/mpeg", "audio/mp3", "audio/webm", "audio/flac", "audio/aac", "audio/m4a", "audio/x-m4a", "audio/mp4", "audio/3gpp", "video/x-ms-asf", } m["image_size_limit"] = 10485760 m["image_matrix_limit"] = 16777216 m["video_size_limit"] = 41943040 m["video_frame_rate_limit"] = 60 m["video_matrix_limit"] = 2304000 j["media_attachments"] = m goodjunk(rw, j) return }