Extremely basic functionality, posting
This commit is contained in:
101
main.go
101
main.go
@@ -3,58 +3,61 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/layout"
|
"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/kirsle/configdir"
|
||||||
"github.com/mattn/go-mastodon"
|
"github.com/mattn/go-mastodon"
|
||||||
"github.com/google/uuid"
|
|
||||||
webview "github.com/webview/webview_go"
|
webview "github.com/webview/webview_go"
|
||||||
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"context"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var App fyne.App
|
var App fyne.App
|
||||||
var MainWindow fyne.Window
|
var MainWindow fyne.Window
|
||||||
|
|
||||||
|
// Client used for posting, getting posts, etc.
|
||||||
|
var Client *mastodon.Client
|
||||||
|
|
||||||
// Federale config settings apply to all profiles.
|
// Federale config settings apply to all profiles.
|
||||||
// The config stores the name of the profile to launch,
|
// The config stores the name of the profile to launch,
|
||||||
// as well as if the profile selection screen should
|
// as well as if the profile selection screen should
|
||||||
// show when the program is next launched.
|
// show when the program is next launched.
|
||||||
|
|
||||||
type FederaleConfig struct {
|
type FederaleConfig struct {
|
||||||
ProfileName string
|
ProfileName string
|
||||||
DoNotDropToProfileSelection bool
|
DoNotDropToProfileSelection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type FederaleProfile struct { // Blueprint for a Federale profile
|
type FederaleProfile struct { // Blueprint for a Federale profile
|
||||||
Name string // Name displayed to user
|
Name string // Name displayed to user
|
||||||
InternalName string // Filename
|
InternalName string // Filename
|
||||||
|
|
||||||
Server string // Homeserver to connect to
|
Server string // Homeserver to connect to
|
||||||
Username string // Username of user (user@domain)
|
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
|
ClientSecret string // Secret of the client
|
||||||
|
|
||||||
UserAuthorizationCode string // Authorization code of the user
|
UserAuthorizationCode string // Authorization code of the user
|
||||||
|
|
||||||
|
|
||||||
Running bool // Whether the profile is currently running
|
Running bool // Whether the profile is currently running
|
||||||
}
|
}
|
||||||
|
|
||||||
var LoadedProfile *FederaleProfile // Profile currently loaded into memory for this Federale instance
|
var LoadedProfile *FederaleProfile // Profile currently loaded into memory for this Federale instance
|
||||||
var LoadedConfig *FederaleConfig // Config currently loaded into memory
|
var LoadedConfig *FederaleConfig // Config currently loaded into memory
|
||||||
var Profiles []*FederaleProfile // Profiles loaded from FS go here.
|
var Profiles []*FederaleProfile // Profiles loaded from FS go here.
|
||||||
|
|
||||||
var ProfileSetupDone bool = false
|
var ProfileSetupDone bool = false
|
||||||
var ProfileSetupProfile *FederaleProfile
|
var ProfileSetupProfile *FederaleProfile
|
||||||
@@ -68,7 +71,7 @@ func SaveConfigToDisk() error {
|
|||||||
|
|
||||||
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigFilePath := filepath.Join(ConfigPath, "federale.json")
|
ConfigFilePath := filepath.Join(ConfigPath, "federale.json")
|
||||||
@@ -93,7 +96,7 @@ func ProfileLaunch() {
|
|||||||
|
|
||||||
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
Files, err := os.ReadDir(ConfigPath)
|
Files, err := os.ReadDir(ConfigPath)
|
||||||
@@ -139,13 +142,16 @@ func ProfileLaunch() {
|
|||||||
AddProfileWindow.SetFixedSize(true)
|
AddProfileWindow.SetFixedSize(true)
|
||||||
|
|
||||||
GoButton := widget.NewButton("Go", func() {
|
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
|
Domain := InstanceEntry.Text
|
||||||
// Step one: register the application
|
// Step one: register the application
|
||||||
AppConfig := &mastodon.AppConfig{
|
AppConfig := &mastodon.AppConfig{
|
||||||
Server: Domain,
|
Server: Domain,
|
||||||
ClientName: "Federalé",
|
ClientName: "Federalé",
|
||||||
Scopes: "read write push",
|
Scopes: "read write push",
|
||||||
Website: "https://forge.sunglocto.net",
|
Website: "https://forge.sunglocto.net",
|
||||||
RedirectURIs: "urn:ietf:wg:oauth:2.0:oob",
|
RedirectURIs: "urn:ietf:wg:oauth:2.0:oob",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,10 +173,10 @@ func ProfileLaunch() {
|
|||||||
AddProfileWindow.Resize(fyne.NewSize(500, 500))
|
AddProfileWindow.Resize(fyne.NewSize(500, 500))
|
||||||
|
|
||||||
// Step three: get the authorization code from the user
|
// 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 {
|
if b {
|
||||||
NewProfile := new(FederaleProfile)
|
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.InternalName = uuid.New().String()
|
||||||
NewProfile.Server = Domain
|
NewProfile.Server = Domain
|
||||||
NewProfile.ClientID = app.ClientID
|
NewProfile.ClientID = app.ClientID
|
||||||
@@ -187,14 +193,27 @@ func ProfileLaunch() {
|
|||||||
|
|
||||||
dialog.ShowForm("Enter authorization code", "Continue", "Exit", FormItems, func(b bool) {
|
dialog.ShowForm("Enter authorization code", "Continue", "Exit", FormItems, func(b bool) {
|
||||||
if b {
|
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)
|
fmt.Println("Successfully created user profile:\n", NewProfile)
|
||||||
// Save profile to disk
|
// Save profile to disk
|
||||||
b, err := json.MarshalIndent(NewProfile, "", "\t")
|
b, err := json.MarshalIndent(NewProfile, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -234,9 +253,6 @@ func ProfileLaunch() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Box.Add(ProfileSelection)
|
Box.Add(ProfileSelection)
|
||||||
RootBox := container.New(layout.NewCenterLayout(), Box)
|
RootBox := container.New(layout.NewCenterLayout(), Box)
|
||||||
|
|
||||||
@@ -267,8 +283,6 @@ func ProfileLaunch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
log.Println("Checking for federale config")
|
log.Println("Checking for federale config")
|
||||||
@@ -278,7 +292,7 @@ func main() {
|
|||||||
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
err := configdir.MakePath(ConfigPath) // Ensure it exists.
|
||||||
log.Println("Creating federale folder if it does not exist")
|
log.Println("Creating federale folder if it does not exist")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Checking if configuration file exists")
|
log.Println("Checking if configuration file exists")
|
||||||
@@ -330,23 +344,46 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfilePath := filepath.Join(ConfigPath, LoadedConfig.ProfileName + ".json")
|
ProfilePath := filepath.Join(ConfigPath, LoadedConfig.ProfileName+".json")
|
||||||
log.Println("Reading profile from disk")
|
|
||||||
b, err = os.ReadFile(ProfilePath)
|
b, err = os.ReadFile(ProfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tempprof := new(FederaleProfile)
|
||||||
log.Println("Unmarshalling config to RAM")
|
log.Println("Unmarshalling config to RAM")
|
||||||
err = json.Unmarshal(b, LoadedConfig)
|
err = json.Unmarshal(b, tempprof)
|
||||||
if err != nil {
|
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()
|
App = app.New()
|
||||||
MainWindow = App.NewWindow("Federalé")
|
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()
|
MainWindow.ShowAndRun()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user