diff --git a/api_domains.go b/api_domains.go index 001cd46..1a2cfe8 100644 --- a/api_domains.go +++ b/api_domains.go @@ -134,6 +134,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) { Type string `json:"type,omitempty"` Status string `json:"status,omitempty"` PublishStatus string `json:"publish_status,omitempty"` + Language string `json:"language,omitempty"` } type DomainInfo struct { @@ -162,7 +163,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) { // Now get feeds for these domains if len(hosts) > 0 { feedRows, err := c.db.Query(` - SELECT source_host, url, title, type, status, publish_status + SELECT source_host, url, title, type, status, publish_status, language FROM feeds WHERE source_host = ANY($1) ORDER BY source_host, url @@ -173,14 +174,15 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) { for feedRows.Next() { var host string var f FeedInfo - var title, feedType, status, publishStatus *string - if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus); err != nil { + var title, feedType, status, publishStatus, language *string + if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus, &language); err != nil { continue } f.Title = StringValue(title) f.Type = StringValue(feedType) f.Status = StringValue(status) f.PublishStatus = StringValue(publishStatus) + f.Language = StringValue(language) feedsByHost[host] = append(feedsByHost[host], f) } // Attach feeds to domains diff --git a/oauth_handlers.go b/oauth_handlers.go index 291718a..62c5eaa 100644 --- a/oauth_handlers.go +++ b/oauth_handlers.go @@ -7,6 +7,7 @@ import ( "html/template" "net/http" "net/url" + "strings" "time" "github.com/haileyok/atproto-oauth-golang/helpers" @@ -64,14 +65,29 @@ func (m *OAuthManager) HandleLogin(w http.ResponseWriter, r *http.Request) { // If handle is provided, start OAuth flow handle := r.URL.Query().Get("handle") if handle != "" { + // Save handle to cookie for prefill on next visit + http.SetCookie(w, &http.Cookie{ + Name: "last_handle", + Value: handle, + Path: "/", + MaxAge: 86400 * 365, // 1 year + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + }) m.startOAuthFlow(w, r, handle) return } + // Get last handle from cookie for prefill + lastHandle := "" + if cookie, err := r.Cookie("last_handle"); err == nil { + lastHandle = cookie.Value + } + // Serve login page w.Header().Set("Content-Type", "text/html; charset=utf-8") tmpl := template.Must(template.New("login").Parse(loginPageHTML)) - tmpl.Execute(w, nil) + tmpl.Execute(w, map[string]string{"LastHandle": lastHandle}) } // startOAuthFlow initiates the OAuth flow for a given handle @@ -79,6 +95,11 @@ func (m *OAuthManager) startOAuthFlow(w http.ResponseWriter, r *http.Request, ha ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second) defer cancel() + // Auto-append .bsky.social if handle has no dots + if !strings.Contains(handle, ".") { + handle = handle + ".bsky.social" + } + fmt.Printf("OAuth: starting flow for handle: %s\n", handle) // Resolve handle to DID @@ -168,20 +189,7 @@ func (m *OAuthManager) startOAuthFlow(w http.ResponseWriter, r *http.Request, ha fmt.Printf("OAuth: redirecting to: %s\n", authURL.String()) - // Use JavaScript redirect to preserve browser security headers - w.Header().Set("Content-Type", "text/html; charset=utf-8") - fmt.Fprintf(w, ` - -
- -Redirecting to authorization server...
- - - -`, authURL.String(), authURL.String()) + http.Redirect(w, r, authURL.String(), http.StatusFound) } // HandleCallback handles the OAuth callback @@ -453,7 +461,7 @@ const loginPageHTML = `