Refactor atproto client to use APIClient directly and fix UIUnverified
72289c4 parent: a6093b7 modified
.gitignore +1 -1 | @@ -23,7 +23,7 @@ go.work.sum | ||
| 23 | 23 | |
| 24 | 24 | # database |
| 25 | 25 | *.db |
| 26 | -*.db.journal | |
| 26 | +*.db-journal | |
| 27 | 27 | |
| 28 | 28 | # tailwind |
| 29 | 29 | static/output.css |
| @@ -23,7 +23,7 @@ go.work.sum | |||
| 23 | 23 | ||
| 24 | # database | 24 | # database |
| 25 | *.db | 25 | *.db |
| 26 | -*.db.journal | 26 | +*.db-journal |
| 27 | 27 | ||
| 28 | # tailwind | 28 | # tailwind |
| 29 | static/output.css | 29 | static/output.css |
modified
internal/atproto/client.go +8 -145 | @@ -1,82 +1,23 @@ | ||
| 1 | 1 | package atproto |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | - "bytes" | |
| 5 | 4 | "context" |
| 6 | 5 | "encoding/json" |
| 7 | 6 | "fmt" |
| 8 | - "net/http" | |
| 9 | 7 | |
| 10 | 8 | "github.com/bluesky-social/indigo/atproto/atclient" |
| 11 | 9 | "github.com/bluesky-social/indigo/atproto/syntax" |
| 12 | 10 | ) |
| 13 | 11 | |
| 14 | 12 | type Client struct { |
| 15 | - httpClient *http.Client | |
| 16 | - pdsURL string | |
| 17 | - accessToken string | |
| 18 | - APIClient *atclient.APIClient | |
| 13 | + api *atclient.APIClient | |
| 19 | 14 | } |
| 20 | 15 | |
| 21 | -func NewClient(pdsURL, accessToken string) *Client { | |
| 22 | - return &Client{ | |
| 23 | - httpClient: &http.Client{}, | |
| 24 | - pdsURL: pdsURL, | |
| 25 | - accessToken: accessToken, | |
| 26 | - } | |
| 16 | +func NewClient(api *atclient.APIClient) *Client { | |
| 17 | + return &Client{api: api} | |
| 27 | 18 | } |
| 28 | 19 | |
| 29 | 20 | func (c *Client) CreateRecord(ctx context.Context, did, collection string, record any) (string, string, error) { |
| 30 | - if c.APIClient != nil { | |
| 31 | - return c.createRecordWithAPI(ctx, did, collection, record) | |
| 32 | - } | |
| 33 | - | |
| 34 | - nsid, err := syntax.ParseNSID(collection) | |
| 35 | - if err != nil { | |
| 36 | - return "", "", fmt.Errorf("parsing collection NSID: %w", err) | |
| 37 | - } | |
| 38 | - | |
| 39 | - body := map[string]any{ | |
| 40 | - "repo": did, | |
| 41 | - "collection": nsid.String(), | |
| 42 | - "record": record, | |
| 43 | - } | |
| 44 | - | |
| 45 | - data, err := json.Marshal(body) | |
| 46 | - if err != nil { | |
| 47 | - return "", "", err | |
| 48 | - } | |
| 49 | - | |
| 50 | - url := c.pdsURL + "/xrpc/com.atproto.repo.createRecord" | |
| 51 | - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(data)) | |
| 52 | - if err != nil { | |
| 53 | - return "", "", err | |
| 54 | - } | |
| 55 | - req.Header.Set("Content-Type", "application/json") | |
| 56 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | |
| 57 | - | |
| 58 | - resp, err := c.httpClient.Do(req) | |
| 59 | - if err != nil { | |
| 60 | - return "", "", err | |
| 61 | - } | |
| 62 | - defer resp.Body.Close() | |
| 63 | - | |
| 64 | - if resp.StatusCode != http.StatusOK { | |
| 65 | - return "", "", fmt.Errorf("create record returned %d", resp.StatusCode) | |
| 66 | - } | |
| 67 | - | |
| 68 | - var result struct { | |
| 69 | - URI string `json:"uri"` | |
| 70 | - CID string `json:"cid"` | |
| 71 | - } | |
| 72 | - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { | |
| 73 | - return "", "", err | |
| 74 | - } | |
| 75 | - | |
| 76 | - return result.URI, result.CID, nil | |
| 77 | -} | |
| 78 | - | |
| 79 | -func (c *Client) createRecordWithAPI(ctx context.Context, did, collection string, record any) (string, string, error) { | |
| 80 | 21 | input := map[string]any{ |
| 81 | 22 | "repo": did, |
| 82 | 23 | "collection": collection, |
| @@ -93,7 +34,7 @@ func (c *Client) createRecordWithAPI(ctx context.Context, did, collection string | ||
| 93 | 34 | return "", "", fmt.Errorf("parsing NSID: %w", err) |
| 94 | 35 | } |
| 95 | 36 | |
| 96 | - if err := c.APIClient.Post(ctx, nsid, input, &out); err != nil { | |
| 37 | + if err := c.api.Post(ctx, nsid, input, &out); err != nil { | |
| 97 | 38 | return "", "", err |
| 98 | 39 | } |
| 99 | 40 | return out.URI, out.CID, nil |
| @@ -106,93 +47,15 @@ func (c *Client) DeleteRecord(ctx context.Context, did, collection, rkey string) | ||
| 106 | 47 | "rkey": rkey, |
| 107 | 48 | } |
| 108 | 49 | |
| 109 | - if c.APIClient != nil { | |
| 110 | - nsid, err := syntax.ParseNSID("com.atproto.repo.deleteRecord") | |
| 111 | - if err != nil { | |
| 112 | - return fmt.Errorf("parsing NSID: %w", err) | |
| 113 | - } | |
| 114 | - return c.APIClient.Post(ctx, nsid, input, nil) | |
| 115 | - } | |
| 116 | - | |
| 117 | - data, err := json.Marshal(input) | |
| 118 | - if err != nil { | |
| 119 | - return err | |
| 120 | - } | |
| 121 | - | |
| 122 | - url := c.pdsURL + "/xrpc/com.atproto.repo.deleteRecord" | |
| 123 | - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(data)) | |
| 124 | - if err != nil { | |
| 125 | - return err | |
| 126 | - } | |
| 127 | - req.Header.Set("Content-Type", "application/json") | |
| 128 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | |
| 129 | - | |
| 130 | - resp, err := c.httpClient.Do(req) | |
| 50 | + nsid, err := syntax.ParseNSID("com.atproto.repo.deleteRecord") | |
| 131 | 51 | if err != nil { |
| 132 | - return err | |
| 52 | + return fmt.Errorf("parsing NSID: %w", err) | |
| 133 | 53 | } |
| 134 | - defer resp.Body.Close() | |
| 135 | 54 | |
| 136 | - if resp.StatusCode != http.StatusOK { | |
| 137 | - return fmt.Errorf("delete record returned %d", resp.StatusCode) | |
| 138 | - } | |
| 139 | - | |
| 140 | - return nil | |
| 55 | + return c.api.Post(ctx, nsid, input, nil) | |
| 141 | 56 | } |
| 142 | 57 | |
| 143 | 58 | func (c *Client) ListRecords(ctx context.Context, did, collection string, limit int, cursor string) ([]Record, string, error) { |
| 144 | - if c.APIClient != nil { | |
| 145 | - return c.listRecordsWithAPI(ctx, did, collection, limit, cursor) | |
| 146 | - } | |
| 147 | - | |
| 148 | - url := fmt.Sprintf("%s/xrpc/com.atproto.repo.listRecords?repo=%s&collection=%s", c.pdsURL, did, collection) | |
| 149 | - if limit > 0 { | |
| 150 | - url += fmt.Sprintf("&limit=%d", limit) | |
| 151 | - } | |
| 152 | - if cursor != "" { | |
| 153 | - url += "&cursor=" + cursor | |
| 154 | - } | |
| 155 | - | |
| 156 | - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | |
| 157 | - if err != nil { | |
| 158 | - return nil, "", err | |
| 159 | - } | |
| 160 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | |
| 161 | - | |
| 162 | - resp, err := c.httpClient.Do(req) | |
| 163 | - if err != nil { | |
| 164 | - return nil, "", err | |
| 165 | - } | |
| 166 | - defer resp.Body.Close() | |
| 167 | - | |
| 168 | - if resp.StatusCode != http.StatusOK { | |
| 169 | - return nil, "", fmt.Errorf("list records returned %d", resp.StatusCode) | |
| 170 | - } | |
| 171 | - | |
| 172 | - var result struct { | |
| 173 | - Records []struct { | |
| 174 | - URI string `json:"uri"` | |
| 175 | - CID string `json:"cid"` | |
| 176 | - Value json.RawMessage `json:"value"` | |
| 177 | - } `json:"records"` | |
| 178 | - Cursor string `json:"cursor"` | |
| 179 | - } | |
| 180 | - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { | |
| 181 | - return nil, "", err | |
| 182 | - } | |
| 183 | - | |
| 184 | - records := make([]Record, len(result.Records)) | |
| 185 | - for i, r := range result.Records { | |
| 186 | - records[i] = Record{ | |
| 187 | - URI: r.URI, | |
| 188 | - CID: r.CID, | |
| 189 | - Value: r.Value, | |
| 190 | - } | |
| 191 | - } | |
| 192 | - return records, result.Cursor, nil | |
| 193 | -} | |
| 194 | - | |
| 195 | -func (c *Client) listRecordsWithAPI(ctx context.Context, did, collection string, limit int, cursor string) ([]Record, string, error) { | |
| 196 | 59 | nsid, err := syntax.ParseNSID("com.atproto.repo.listRecords") |
| 197 | 60 | if err != nil { |
| 198 | 61 | return nil, "", fmt.Errorf("parsing NSID: %w", err) |
| @@ -218,7 +81,7 @@ func (c *Client) listRecordsWithAPI(ctx context.Context, did, collection string, | ||
| 218 | 81 | Cursor string `json:"cursor"` |
| 219 | 82 | } |
| 220 | 83 | |
| 221 | - if err := c.APIClient.Get(ctx, nsid, params, &result); err != nil { | |
| 84 | + if err := c.api.Get(ctx, nsid, params, &result); err != nil { | |
| 222 | 85 | return nil, "", err |
| 223 | 86 | } |
| 224 | 87 | |
| @@ -1,82 +1,23 @@ | |||
| 1 | package atproto | 1 | package atproto |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | - "bytes" | ||
| 5 | "context" | 4 | "context" |
| 6 | "encoding/json" | 5 | "encoding/json" |
| 7 | "fmt" | 6 | "fmt" |
| 8 | - "net/http" | ||
| 9 | 7 | ||
| 10 | "github.com/bluesky-social/indigo/atproto/atclient" | 8 | "github.com/bluesky-social/indigo/atproto/atclient" |
| 11 | "github.com/bluesky-social/indigo/atproto/syntax" | 9 | "github.com/bluesky-social/indigo/atproto/syntax" |
| 12 | ) | 10 | ) |
| 13 | 11 | ||
| 14 | type Client struct { | 12 | type Client struct { |
| 15 | - httpClient *http.Client | 13 | + api *atclient.APIClient |
| 16 | - pdsURL string | ||
| 17 | - accessToken string | ||
| 18 | - APIClient *atclient.APIClient | ||
| 19 | } | 14 | } |
| 20 | 15 | ||
| 21 | -func NewClient(pdsURL, accessToken string) *Client { | 16 | +func NewClient(api *atclient.APIClient) *Client { |
| 22 | - return &Client{ | 17 | + return &Client{api: api} |
| 23 | - httpClient: &http.Client{}, | ||
| 24 | - pdsURL: pdsURL, | ||
| 25 | - accessToken: accessToken, | ||
| 26 | - } | ||
| 27 | } | 18 | } |
| 28 | 19 | ||
| 29 | func (c *Client) CreateRecord(ctx context.Context, did, collection string, record any) (string, string, error) { | 20 | func (c *Client) CreateRecord(ctx context.Context, did, collection string, record any) (string, string, error) { |
| 30 | - if c.APIClient != nil { | ||
| 31 | - return c.createRecordWithAPI(ctx, did, collection, record) | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | - nsid, err := syntax.ParseNSID(collection) | ||
| 35 | - if err != nil { | ||
| 36 | - return "", "", fmt.Errorf("parsing collection NSID: %w", err) | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | - body := map[string]any{ | ||
| 40 | - "repo": did, | ||
| 41 | - "collection": nsid.String(), | ||
| 42 | - "record": record, | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - data, err := json.Marshal(body) | ||
| 46 | - if err != nil { | ||
| 47 | - return "", "", err | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - url := c.pdsURL + "/xrpc/com.atproto.repo.createRecord" | ||
| 51 | - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(data)) | ||
| 52 | - if err != nil { | ||
| 53 | - return "", "", err | ||
| 54 | - } | ||
| 55 | - req.Header.Set("Content-Type", "application/json") | ||
| 56 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | ||
| 57 | - | ||
| 58 | - resp, err := c.httpClient.Do(req) | ||
| 59 | - if err != nil { | ||
| 60 | - return "", "", err | ||
| 61 | - } | ||
| 62 | - defer resp.Body.Close() | ||
| 63 | - | ||
| 64 | - if resp.StatusCode != http.StatusOK { | ||
| 65 | - return "", "", fmt.Errorf("create record returned %d", resp.StatusCode) | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - var result struct { | ||
| 69 | - URI string `json:"uri"` | ||
| 70 | - CID string `json:"cid"` | ||
| 71 | - } | ||
| 72 | - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { | ||
| 73 | - return "", "", err | ||
| 74 | - } | ||
| 75 | - | ||
| 76 | - return result.URI, result.CID, nil | ||
| 77 | -} | ||
| 78 | - | ||
| 79 | -func (c *Client) createRecordWithAPI(ctx context.Context, did, collection string, record any) (string, string, error) { | ||
| 80 | input := map[string]any{ | 21 | input := map[string]any{ |
| 81 | "repo": did, | 22 | "repo": did, |
| 82 | "collection": collection, | 23 | "collection": collection, |
| @@ -93,7 +34,7 @@ func (c *Client) createRecordWithAPI(ctx context.Context, did, collection string | |||
| 93 | return "", "", fmt.Errorf("parsing NSID: %w", err) | 34 | return "", "", fmt.Errorf("parsing NSID: %w", err) |
| 94 | } | 35 | } |
| 95 | 36 | ||
| 96 | - if err := c.APIClient.Post(ctx, nsid, input, &out); err != nil { | 37 | + if err := c.api.Post(ctx, nsid, input, &out); err != nil { |
| 97 | return "", "", err | 38 | return "", "", err |
| 98 | } | 39 | } |
| 99 | return out.URI, out.CID, nil | 40 | return out.URI, out.CID, nil |
| @@ -106,93 +47,15 @@ func (c *Client) DeleteRecord(ctx context.Context, did, collection, rkey string) | |||
| 106 | "rkey": rkey, | 47 | "rkey": rkey, |
| 107 | } | 48 | } |
| 108 | 49 | ||
| 109 | - if c.APIClient != nil { | 50 | + nsid, err := syntax.ParseNSID("com.atproto.repo.deleteRecord") |
| 110 | - nsid, err := syntax.ParseNSID("com.atproto.repo.deleteRecord") | ||
| 111 | - if err != nil { | ||
| 112 | - return fmt.Errorf("parsing NSID: %w", err) | ||
| 113 | - } | ||
| 114 | - return c.APIClient.Post(ctx, nsid, input, nil) | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - data, err := json.Marshal(input) | ||
| 118 | - if err != nil { | ||
| 119 | - return err | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - url := c.pdsURL + "/xrpc/com.atproto.repo.deleteRecord" | ||
| 123 | - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(data)) | ||
| 124 | - if err != nil { | ||
| 125 | - return err | ||
| 126 | - } | ||
| 127 | - req.Header.Set("Content-Type", "application/json") | ||
| 128 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | ||
| 129 | - | ||
| 130 | - resp, err := c.httpClient.Do(req) | ||
| 131 | if err != nil { | 51 | if err != nil { |
| 132 | - return err | 52 | + return fmt.Errorf("parsing NSID: %w", err) |
| 133 | } | 53 | } |
| 134 | - defer resp.Body.Close() | ||
| 135 | 54 | ||
| 136 | - if resp.StatusCode != http.StatusOK { | 55 | + return c.api.Post(ctx, nsid, input, nil) |
| 137 | - return fmt.Errorf("delete record returned %d", resp.StatusCode) | ||
| 138 | - } | ||
| 139 | - | ||
| 140 | - return nil | ||
| 141 | } | 56 | } |
| 142 | 57 | ||
| 143 | func (c *Client) ListRecords(ctx context.Context, did, collection string, limit int, cursor string) ([]Record, string, error) { | 58 | func (c *Client) ListRecords(ctx context.Context, did, collection string, limit int, cursor string) ([]Record, string, error) { |
| 144 | - if c.APIClient != nil { | ||
| 145 | - return c.listRecordsWithAPI(ctx, did, collection, limit, cursor) | ||
| 146 | - } | ||
| 147 | - | ||
| 148 | - url := fmt.Sprintf("%s/xrpc/com.atproto.repo.listRecords?repo=%s&collection=%s", c.pdsURL, did, collection) | ||
| 149 | - if limit > 0 { | ||
| 150 | - url += fmt.Sprintf("&limit=%d", limit) | ||
| 151 | - } | ||
| 152 | - if cursor != "" { | ||
| 153 | - url += "&cursor=" + cursor | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | ||
| 157 | - if err != nil { | ||
| 158 | - return nil, "", err | ||
| 159 | - } | ||
| 160 | - req.Header.Set("Authorization", "Bearer "+c.accessToken) | ||
| 161 | - | ||
| 162 | - resp, err := c.httpClient.Do(req) | ||
| 163 | - if err != nil { | ||
| 164 | - return nil, "", err | ||
| 165 | - } | ||
| 166 | - defer resp.Body.Close() | ||
| 167 | - | ||
| 168 | - if resp.StatusCode != http.StatusOK { | ||
| 169 | - return nil, "", fmt.Errorf("list records returned %d", resp.StatusCode) | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | - var result struct { | ||
| 173 | - Records []struct { | ||
| 174 | - URI string `json:"uri"` | ||
| 175 | - CID string `json:"cid"` | ||
| 176 | - Value json.RawMessage `json:"value"` | ||
| 177 | - } `json:"records"` | ||
| 178 | - Cursor string `json:"cursor"` | ||
| 179 | - } | ||
| 180 | - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { | ||
| 181 | - return nil, "", err | ||
| 182 | - } | ||
| 183 | - | ||
| 184 | - records := make([]Record, len(result.Records)) | ||
| 185 | - for i, r := range result.Records { | ||
| 186 | - records[i] = Record{ | ||
| 187 | - URI: r.URI, | ||
| 188 | - CID: r.CID, | ||
| 189 | - Value: r.Value, | ||
| 190 | - } | ||
| 191 | - } | ||
| 192 | - return records, result.Cursor, nil | ||
| 193 | -} | ||
| 194 | - | ||
| 195 | -func (c *Client) listRecordsWithAPI(ctx context.Context, did, collection string, limit int, cursor string) ([]Record, string, error) { | ||
| 196 | nsid, err := syntax.ParseNSID("com.atproto.repo.listRecords") | 59 | nsid, err := syntax.ParseNSID("com.atproto.repo.listRecords") |
| 197 | if err != nil { | 60 | if err != nil { |
| 198 | return nil, "", fmt.Errorf("parsing NSID: %w", err) | 61 | return nil, "", fmt.Errorf("parsing NSID: %w", err) |
| @@ -218,7 +81,7 @@ func (c *Client) listRecordsWithAPI(ctx context.Context, did, collection string, | |||
| 218 | Cursor string `json:"cursor"` | 81 | Cursor string `json:"cursor"` |
| 219 | } | 82 | } |
| 220 | 83 | ||
| 221 | - if err := c.APIClient.Get(ctx, nsid, params, &result); err != nil { | 84 | + if err := c.api.Get(ctx, nsid, params, &result); err != nil { |
| 222 | return nil, "", err | 85 | return nil, "", err |
| 223 | } | 86 | } |
| 224 | 87 | ||
modified
internal/server/auth_handler.go +1 -1 | @@ -157,7 +157,7 @@ func (s *Server) pdsClientFromSession(sessData *oauth.ClientSessionData) *atprot | ||
| 157 | 157 | s.logger.Warn("failed to resume session for sync", "error", err) |
| 158 | 158 | return nil |
| 159 | 159 | } |
| 160 | - return &atproto.Client{APIClient: session.APIClient()} | |
| 160 | + return atproto.NewClient(session.APIClient()) | |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | 163 | func (s *Server) handleOAuthClientMetadata(w http.ResponseWriter, r *http.Request) { |
| @@ -157,7 +157,7 @@ func (s *Server) pdsClientFromSession(sessData *oauth.ClientSessionData) *atprot | |||
| 157 | s.logger.Warn("failed to resume session for sync", "error", err) | 157 | s.logger.Warn("failed to resume session for sync", "error", err) |
| 158 | return nil | 158 | return nil |
| 159 | } | 159 | } |
| 160 | - return &atproto.Client{APIClient: session.APIClient()} | 160 | + return atproto.NewClient(session.APIClient()) |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | func (s *Server) handleOAuthClientMetadata(w http.ResponseWriter, r *http.Request) { | 163 | func (s *Server) handleOAuthClientMetadata(w http.ResponseWriter, r *http.Request) { |
modified
internal/server/server.go +12 -16 | @@ -229,24 +229,20 @@ func (s *Server) pdsClientForUser(r *http.Request) *atproto.Client { | ||
| 229 | 229 | return nil |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | - if session.SessionID != "" { | |
| 233 | - did, err := syntax.ParseDID(session.DID) | |
| 234 | - if err != nil { | |
| 235 | - return nil | |
| 236 | - } | |
| 237 | - sess, err := s.oauth.ResumeSession(r.Context(), did, session.SessionID) | |
| 238 | - if err != nil { | |
| 239 | - s.logger.Warn("failed to resume OAuth session", "error", err) | |
| 240 | - return nil | |
| 241 | - } | |
| 242 | - apiClient := sess.APIClient() | |
| 243 | - return &atproto.Client{APIClient: apiClient} | |
| 232 | + if session.SessionID == "" { | |
| 233 | + return nil | |
| 244 | 234 | } |
| 245 | 235 | |
| 246 | - if session.AccessToken != "" && session.PDSURL != "" { | |
| 247 | - return atproto.NewClient(session.PDSURL, session.AccessToken) | |
| 236 | + did, err := syntax.ParseDID(session.DID) | |
| 237 | + if err != nil { | |
| 238 | + return nil | |
| 239 | + } | |
| 240 | + sess, err := s.oauth.ResumeSession(r.Context(), did, session.SessionID) | |
| 241 | + if err != nil { | |
| 242 | + s.logger.Warn("failed to resume OAuth session", "error", err) | |
| 243 | + return nil | |
| 248 | 244 | } |
| 249 | - return nil | |
| 245 | + return atproto.NewClient(sess.APIClient()) | |
| 250 | 246 | } |
| 251 | 247 | |
| 252 | 248 | func (s *Server) syncUserInBackground(userDID string, client *atproto.Client) { |
| @@ -298,7 +294,7 @@ func (s *Server) runSyncAll(ctx context.Context) { | ||
| 298 | 294 | continue |
| 299 | 295 | } |
| 300 | 296 | |
| 301 | - client := &atproto.Client{APIClient: sess.APIClient()} | |
| 297 | + client := atproto.NewClient(sess.APIClient()) | |
| 302 | 298 | sync := atproto.NewSync(s.db, client, s.logger) |
| 303 | 299 | if err := sync.Run(ctx, u.DID); err != nil { |
| 304 | 300 | s.logger.Error("periodic sync failed", "error", err, "did", u.DID) |
| @@ -229,24 +229,20 @@ func (s *Server) pdsClientForUser(r *http.Request) *atproto.Client { | |||
| 229 | return nil | 229 | return nil |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | - if session.SessionID != "" { | 232 | + if session.SessionID == "" { |
| 233 | - did, err := syntax.ParseDID(session.DID) | 233 | + return nil |
| 234 | - if err != nil { | ||
| 235 | - return nil | ||
| 236 | - } | ||
| 237 | - sess, err := s.oauth.ResumeSession(r.Context(), did, session.SessionID) | ||
| 238 | - if err != nil { | ||
| 239 | - s.logger.Warn("failed to resume OAuth session", "error", err) | ||
| 240 | - return nil | ||
| 241 | - } | ||
| 242 | - apiClient := sess.APIClient() | ||
| 243 | - return &atproto.Client{APIClient: apiClient} | ||
| 244 | } | 234 | } |
| 245 | 235 | ||
| 246 | - if session.AccessToken != "" && session.PDSURL != "" { | 236 | + did, err := syntax.ParseDID(session.DID) |
| 247 | - return atproto.NewClient(session.PDSURL, session.AccessToken) | 237 | + if err != nil { |
| 238 | + return nil | ||
| 239 | + } | ||
| 240 | + sess, err := s.oauth.ResumeSession(r.Context(), did, session.SessionID) | ||
| 241 | + if err != nil { | ||
| 242 | + s.logger.Warn("failed to resume OAuth session", "error", err) | ||
| 243 | + return nil | ||
| 248 | } | 244 | } |
| 249 | - return nil | 245 | + return atproto.NewClient(sess.APIClient()) |
| 250 | } | 246 | } |
| 251 | 247 | ||
| 252 | func (s *Server) syncUserInBackground(userDID string, client *atproto.Client) { | 248 | func (s *Server) syncUserInBackground(userDID string, client *atproto.Client) { |
| @@ -298,7 +294,7 @@ func (s *Server) runSyncAll(ctx context.Context) { | |||
| 298 | continue | 294 | continue |
| 299 | } | 295 | } |
| 300 | 296 | ||
| 301 | - client := &atproto.Client{APIClient: sess.APIClient()} | 297 | + client := atproto.NewClient(sess.APIClient()) |
| 302 | sync := atproto.NewSync(s.db, client, s.logger) | 298 | sync := atproto.NewSync(s.db, client, s.logger) |
| 303 | if err := sync.Run(ctx, u.DID); err != nil { | 299 | if err := sync.Run(ctx, u.DID); err != nil { |
| 304 | s.logger.Error("periodic sync failed", "error", err, "did", u.DID) | 300 | s.logger.Error("periodic sync failed", "error", err, "did", u.DID) |
modified
internal/tmpl/feeds.html +1 -1 | @@ -123,7 +123,7 @@ | ||
| 123 | 123 | <input type="file" name="opml" accept=".opml,.xml" class="text-sm text-spot-secondary file:mr-2 file:py-1 file:px-3 file:rounded-pill file:border-0 file:text-sm file:bg-spot-hover file:text-spot-text hover:file:bg-spot-surface file:cursor-pointer"> |
| 124 | 124 | <button type="submit" class="w-full border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Import OPML</button> |
| 125 | 125 | </form> |
| 126 | - <a href="/feeds/opml/download" class="block w-full text-center border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Export OPML</a> | |
| 126 | + {{if .Subscriptions}}<a href="/feeds/opml/download" class="block w-full text-center border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Export OPML</a>{{end}} | |
| 127 | 127 | </div> |
| 128 | 128 | </div> |
| 129 | 129 | |
| @@ -123,7 +123,7 @@ | |||
| 123 | <input type="file" name="opml" accept=".opml,.xml" class="text-sm text-spot-secondary file:mr-2 file:py-1 file:px-3 file:rounded-pill file:border-0 file:text-sm file:bg-spot-hover file:text-spot-text hover:file:bg-spot-surface file:cursor-pointer"> | 123 | <input type="file" name="opml" accept=".opml,.xml" class="text-sm text-spot-secondary file:mr-2 file:py-1 file:px-3 file:rounded-pill file:border-0 file:text-sm file:bg-spot-hover file:text-spot-text hover:file:bg-spot-surface file:cursor-pointer"> |
| 124 | <button type="submit" class="w-full border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Import OPML</button> | 124 | <button type="submit" class="w-full border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Import OPML</button> |
| 125 | </form> | 125 | </form> |
| 126 | - <a href="/feeds/opml/download" class="block w-full text-center border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Export OPML</a> | 126 | + {{if .Subscriptions}}<a href="/feeds/opml/download" class="block w-full text-center border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-sm font-bold uppercase tracking-button hover:border-spot-text transition">Export OPML</a>{{end}} |
| 127 | </div> | 127 | </div> |
| 128 | </div> | 128 | </div> |
| 129 | 129 | ||
modified
internal/tmpl/partials/logo.html +2 -2 | @@ -15,7 +15,7 @@ | ||
| 15 | 15 | |
| 16 | 16 | {{define "logo-link"}}<a href="/" class="text-spot-green font-bold text-xl tracking-tight flex items-center gap-2"> |
| 17 | 17 | <span class="w-7 h-7">{{template "logo-icon"}}</span> |
| 18 | - Glean.at | |
| 18 | + <span class="font-bold text-xl text-spot-text">Glean</span> | |
| 19 | 19 | </a>{{end}} |
| 20 | 20 | |
| 21 | -{{define "logo-text"}}<a href="/" class="text-spot-green font-bold text-lg tracking-tight">Glean.at</a>{{end}} | |
| 21 | +{{define "logo-text"}}<a href="/" class="text-spot-green font-bold text-lg tracking-tight"><span class="font-bold text-xl text-spot-text">Glean</span>.at</a>{{end}} | |
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | {{define "logo-link"}}<a href="/" class="text-spot-green font-bold text-xl tracking-tight flex items-center gap-2"> | 16 | {{define "logo-link"}}<a href="/" class="text-spot-green font-bold text-xl tracking-tight flex items-center gap-2"> |
| 17 | <span class="w-7 h-7">{{template "logo-icon"}}</span> | 17 | <span class="w-7 h-7">{{template "logo-icon"}}</span> |
| 18 | - Glean.at | 18 | + <span class="font-bold text-xl text-spot-text">Glean</span> |
| 19 | </a>{{end}} | 19 | </a>{{end}} |
| 20 | 20 | ||
| 21 | -{{define "logo-text"}}<a href="/" class="text-spot-green font-bold text-lg tracking-tight">Glean.at</a>{{end}} | 21 | +{{define "logo-text"}}<a href="/" class="text-spot-green font-bold text-lg tracking-tight"><span class="font-bold text-xl text-spot-text">Glean</span>.at</a>{{end}} |