Working on Posting
This commit is contained in:
@@ -22,7 +22,6 @@ THE SOFTWARE.
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -311,6 +310,7 @@ func (s *ScreenHome) initCli() {
|
|||||||
s.cli.AddCommand(w.NewCliCommand("getpds", s.cliGetPds))
|
s.cli.AddCommand(w.NewCliCommand("getpds", s.cliGetPds))
|
||||||
s.cli.AddCommand(w.NewCliCommand("authpds", s.cliAuthPds))
|
s.cli.AddCommand(w.NewCliCommand("authpds", s.cliAuthPds))
|
||||||
s.cli.AddCommand(w.NewCliCommand("backuppds", s.cliBackupPds))
|
s.cli.AddCommand(w.NewCliCommand("backuppds", s.cliBackupPds))
|
||||||
|
s.cli.AddCommand(w.NewCliCommand("sendstatus", s.cliSendStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ScreenHome) toggleCli() {
|
func (s *ScreenHome) toggleCli() {
|
||||||
@@ -373,19 +373,18 @@ func (s *ScreenHome) cliAuthPds(args ...string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
s.isLoading = true
|
s.isLoading = true
|
||||||
ctx := context.Background()
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() { s.isLoading = false }()
|
defer func() { s.isLoading = false }()
|
||||||
atid := s.activePds.AtId.String()
|
atid := s.activePds.AtId.String()
|
||||||
callbackRes := make(chan url.Values, 1)
|
callbackRes := make(chan url.Values, 1)
|
||||||
listenPort, err := s.r.Auth.ListenForCallback(ctx, callbackRes)
|
listenPort, err := s.r.Auth.ListenForCallback(callbackRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log("Error Instantiating HTTP Server for Callback: %w", err)
|
s.Log("Error Instantiating HTTP Server for Callback: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.Log("Listening on %d", listenPort)
|
s.Log("Listening on %d", listenPort)
|
||||||
var authUrl string
|
var authUrl string
|
||||||
authUrl, err = s.r.Auth.StartAuthFlow(listenPort, ctx, atid, callbackRes)
|
authUrl, err = s.r.Auth.StartAuthFlow(listenPort, atid, callbackRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log("Error starting auth flow: %w", err)
|
s.Log("Error starting auth flow: %w", err)
|
||||||
}
|
}
|
||||||
@@ -414,6 +413,23 @@ func (s *ScreenHome) cliBackupPds(args ...string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ScreenHome) cliSendStatus(args ...string) bool {
|
||||||
|
if s.activePds == nil {
|
||||||
|
s.Log("No active PDS.")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
s.isLoading = true
|
||||||
|
go func() {
|
||||||
|
defer func() { s.isLoading = false }()
|
||||||
|
if !s.r.Auth.HasAuth() {
|
||||||
|
s.Log("Not authorized. Run `authpds`")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.r.SendToPDS()
|
||||||
|
}()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ScreenHome) updatePdsListing() {
|
func (s *ScreenHome) updatePdsListing() {
|
||||||
s.pdsListing.SetTitle(fmt.Sprintf("─ %s (%s)", s.activePds.AtId.String(), s.activePds.Did.String()))
|
s.pdsListing.SetTitle(fmt.Sprintf("─ %s (%s)", s.activePds.AtId.String(), s.activePds.Did.String()))
|
||||||
s.pdsListing.Clear()
|
s.pdsListing.Clear()
|
||||||
|
|||||||
32
data/repo.go
32
data/repo.go
@@ -22,10 +22,13 @@ THE SOFTWARE.
|
|||||||
package data
|
package data
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.bullercodeworks.com/brian/expds/data/models"
|
"git.bullercodeworks.com/brian/expds/data/models"
|
||||||
|
"github.com/bluesky-social/indigo/atproto/syntax"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,6 +40,8 @@ type Repo struct {
|
|||||||
|
|
||||||
handler *AppLogHandler
|
handler *AppLogHandler
|
||||||
logFunc func(string, ...any)
|
logFunc func(string, ...any)
|
||||||
|
|
||||||
|
context context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepo() (*Repo, error) {
|
func NewRepo() (*Repo, error) {
|
||||||
@@ -44,6 +49,7 @@ func NewRepo() (*Repo, error) {
|
|||||||
LoadedPDSs: make(map[string]*models.Pds),
|
LoadedPDSs: make(map[string]*models.Pds),
|
||||||
BestBy: time.Minute * 15,
|
BestBy: time.Minute * 15,
|
||||||
handler: NewAppLogHandler(nil),
|
handler: NewAppLogHandler(nil),
|
||||||
|
context: context.Background(),
|
||||||
}
|
}
|
||||||
if viper.GetBool(KeyDebug) {
|
if viper.GetBool(KeyDebug) {
|
||||||
r.handler.SetLevel(slog.LevelDebug)
|
r.handler.SetLevel(slog.LevelDebug)
|
||||||
@@ -70,6 +76,32 @@ func (r *Repo) GetPDS(atId string) (*models.Pds, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Repo) SendToPDS() error {
|
||||||
|
session, err := r.Auth.GetSession()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c := session.APIClient()
|
||||||
|
body := map[string]any{
|
||||||
|
"repo": c.AccountDID.String(),
|
||||||
|
"collection": "com.bullercodeworks.expds.status",
|
||||||
|
"record": map[string]any{
|
||||||
|
"$type": "com.bullercodeworks.expds.status",
|
||||||
|
"text": "writeable",
|
||||||
|
"createdAt": syntax.DatetimeNow(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var resp struct {
|
||||||
|
Uri syntax.ATURI `json:"uri"`
|
||||||
|
}
|
||||||
|
slog.Debug("posting expds status...")
|
||||||
|
if err := c.Post(r.context, "com.atproto.repo.CreateRecord", body, &resp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slog.Debug(fmt.Sprintf("posted: %s :: %s", resp.Uri.Authority(), resp.Uri.RecordKey()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Repo) SetLogFunc(l func(string, ...any)) {
|
func (r *Repo) SetLogFunc(l func(string, ...any)) {
|
||||||
r.logFunc = l
|
r.logFunc = l
|
||||||
r.handler = NewAppLogHandler(r.logFunc)
|
r.handler = NewAppLogHandler(r.logFunc)
|
||||||
|
|||||||
@@ -21,12 +21,16 @@ type AuthRepo struct {
|
|||||||
oauthClient *oauth.ClientApp
|
oauthClient *oauth.ClientApp
|
||||||
oauthConfig *oauth.ClientConfig
|
oauthConfig *oauth.ClientConfig
|
||||||
store *SqliteStore
|
store *SqliteStore
|
||||||
|
context context.Context
|
||||||
|
|
||||||
session *oauth.ClientSessionData
|
session *oauth.ClientSessionData
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthRepo(r *Repo) (*AuthRepo, error) {
|
func NewAuthRepo(r *Repo) (*AuthRepo, error) {
|
||||||
a := &AuthRepo{r: r}
|
a := &AuthRepo{
|
||||||
|
r: r,
|
||||||
|
context: r.context,
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
a.oauthConfig, a.oauthClient, a.store, err = a.buildOAuthClient()
|
a.oauthConfig, a.oauthClient, a.store, err = a.buildOAuthClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,7 +43,7 @@ func NewAuthRepo(r *Repo) (*AuthRepo, error) {
|
|||||||
func (r *AuthRepo) buildOAuthClient() (*oauth.ClientConfig, *oauth.ClientApp, *SqliteStore, error) {
|
func (r *AuthRepo) buildOAuthClient() (*oauth.ClientConfig, *oauth.ClientApp, *SqliteStore, error) {
|
||||||
config := oauth.ClientConfig{
|
config := oauth.ClientConfig{
|
||||||
ClientID: "https://expds.bullercodeworks.com/oauth-client-metadata.json",
|
ClientID: "https://expds.bullercodeworks.com/oauth-client-metadata.json",
|
||||||
Scopes: []string{"atproto", "repo:*"},
|
Scopes: []string{"atproto", "repo:*", "blob:*/*"},
|
||||||
UserAgent: "expds",
|
UserAgent: "expds",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,9 +61,9 @@ func (r *AuthRepo) buildOAuthClient() (*oauth.ClientConfig, *oauth.ClientApp, *S
|
|||||||
return &config, oauthClient, store, nil
|
return &config, oauthClient, store, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AuthRepo) StartAuthFlow(port int, ctx context.Context, identifier string, callbackRes chan url.Values) (string, error) {
|
func (r *AuthRepo) StartAuthFlow(port int, identifier string, callbackRes chan url.Values) (string, error) {
|
||||||
r.oauthConfig.CallbackURL = fmt.Sprintf("http://127.0.0.1:%d/callback", port)
|
r.oauthConfig.CallbackURL = fmt.Sprintf("http://127.0.0.1:%d/callback", port)
|
||||||
authUrl, err := r.oauthClient.StartAuthFlow(ctx, identifier)
|
authUrl, err := r.oauthClient.StartAuthFlow(r.context, identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error logging in: %w", err)
|
return "", fmt.Errorf("error logging in: %w", err)
|
||||||
}
|
}
|
||||||
@@ -68,7 +72,7 @@ func (r *AuthRepo) StartAuthFlow(port int, ctx context.Context, identifier strin
|
|||||||
}
|
}
|
||||||
exec.Command("xdg-open", authUrl).Run()
|
exec.Command("xdg-open", authUrl).Run()
|
||||||
|
|
||||||
r.session, err = r.oauthClient.ProcessCallback(ctx, <-callbackRes)
|
r.session, err = r.oauthClient.ProcessCallback(r.context, <-callbackRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -82,7 +86,7 @@ func (r *AuthRepo) prepareDbPath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTTP Server listening for OAuth Response
|
// HTTP Server listening for OAuth Response
|
||||||
func (r *AuthRepo) ListenForCallback(ctx context.Context, res chan url.Values) (int, error) {
|
func (r *AuthRepo) ListenForCallback(res chan url.Values) (int, error) {
|
||||||
listener, err := net.Listen("tcp", ":0")
|
listener, err := net.Listen("tcp", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -93,12 +97,12 @@ func (r *AuthRepo) ListenForCallback(ctx context.Context, res chan url.Values) (
|
|||||||
Handler: mux,
|
Handler: mux,
|
||||||
}
|
}
|
||||||
|
|
||||||
mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/callback", func(w http.ResponseWriter, req *http.Request) {
|
||||||
res <- r.URL.Query()
|
res <- req.URL.Query()
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
w.Write([]byte("<!DOCTYPE html><html><body><h2>expds</h2><p>You can safely close this window and return to your application.</p></body></html>\n"))
|
w.Write([]byte("<!DOCTYPE html><html><body><h2>expds</h2><p>You can safely close this window and return to your application.</p></body></html>\n"))
|
||||||
go server.Shutdown(ctx)
|
go server.Shutdown(r.context)
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -110,3 +114,16 @@ func (r *AuthRepo) ListenForCallback(ctx context.Context, res chan url.Values) (
|
|||||||
|
|
||||||
return listener.Addr().(*net.TCPAddr).Port, nil
|
return listener.Addr().(*net.TCPAddr).Port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AuthRepo) HasAuth() bool {
|
||||||
|
sess, err := r.store.GetMostRecentSession(r.context)
|
||||||
|
return err != nil || sess == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AuthRepo) GetSession() (*oauth.ClientSession, error) {
|
||||||
|
sess, err := r.store.GetMostRecentSession(r.context)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error getting most recent session: %w", err)
|
||||||
|
}
|
||||||
|
return r.oauthClient.ResumeSession(r.context, sess.AccountDID, sess.SessionID)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"authorization_code",
|
"authorization_code",
|
||||||
"refresh_token"
|
"refresh_token"
|
||||||
],
|
],
|
||||||
"scope": "atproto repo:*",
|
"scope": "atproto repo:* blob:*/*",
|
||||||
"response_types": [
|
"response_types": [
|
||||||
"code"
|
"code"
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user