Initial commit
This commit is contained in:
235
main.go
Normal file
235
main.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/container"
|
||||
|
||||
"github.com/kirsle/configdir"
|
||||
"github.com/mattn/go-mastodon"
|
||||
webview "github.com/webview/webview_go"
|
||||
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"context"
|
||||
)
|
||||
|
||||
var App fyne.App
|
||||
var MainWindow fyne.Window
|
||||
|
||||
type FederaleProfile struct { // Blueprint for a Federale profile
|
||||
Name string // Name displayed to user
|
||||
InternalName string // Filename
|
||||
|
||||
Server string // Homeserver to connect to
|
||||
Username string // Username of user (user@domain)
|
||||
|
||||
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 Profiles []*FederaleProfile // Profiles loaded from FS go here.
|
||||
|
||||
var ProfileSetupDone bool = false
|
||||
var ProfileSetupProfile *FederaleProfile
|
||||
|
||||
var ProfileSelectionDone bool = false
|
||||
var ProfileSelectionProfile *FederaleProfile
|
||||
|
||||
// This function asks for the profile to launch Federale with.
|
||||
func ProfileLaunch() (error, *FederaleProfile) {
|
||||
ConfigPath := configdir.LocalConfig("federale") // Federale foler in the user's config directory
|
||||
|
||||
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Files, err := os.ReadDir(ConfigPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, v := range Files {
|
||||
if !v.IsDir() {
|
||||
Profile := new(FederaleProfile)
|
||||
dat, err := os.ReadFile(filepath.Join(ConfigPath, v.Name()))
|
||||
if err != nil {
|
||||
log.Println("ERR - " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dat, Profile)
|
||||
if err != nil {
|
||||
log.Println("ERR - " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
Profiles = append(Profiles, Profile)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
App = app.New()
|
||||
|
||||
Box := container.NewVBox()
|
||||
Box.Add(widget.NewRichTextFromMarkdown("# Please pick a profile"))
|
||||
Box.Add(widget.NewLabel(fmt.Sprintf("There are %d profile(s) available.", len(Profiles))))
|
||||
ProfileSelection := container.NewVBox(
|
||||
container.NewHBox(
|
||||
widget.NewButton("+ Add profile", func() {
|
||||
AddProfileBox := container.NewVBox()
|
||||
InstanceEntry := widget.NewEntry()
|
||||
InstanceEntry.SetPlaceHolder("https://example.com")
|
||||
|
||||
AddProfileWindow := App.NewWindow("Add a profile")
|
||||
AddProfileWindow.SetFixedSize(true)
|
||||
|
||||
GoButton := widget.NewButton("Go", func() {
|
||||
Domain := InstanceEntry.Text
|
||||
// Step one: register the application
|
||||
AppConfig := &mastodon.AppConfig{
|
||||
Server: Domain,
|
||||
ClientName: "Federalé",
|
||||
Scopes: "read write push",
|
||||
Website: "https://forge.sunglocto.net",
|
||||
RedirectURIs: "urn:ietf:wg:oauth:2.0:oob",
|
||||
}
|
||||
|
||||
app, err := mastodon.RegisterApp(context.Background(), AppConfig)
|
||||
if err != nil {
|
||||
dialog.ShowError(err, AddProfileWindow)
|
||||
}
|
||||
|
||||
fmt.Println("App successfully created:\n", app)
|
||||
// Step two: the user now needs to log in
|
||||
|
||||
Webview := webview.New(false)
|
||||
defer Webview.Destroy()
|
||||
Webview.SetTitle("Authenticate - copy the authorisation code when logged in.")
|
||||
Webview.SetSize(480, 320, webview.HintNone)
|
||||
Webview.Navigate(app.AuthURI)
|
||||
Webview.Run()
|
||||
|
||||
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) {
|
||||
if b {
|
||||
NewProfile := new(FederaleProfile)
|
||||
NewProfile.Name = "boob"
|
||||
NewProfile.InternalName = "boob123456" // TODO: Use UUID
|
||||
NewProfile.Server = Domain
|
||||
NewProfile.ClientID = app.ClientID
|
||||
NewProfile.ClientSecret = app.ClientSecret
|
||||
|
||||
AuthPasswordWidget := widget.NewPasswordEntry()
|
||||
|
||||
AuthCodeInput := new(widget.FormItem)
|
||||
AuthCodeInput.Text = "Authorization code"
|
||||
AuthCodeInput.Widget = AuthPasswordWidget
|
||||
|
||||
var FormItems []*widget.FormItem
|
||||
FormItems = append(FormItems, AuthCodeInput)
|
||||
|
||||
dialog.ShowForm("Enter authorization code", "Continue", "Exit", FormItems, func(b bool) {
|
||||
if b {
|
||||
NewProfile.UserAuthorizationCode = AuthPasswordWidget.Text
|
||||
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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ProfileSetupDone = true
|
||||
ProfileSetupProfile = NewProfile
|
||||
AddProfileWindow.Close()
|
||||
MainWindow.Close()
|
||||
}
|
||||
}, AddProfileWindow)
|
||||
}
|
||||
}, AddProfileWindow)
|
||||
})
|
||||
GoButton.Importance = widget.HighImportance
|
||||
|
||||
AddProfileBox.Add(widget.NewLabel("Federalé will log in via OAuth2\nInstance:"))
|
||||
AddProfileBox.Add(InstanceEntry)
|
||||
AddProfileBox.Add(GoButton)
|
||||
|
||||
AddProfileWindow.SetContent(AddProfileBox)
|
||||
AddProfileWindow.Show()
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
for _, v := range Profiles {
|
||||
ProfileSelection.Add(
|
||||
container.NewHBox(
|
||||
widget.NewLabel(v.Name),
|
||||
widget.NewButton("Log in", func() {
|
||||
ProfileSelectionDone = true
|
||||
ProfileSelectionProfile = v
|
||||
MainWindow.Close()
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Box.Add(ProfileSelection)
|
||||
RootBox := container.New(layout.NewCenterLayout(), Box)
|
||||
MainWindow = App.NewWindow("Please pick a profile")
|
||||
|
||||
MainWindow.SetContent(RootBox)
|
||||
MainWindow.SetFixedSize(true)
|
||||
MainWindow.ShowAndRun()
|
||||
|
||||
if ProfileSetupDone { // A new profile was created. Return this new profile.
|
||||
return nil, ProfileSetupProfile
|
||||
} else { // A profile was either picked from the list OR no profile was picked by the user.
|
||||
if ProfileSelectionDone {
|
||||
return nil, ProfileSelectionProfile
|
||||
} else {
|
||||
return errors.New("no profile specified"), new(FederaleProfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func main() {
|
||||
err, profile := ProfileLaunch()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
LoadedProfile = profile
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
App = app.New()
|
||||
MainWindow = App.NewWindow("Federalé")
|
||||
MainWindow.SetContent(widget.NewLabel("Hello World!"))
|
||||
MainWindow.ShowAndRun()
|
||||
}
|
||||
Reference in New Issue
Block a user