From 01776f0ec0774d030e7f180bab3af75d9b6c6b2f Mon Sep 17 00:00:00 2001 From: sunglocto Date: Sat, 22 Nov 2025 09:15:52 +0000 Subject: [PATCH] Extremely basic functionality, posting --- main.go | 103 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/main.go b/main.go index 19a524a..04b5933 100644 --- a/main.go +++ b/main.go @@ -3,58 +3,61 @@ package main import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" - "fyne.io/fyne/v2/widget" + "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" - "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" + "github.com/google/uuid" "github.com/kirsle/configdir" "github.com/mattn/go-mastodon" - "github.com/google/uuid" webview "github.com/webview/webview_go" "encoding/json" "path/filepath" + "context" "errors" "fmt" "log" "os" - "context" + "strings" ) var App fyne.App var MainWindow fyne.Window +// Client used for posting, getting posts, etc. +var Client *mastodon.Client + // Federale config settings apply to all profiles. // The config stores the name of the profile to launch, // as well as if the profile selection screen should // show when the program is next launched. type FederaleConfig struct { - ProfileName string + ProfileName string DoNotDropToProfileSelection bool } type FederaleProfile struct { // Blueprint for a Federale profile - Name string // Name displayed to user + Name string // Name displayed to user InternalName string // Filename - Server string // Homeserver to connect to + Server string // Homeserver to connect to Username string // Username of user (user@domain) - - ClientID string // ID of the client + + ClientID string // ID of the client ClientSecret string // Secret of the client UserAuthorizationCode string // Authorization code of the user - Running bool // Whether the profile is currently running } var LoadedProfile *FederaleProfile // Profile currently loaded into memory for this Federale instance -var LoadedConfig *FederaleConfig // Config currently loaded into memory -var Profiles []*FederaleProfile // Profiles loaded from FS go here. +var LoadedConfig *FederaleConfig // Config currently loaded into memory +var Profiles []*FederaleProfile // Profiles loaded from FS go here. var ProfileSetupDone bool = false var ProfileSetupProfile *FederaleProfile @@ -68,7 +71,7 @@ func SaveConfigToDisk() error { err := configdir.MakePath(ConfigPath) // Ensure it exists. if err != nil { - return err + return err } ConfigFilePath := filepath.Join(ConfigPath, "federale.json") @@ -93,7 +96,7 @@ func ProfileLaunch() { err := configdir.MakePath(ConfigPath) // Ensure it exists. if err != nil { - panic(err) + panic(err) } Files, err := os.ReadDir(ConfigPath) @@ -139,13 +142,16 @@ func ProfileLaunch() { AddProfileWindow.SetFixedSize(true) GoButton := widget.NewButton("Go", func() { + if !strings.HasPrefix(InstanceEntry.Text, "https://") { + InstanceEntry.SetText("https://" + InstanceEntry.Text) // FIXME: This may not work with darknet instances? + } Domain := InstanceEntry.Text // Step one: register the application AppConfig := &mastodon.AppConfig{ - Server: Domain, - ClientName: "Federalé", - Scopes: "read write push", - Website: "https://forge.sunglocto.net", + Server: Domain, + ClientName: "Federalé", + Scopes: "read write push", + Website: "https://forge.sunglocto.net", RedirectURIs: "urn:ietf:wg:oauth:2.0:oob", } @@ -167,10 +173,10 @@ func ProfileLaunch() { AddProfileWindow.Resize(fyne.NewSize(500, 500)) // Step three: get the authorization code from the user - dialog.ShowConfirm("Confirm", "Do you have an authorisation code?", func (b bool) { + dialog.ShowConfirm("Confirm", "Do you have an authorisation code?", func(b bool) { if b { NewProfile := new(FederaleProfile) - NewProfile.Name = fmt.Sprintf("Profile %d", len(Profiles) + 1) + NewProfile.Name = fmt.Sprintf("Profile %d", len(Profiles)+1) NewProfile.InternalName = uuid.New().String() NewProfile.Server = Domain NewProfile.ClientID = app.ClientID @@ -187,14 +193,27 @@ func ProfileLaunch() { dialog.ShowForm("Enter authorization code", "Continue", "Exit", FormItems, func(b bool) { if b { - NewProfile.UserAuthorizationCode = AuthPasswordWidget.Text + config := &mastodon.Config{ + Server: NewProfile.Server, + ClientID: NewProfile.ClientID, + ClientSecret: NewProfile.ClientSecret, + } + + // Create the client + c := mastodon.NewClient(config) + + err = c.GetUserAccessToken(context.Background(), AuthPasswordWidget.Text, app.RedirectURI) + if err != nil { + panic(err) + } + NewProfile.UserAuthorizationCode = c.Config.AccessToken fmt.Println("Successfully created user profile:\n", NewProfile) // Save profile to disk b, err := json.MarshalIndent(NewProfile, "", "\t") if err != nil { panic(err) } - err = os.WriteFile(filepath.Join(ConfigPath, NewProfile.InternalName + ".json"), b, 0644) + err = os.WriteFile(filepath.Join(ConfigPath, NewProfile.InternalName+".json"), b, 0644) if err != nil { panic(err) } @@ -234,9 +253,6 @@ func ProfileLaunch() { ) } - - - Box.Add(ProfileSelection) RootBox := container.New(layout.NewCenterLayout(), Box) @@ -267,8 +283,6 @@ func ProfileLaunch() { } } - - func main() { log.Println("Checking for federale config") @@ -278,7 +292,7 @@ func main() { err := configdir.MakePath(ConfigPath) // Ensure it exists. log.Println("Creating federale folder if it does not exist") if err != nil { - panic(err) + panic(err) } log.Println("Checking if configuration file exists") @@ -330,23 +344,46 @@ func main() { return } - ProfilePath := filepath.Join(ConfigPath, LoadedConfig.ProfileName + ".json") - log.Println("Reading profile from disk") + ProfilePath := filepath.Join(ConfigPath, LoadedConfig.ProfileName+".json") b, err = os.ReadFile(ProfilePath) if err != nil { panic(err) } + + tempprof := new(FederaleProfile) log.Println("Unmarshalling config to RAM") - err = json.Unmarshal(b, LoadedConfig) + err = json.Unmarshal(b, tempprof) if err != nil { - return + panic(err) } + LoadedProfile = tempprof //////////////////////////////////////////////////// + config := &mastodon.Config{ + Server: LoadedProfile.Server, + ClientID: LoadedProfile.ClientID, + ClientSecret: LoadedProfile.ClientSecret, + AccessToken: LoadedProfile.UserAuthorizationCode, + } + + Client = mastodon.NewClient(config) + log.Println(Client) + App = app.New() MainWindow = App.NewWindow("Federalé") - MainWindow.SetContent(widget.NewLabel("Hello World!")) + TootEntry := widget.NewEntry() + MainWindow.SetContent(container.NewVBox(TootEntry, widget.NewButton("Post", func() { + toot := mastodon.Toot{ + Status: TootEntry.Text, + Visibility: "public", + } + + _, err := Client.PostStatus(context.Background(), &toot) + if err != nil { + dialog.ShowError(err, MainWindow) + } + }))) MainWindow.ShowAndRun() }