--- a/app.go Tue Apr 11 17:15:12 2017 +0200
+++ b/app.go Wed Apr 12 14:27:09 2017 +0200
@@ -7,13 +7,7 @@
"strings"
)
-var (
- ourScopes = []string{
- "read",
- "write",
- "follow",
- }
-)
+var ()
type registerApp struct {
ID string `json:"id"`
@@ -21,9 +15,17 @@
ClientSecret string `json:"client_secret"`
}
-func registerApplication(name string, scopes []string, redirectURI, baseURL string) (g *Gondole, err error) {
- g = &Gondole{
+// NewApp registers a new instance
+func NewApp(name string, scopes []string, redirectURI, baseURL string) (g *Client, err error) {
+ var endpoint string
+
+ if baseURL != "" {
+ endpoint = baseURL
+ }
+
+ g = &Client{
Name: name,
+ APIBase: endpoint,
}
req := g.prepareRequest("apps")
@@ -47,54 +49,16 @@
if err != nil {
log.Fatalf("error can not register app: %v", err)
}
- g.ID = resp.ClientID
- g.Secret = resp.ClientSecret
- server := &Server{
- ID: g.ID,
- Name: name,
- BearerToken: g.Secret,
- BaseURL: baseURL,
- }
- err = server.WriteToken(name)
if err != nil {
log.Fatalf("error: can not write token for %s", name)
}
- return
-}
-// NewApp registers a new instance
-func NewApp(name string, scopes []string, redirectURI, baseURL string) (g *Gondole, err error) {
-
- if baseURL != "" {
- APIEndpoint = baseURL
- }
-
- // Load configuration, will register if none is found
- cnf, err := LoadConfig(name)
- if err != nil {
- // Nothing exist yet
- cnf := Config{
- Default: name,
- }
- err = cnf.Write()
- if err != nil {
- log.Fatalf("error: can not write config for %s", name)
- }
-
- // Now register this through OAuth
- if scopes == nil {
- scopes = ourScopes
- }
-
- g, err = registerApplication(name, scopes, redirectURI, baseURL)
-
- } else {
- g = &Gondole{
- Name: cnf.Name,
- ID: cnf.ID,
- Secret: cnf.BearerToken,
- }
+ g = &Client{
+ Name: name,
+ ID: resp.ClientID,
+ Secret: resp.ClientSecret,
+ APIBase: endpoint,
}
return
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/config.go Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,140 @@
+// config.go
+//
+// This file implements the configuration part for when you need the API
+// key to modify things in the Mastodon configuration and manage measurements.
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+
+ "github.com/naoina/toml"
+)
+
+/*
+Assume the application is registered if $HOME/.config/<gondole>/config.toml already exist
+We will store the per-instance token into $HOME/.config/<gondole>/<site>.token
+*/
+
+const (
+ DefaultName = "config.toml"
+)
+
+var (
+ baseDir = filepath.Join(os.Getenv("HOME"),
+ ".config",
+ "gondole",
+ )
+)
+
+func loadGlobal(file string) (c *Config, err error) {
+ log.Printf("file=%s", file)
+ // Check if there is any config file
+ _, err = os.Stat(file)
+ if err != nil {
+ return
+ }
+
+ log.Printf("file=%s, found it", file)
+ // Read it
+ buf, err := ioutil.ReadFile(file)
+ if err != nil {
+ return c, fmt.Errorf("Can not read %s", file)
+ }
+
+ cnf := Config{}
+ err = toml.Unmarshal(buf, &cnf)
+ if err != nil {
+ return c, fmt.Errorf("Error parsing toml %s: %v", file, err)
+ }
+ c = &cnf
+ return
+}
+
+func loadInstance(name string) (s *Server, err error) {
+ // Load instance-specific file
+ file := filepath.Join(baseDir, name+".token")
+
+ log.Printf("instance is %s", file)
+
+ // Check if there is any config file
+ if _, err = os.Stat(file); err == nil {
+ // Read it
+ buf, err := ioutil.ReadFile(file)
+ if err != nil {
+ return s, fmt.Errorf("Can not read %s", file)
+ }
+
+ sc := Server{}
+ err = toml.Unmarshal(buf, &sc)
+ if err != nil {
+ return s, fmt.Errorf("Error parsing toml %s: %v", file, err)
+ }
+ s = &sc
+ }
+ return
+}
+
+func GetInstanceList() (list []string) {
+ list, err := filepath.Glob(filepath.Join(baseDir, "*.token"))
+ log.Printf("basedir=%s", filepath.Join(baseDir, "*.token"))
+ if err != nil {
+ log.Printf("warning, no *.token files in %s", baseDir)
+ list = nil
+ }
+ log.Printf("list=%v", list)
+ return
+}
+
+// LoadConfig reads a file as a TOML document and return the structure
+func LoadConfig(name string) (s *Server, err error) {
+ // Load global file
+ gFile := filepath.Join(baseDir, DefaultName)
+
+ log.Printf("global is %s", gFile)
+ c, err := loadGlobal(gFile)
+ if err != nil {
+ return
+ }
+ if name == "" {
+ s, err = loadInstance(c.Default)
+ } else {
+ s, err = loadInstance(name)
+ }
+
+ return s, err
+}
+
+func (c *Config) Write() (err error) {
+ if err = os.MkdirAll(baseDir, 0700); err != nil {
+ log.Fatalf("error creating configuration directory: %s", baseDir)
+ }
+
+ var sc []byte
+
+ if sc, err = toml.Marshal(*c); err != nil {
+ log.Fatalf("error saving configuration")
+ }
+ err = ioutil.WriteFile(filepath.Join(baseDir, DefaultName), sc, 0600)
+ return
+}
+
+func (s *Server) WriteToken(instance string) (err error) {
+ if err = os.MkdirAll(baseDir, 0700); err != nil {
+ log.Fatalf("error creating configuration directory: %s", baseDir)
+ }
+
+ var sc []byte
+
+ if sc, err = toml.Marshal(s); err != nil {
+ log.Fatalf("error saving configuration")
+ }
+
+ full := instance + ".token"
+ err = ioutil.WriteFile(filepath.Join(baseDir, full), sc, 0600)
+ return
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/config_test.go Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,105 @@
+package main
+
+import (
+ "github.com/stretchr/testify/assert"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestLoadGlobal(t *testing.T) {
+ baseDir = "."
+
+ _, err := loadGlobal(filepath.Join("test", "non.toml"))
+ assert.Error(t, err, "does not exist")
+
+ _, err = loadGlobal(filepath.Join("test", "garbage.token"))
+ assert.Error(t, err, "just garbage")
+
+ // git does now allow you to checkin 000 files :(
+ err = os.Chmod(filepath.Join("test", "perms.toml"), 0000)
+ assert.NoError(t, err, "should be fine")
+ _, err = loadGlobal(filepath.Join("test", "perms.toml"))
+ assert.Error(t, err, "unreadable")
+ err = os.Chmod(filepath.Join("test", "perms.toml"), 0600)
+ assert.NoError(t, err, "should be fine")
+
+ c, err := loadGlobal(filepath.Join("test", "config.toml"))
+ assert.NoError(t, err, "should read it fine")
+ assert.EqualValues(t, "foo", c.Default, "equal")
+}
+
+func TestLoadInstance(t *testing.T) {
+ baseDir = "."
+
+ _, err := loadInstance("nonexistent")
+ assert.Error(t, err, "does not exist")
+
+ file := filepath.Join("test", "garbage")
+ _, err = loadInstance(file)
+ assert.Error(t, err, "just garbage")
+
+ file = filepath.Join("test", "foo.token")
+ err = os.Chmod(file, 0000)
+ assert.NoError(t, err, "should be fine")
+
+ file = filepath.Join("test", "foo")
+ _, err = loadInstance(file)
+ assert.Error(t, err, "unreadable")
+
+ file = filepath.Join("test", "foo.token")
+ err = os.Chmod(file, 0644)
+ assert.NoError(t, err, "should be fine")
+
+ real := &Server{
+ ID: "666",
+ Name: "foo",
+ BearerToken: "d3b07384d113edec49eaa6238ad5ff00",
+ BaseURL: "https://mastodon.social",
+ }
+ file = filepath.Join("test", "foo")
+ s, err := loadInstance(file)
+ assert.NoError(t, err, "all fine")
+ assert.Equal(t, real, s, "equal")
+}
+
+func TestGetInstanceList(t *testing.T) {
+ baseDir = "test"
+
+ real := []string{
+ filepath.Join("test", "foo.token"),
+ filepath.Join("test", "garbage.token"),
+ }
+ list := GetInstanceList()
+ assert.Equal(t, real, list, "equal")
+
+ baseDir = "/tmp"
+ real = nil
+ list = GetInstanceList()
+ assert.Equal(t, real, list, "equal")
+
+ baseDir = "/nonexistent"
+ real = nil
+ list = GetInstanceList()
+ assert.Equal(t, real, list, "equal")
+}
+
+func TestLoadConfig(t *testing.T) {
+ baseDir = "test"
+
+ _, err := LoadConfig("foo")
+ assert.NoError(t, err, "should be fine")
+
+ _, err = LoadConfig("")
+ assert.NoError(t, err, "should be fine")
+
+ err = os.Chmod(filepath.Join("test", "config.toml"), 0000)
+ assert.NoError(t, err, "should be fine")
+
+ _, err = LoadConfig("")
+ assert.Error(t, err, "should be unreadable")
+
+ err = os.Chmod(filepath.Join("test", "config.toml"), 0600)
+ assert.NoError(t, err, "should be fine")
+
+}
\ No newline at end of file
--- a/cmd/gondole-cli/main.go Tue Apr 11 17:15:12 2017 +0200
+++ b/cmd/gondole-cli/main.go Wed Apr 12 14:27:09 2017 +0200
@@ -5,17 +5,95 @@
"github.com/urfave/cli"
"log"
"os"
+ "strings"
)
var (
- fVerbose bool
- fBaseURL string
- instance *gondole.Gondole
- cnf *gondole.Config
+ fVerbose bool
+ fInstance string
+ fScopes string
+
+ instance *gondole.Client
+ cnf *Server
+
+ // For bootstrapping, override the API endpoint w/o any possible /api/vN, that is
+ // supplied by the library
+ APIEndpoint string
+
+ // Deduced though the full instance URL when registering
+ InstanceName string
+
+ // Default scopes
+ ourScopes = []string{
+ "read",
+ "write",
+ "follow",
+ }
)
-func Register(c *cli.Context) (err error) {
- instance, err = gondole.NewApp("gondole-cli", nil, gondole.NoRedirect, fBaseURL)
+// Config holds our parameters
+type Server struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ BearerToken string `json:"bearer_token"`
+ BaseURL string `json:"base_url"` // Allow for overriding APIEndpoint on registration
+}
+
+type Config struct {
+ Default string
+}
+
+func setupEnvironment(c *cli.Context) (err error) {
+ var scopes []string
+
+ if fInstance != "" {
+ InstanceName = basename(fInstance)
+ APIEndpoint = filterURL(fInstance)
+ }
+
+ // Load configuration, will register if none is found
+ cnf, err = LoadConfig(InstanceName)
+ if err != nil {
+ // Nothing exist yet
+ defName := Config{
+ Default: InstanceName,
+ }
+ err = defName.Write()
+ if err != nil {
+ log.Fatalf("error: can not write config for %s", InstanceName)
+ }
+
+ // Now register this through OAuth
+ if fScopes != "" {
+ scopes = strings.Split(fScopes, " ")
+ } else {
+ scopes = ourScopes
+ }
+
+ instance, err = gondole.NewApp("gondole-cli", scopes, gondole.NoRedirect, fInstance)
+
+ server := &Server{
+ ID: instance.ID,
+ Name: instance.Name,
+ BearerToken: instance.Secret,
+ BaseURL: instance.APIBase,
+ }
+ err = server.WriteToken(InstanceName)
+ if err != nil {
+ log.Fatalf("error: can not write token for %s", instance.Name)
+ }
+
+ cnf := Config{
+ Default: instance.Name,
+ }
+
+ err = cnf.Write()
+ if err != nil {
+ log.Fatalf("error: can not write config for %s", instance.Name)
+ }
+
+ }
+ // Log in to the instance
return err
}
@@ -36,7 +114,7 @@
app.Version = gondole.APIVersion
//app.HideVersion = true
- app.Before = Register
+ app.Before = setupEnvironment
app.Flags = []cli.Flag{
cli.BoolFlag{
@@ -45,9 +123,14 @@
Destination: &fVerbose,
},
cli.StringFlag{
- Name: "instance,i",
+ Name: "instance,I",
Usage: "use that instance",
- Destination: &fBaseURL,
+ Destination: &fInstance,
+ },
+ cli.StringFlag{
+ Name: "scopes,S",
+ Usage: "use these scopes",
+ Destination: &fScopes,
},
}
app.Run(os.Args)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/test/config.toml Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,1 @@
+default="foo"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/test/foo.token Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,4 @@
+id = "666"
+name = "foo"
+bearer_token = "d3b07384d113edec49eaa6238ad5ff00"
+base_URL = "https://mastodon.social"
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/test/garbage.token Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,1 @@
+>'''(fsljfùùksdjlf1656>
--- a/cmd/gondole-cli/utils.go Tue Apr 11 17:15:12 2017 +0200
+++ b/cmd/gondole-cli/utils.go Wed Apr 12 14:27:09 2017 +0200
@@ -1,6 +1,10 @@
package main
-import "github.com/urfave/cli"
+import (
+ "github.com/urfave/cli"
+ "net/url"
+ "strings"
+)
// ByAlphabet is for sorting
type ByAlphabet []cli.Command
@@ -9,3 +13,24 @@
func (a ByAlphabet) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAlphabet) Less(i, j int) bool { return a[i].Name < a[j].Name }
+func filterURL(in string) (out string) {
+ uri, err := url.Parse(in)
+ if err != nil {
+ out = ""
+ } else {
+ uri := url.URL{Scheme: uri.Scheme, Host: uri.Host}
+ out = uri.String()
+ }
+ return
+}
+
+func basename(in string) (out string) {
+ uri, err := url.Parse(in)
+ if err != nil {
+ out = ""
+ } else {
+ // Remove the :NN part of present
+ out = strings.Split(uri.Host, ":")[0]
+ }
+ return
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/gondole-cli/utils_test.go Wed Apr 12 14:27:09 2017 +0200
@@ -0,0 +1,30 @@
+package main
+
+import (
+ "testing"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFilterURL(t *testing.T) {
+ in := "https://example.com"
+ out := filterURL(in)
+ assert.EqualValues(t, in, out, "equal")
+}
+
+func TestBasename(t *testing.T) {
+ in := "https://example.com"
+ out := basename(in)
+ assert.EqualValues(t, "example.com", out, "equal")
+
+ in = "https://example.com:80"
+ out = basename(in)
+ assert.EqualValues(t, "example.com", out, "equal")
+
+ in = "https://example.com:16443"
+ out = basename(in)
+ assert.EqualValues(t, "example.com", out, "equal")
+
+ in = "//example.com:443"
+ out = basename(in)
+ assert.EqualValues(t, "example.com", out, "equal")
+}
--- a/config.go Tue Apr 11 17:15:12 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-// config.go
-//
-// This file implements the configuration part for when you need the API
-// key to modify things in the Mastodon configuration and manage measurements.
-
-package gondole
-
-import (
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
-
- "github.com/naoina/toml"
-)
-
-/*
-Assume the application is registered if $HOME/.config/<gondole>/config.toml already exist
-We will store the per-instance token into $HOME/.config/<gondole>/<site>.token
-*/
-
-const (
- DefaultName = "config.toml"
-)
-
-var (
- baseDir = filepath.Join(os.Getenv("HOME"),
- ".config",
- "gondole",
- )
-)
-
-// Config holds our parameters
-type Server struct {
- ID string `json:"id"`
- Name string `json:"name"`
- BearerToken string `json:"bearer_token"`
- BaseURL string `json:"base_url"` // Allow for overriding APIEndpoint on registration
-}
-
-type Config struct {
- Default string
-}
-
-func loadGlobal(file string) (c *Config, err error) {
- log.Printf("file=%s", file)
- // Check if there is any config file
- _, err = os.Stat(file)
- if err != nil {
- return
- }
-
- log.Printf("file=%s, found it", file)
- // Read it
- buf, err := ioutil.ReadFile(file)
- if err != nil {
- return c, fmt.Errorf("Can not read %s", file)
- }
-
- cnf := Config{}
- err = toml.Unmarshal(buf, &cnf)
- if err != nil {
- return c, fmt.Errorf("Error parsing toml %s: %v", file, err)
- }
- c = &cnf
- return
-}
-
-func loadInstance(name string) (s *Server, err error) {
- // Load instance-specific file
- file := filepath.Join(baseDir, name+".token")
-
- log.Printf("instance is %s", file)
-
- // Check if there is any config file
- if _, err = os.Stat(file); err == nil {
- // Read it
- buf, err := ioutil.ReadFile(file)
- if err != nil {
- return s, fmt.Errorf("Can not read %s", file)
- }
-
- sc := Server{}
- err = toml.Unmarshal(buf, &sc)
- if err != nil {
- return s, fmt.Errorf("Error parsing toml %s: %v", file, err)
- }
- s = &sc
- }
- return
-}
-
-func GetInstanceList() (list []string) {
- list, err := filepath.Glob(filepath.Join(baseDir, "*.token"))
- log.Printf("basedir=%s", filepath.Join(baseDir, "*.token"))
- if err != nil {
- log.Printf("warning, no *.token files in %s", baseDir)
- list = nil
- }
- log.Printf("list=%v", list)
- return
-}
-
-// LoadConfig reads a file as a TOML document and return the structure
-func LoadConfig(name string) (s *Server, err error) {
- // Load global file
- gFile := filepath.Join(baseDir, DefaultName)
-
- log.Printf("global is %s", gFile)
- c, err := loadGlobal(gFile)
- if err != nil {
- return
- }
- if name == "" {
- s, err = loadInstance(c.Default)
- } else {
- s, err = loadInstance(name)
- }
-
- return s, err
-}
-
-func (c *Config) Write() (err error) {
- if err = os.MkdirAll(baseDir, 0700); err != nil {
- log.Fatalf("error creating configuration directory: %s", baseDir)
- }
-
- var sc []byte
-
- if sc, err = toml.Marshal(*c); err != nil {
- log.Fatalf("error saving configuration")
- }
- err = ioutil.WriteFile(filepath.Join(baseDir, DefaultName), sc, 0600)
- return
-}
-
-func (s *Server) WriteToken(instance string) (err error) {
- if err = os.MkdirAll(baseDir, 0700); err != nil {
- log.Fatalf("error creating configuration directory: %s", baseDir)
- }
-
- var sc []byte
-
- if sc, err = toml.Marshal(s); err != nil {
- log.Fatalf("error saving configuration")
- }
-
- full := instance + ".token"
- err = ioutil.WriteFile(filepath.Join(baseDir, full), sc, 0600)
- return
-}
--- a/config_test.go Tue Apr 11 17:15:12 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-package gondole
-
-import (
- "github.com/stretchr/testify/assert"
- "os"
- "path/filepath"
- "testing"
-)
-
-func TestLoadGlobal(t *testing.T) {
- baseDir = "."
-
- _, err := loadGlobal(filepath.Join("test", "non.toml"))
- assert.Error(t, err, "does not exist")
-
- _, err = loadGlobal(filepath.Join("test", "garbage.token"))
- assert.Error(t, err, "just garbage")
-
- // git does now allow you to checkin 000 files :(
- err = os.Chmod(filepath.Join("test", "perms.toml"), 0000)
- assert.NoError(t, err, "should be fine")
- _, err = loadGlobal(filepath.Join("test", "perms.toml"))
- assert.Error(t, err, "unreadable")
- err = os.Chmod(filepath.Join("test", "perms.toml"), 0600)
- assert.NoError(t, err, "should be fine")
-
- c, err := loadGlobal(filepath.Join("test", "config.toml"))
- assert.NoError(t, err, "should read it fine")
- assert.EqualValues(t, "foo", c.Default, "equal")
-}
-
-func TestLoadInstance(t *testing.T) {
- baseDir = "."
-
- _, err := loadInstance("nonexistent")
- assert.Error(t, err, "does not exist")
-
- file := filepath.Join("test", "garbage")
- _, err = loadInstance(file)
- assert.Error(t, err, "just garbage")
-
- file = filepath.Join("test", "foo.token")
- err = os.Chmod(file, 0000)
- assert.NoError(t, err, "should be fine")
-
- file = filepath.Join("test", "foo")
- _, err = loadInstance(file)
- assert.Error(t, err, "unreadable")
-
- file = filepath.Join("test", "foo.token")
- err = os.Chmod(file, 0644)
- assert.NoError(t, err, "should be fine")
-
- real := &Server{
- ID: "666",
- Name: "foo",
- BearerToken: "d3b07384d113edec49eaa6238ad5ff00",
- BaseURL: "https://mastodon.social",
- }
- file = filepath.Join("test", "foo")
- s, err := loadInstance(file)
- assert.NoError(t, err, "all fine")
- assert.Equal(t, real, s, "equal")
-}
-
-func TestGetInstanceList(t *testing.T) {
- baseDir = "test"
-
- real := []string{
- filepath.Join("test", "foo.token"),
- filepath.Join("test", "garbage.token"),
- }
- list := GetInstanceList()
- assert.Equal(t, real, list, "equal")
-
- baseDir = "/tmp"
- real = nil
- list = GetInstanceList()
- assert.Equal(t, real, list, "equal")
-
- baseDir = "/nonexistent"
- real = nil
- list = GetInstanceList()
- assert.Equal(t, real, list, "equal")
-}
-
-func TestLoadConfig(t *testing.T) {
- baseDir = "test"
-
- _, err := LoadConfig("foo")
- assert.NoError(t, err, "should be fine")
-
- _, err = LoadConfig("")
- assert.NoError(t, err, "should be fine")
-
- err = os.Chmod(filepath.Join("test", "config.toml"), 0000)
- assert.NoError(t, err, "should be fine")
-
- _, err = LoadConfig("")
- assert.Error(t, err, "should be unreadable")
-
- err = os.Chmod(filepath.Join("test", "config.toml"), 0600)
- assert.NoError(t, err, "should be fine")
-
-}
\ No newline at end of file
--- a/gondole.go Tue Apr 11 17:15:12 2017 +0200
+++ b/gondole.go Wed Apr 12 14:27:09 2017 +0200
@@ -9,7 +9,11 @@
const (
APIVersion = "0.0"
- defAPIEndpoint = "https://mastodon.social/api/v1"
+ // That is not overridable
+ apiURL = "/api/v1"
+
+ // Fallback instance
+ FallBackURL = "https://mastodon.social"
NoRedirect = "urn:ietf:wg:oauth:2.0:oob"
)
@@ -20,27 +24,28 @@
)
// prepareRequest insert all pre-defined stuff
-func (g *Gondole) prepareRequest(what string) (req rest.Request) {
- var endPoint string
+func (g *Client) prepareRequest(what string) (req rest.Request) {
+ var APIBase string
// Allow for overriding for registration
- if APIEndpoint == "" {
- endPoint = defAPIEndpoint
+ if g.APIBase == "" {
+ APIBase = FallBackURL
} else {
- endPoint = APIEndpoint
+ APIBase = g.APIBase
}
- endPoint = endPoint + fmt.Sprintf("/%s", what)
+ APIEndpoint = fmt.Sprintf("%s%s/%", APIBase, apiURL, what)
+
// Add at least one option, the APIkey if present
hdrs := make(map[string]string)
opts := make(map[string]string)
// Insert our sig
- hdrs["User-Agent"] = fmt.Sprintf("Gondole/%s", APIVersion)
+ hdrs["User-Agent"] = fmt.Sprintf("Client/%s", APIVersion)
hdrs["Authorization"] = fmt.Sprintf("Bearer %s", g.Secret)
req = rest.Request{
- BaseURL: endPoint,
+ BaseURL: APIEndpoint,
Headers: hdrs,
QueryParams: opts,
}
--- a/gondole_test.go Tue Apr 11 17:15:12 2017 +0200
+++ b/gondole_test.go Wed Apr 12 14:27:09 2017 +0200
@@ -6,8 +6,12 @@
)
func TestPrepareRequest(t *testing.T) {
- g, err := NewApp("foo", nil, NoRedirect, "")
- assert.NoError(t, err, "no error")
+ g := &Client{
+ Name: "foo",
+ ID: "666",
+ Secret: "biiiip",
+ APIBase: "http://example.com",
+ }
req := g.prepareRequest("bar")
assert.NotNil(t, req.Headers, "not nil")
--- a/test/config.toml Tue Apr 11 17:15:12 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-default="foo"
--- a/test/foo.token Tue Apr 11 17:15:12 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-id = "666"
-name = "foo"
-bearer_token = "d3b07384d113edec49eaa6238ad5ff00"
-base_URL = "https://mastodon.social"
\ No newline at end of file
--- a/test/garbage.token Tue Apr 11 17:15:12 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
->'''(fsljfùùksdjlf1656>
--- a/types.go Tue Apr 11 17:15:12 2017 +0200
+++ b/types.go Wed Apr 12 14:27:09 2017 +0200
@@ -4,133 +4,146 @@
"time"
)
-type Gondole struct {
- Name string
- ID string
- Secret string
-}
-
type Client struct {
- BaseURL string
- BearerToken string
+ Name string
+ ID string
+ Secret string
+ APIBase string
}
/*
-
Entities:
Everything manipulated/returned by the API
*/
+// Account represents a Mastodon account entity
type Account struct {
- ID string
- Username string
- Acct string
- DisplayName string
- Note string
- URL string
- Avatar string
- Header string
- Locked bool
- Followers int
- Followings int
- Statuses int
+ ID int `json:"id"`
+ Username string `json:"username"`
+ Acct string `json:"acct"`
+ DisplayName string `json:"display_name"`
+ Note string `json:"note"`
+ URL string `json:"url"`
+ Avatar string `json:"avatar"`
+ Header string `json:"header"`
+ Locked bool `json:"locked"`
+ CreatedAt string `json:"created_at"`
+ FollowersCount int `json:"followers_count"`
+ FollowingCount int `json:"following_count"`
+ StatusesCount int `json:"statuses_count"`
}
+// Application represents a Mastodon application entity
type Application struct {
- Name string
- Website string
+ Name string `json:"name"`
+ Website string `json:"website"`
}
-type Attachement struct {
- ID string
- Type string
- URL string
- RemoteURL string
- PreviewURL string
- TextURL string
+// Attachment represents a Mastodon attachement entity
+type Attachment struct {
+ ID int `json:"iD"`
+ Type string `json:"type"`
+ URL string `json:"url"`
+ RemoteURL string `json:"remote_url"`
+ PreviewURL string `json:"preview_url"`
+ TextURL string `json:"text_url"`
}
+/*
+// Card represents a Mastodon card entity
type Card struct {
- URL string
- Title string
- Description string
- Image string
+ URL string `json:"url"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Image *interface{} `json:"image"`
+}
+*/
+
+// Context represents a Mastodon context entity
+type Context struct {
+ Ancestors []Status `json:"ancestors"`
+ Descendents []Status `json:"descendents"`
}
-type Context struct {
- Ancestors []Status
- Descendents []Status
+// Error represents a Mastodon error entity
+type Error struct {
+ Text string `json:"error"`
}
-type Error struct {
- Text string
-}
-
+// Instance represents a Mastodon instance entity
type Instance struct {
- URI string
- Title string
- Description string
- Email string
+ URI string `json:"uri"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Email string `json:"email"`
}
+// Mention represents a Mastodon mention entity
type Mention struct {
- ID string
- URL string
- Username string
- Acct string
+ ID int `json:"id"`
+ URL string `json:"url"`
+ Username string `json:"username"`
+ Acct string `json:"acct"`
}
+// Notification represents a Mastodon notification entity
type Notification struct {
- ID string
- Type string
- CreatedAt time.Time
- Account *Account
- Status *Status
+ ID int `json:"id"`
+ Type string `json:"type"`
+ CreatedAt string `json:"created_at"`
+ Account *Account `json:"account"`
+ Status *Status `json:"status"`
}
+// Relationship represents a Mastodon relationship entity
type Relationship struct {
- Following bool
- FollowedBy bool
- Blocking bool
- Muting bool
- Requested bool
+ Following bool `json:"following"`
+ FollowedBy bool `json:"followed_by"`
+ Blocking bool `json:"blocking"`
+ Muting bool `json:"muting"`
+ Requested bool `json:"requested"`
}
+
+// Report represents a Mastodon report entity
type Report struct {
- ID int64
- ActionTaken string
+ ID int `json:"iD"`
+ ActionTaken string `json:"action_taken"`
}
-type Result struct {
- Accounts []Account
- Statutes []Status
- Hashtags []Tag
+// Results represents a Mastodon results entity
+type Results struct {
+ Accounts []Account `json:"accounts"`
+ Statuses []Status `json:"statuses"`
+ Hashtags []string `json:"hashtags"`
}
+// Status represents a Mastodon status entity
type Status struct {
- ID string
- URI string
- URL string
- Account *Account
- InReplyToId string
- InReplyToAccountID string
- Reblog *Status
- Content string
- CreatedAT time.Time
- Reblogs int
- Favourites int
- Reblogged bool
- Favourited bool
- Sensitive bool
- SpoilerText string
- Visibility string
- MediaAttachments []Attachement
- Mentions []Mention
- Tags []Tag
- App Application
+ ID int `json:"id"`
+ URI string `json:"uri"`
+ URL string `json:"url"`
+ Account *Account `json:"account"`
+ InReplyToID int `json:"in_reply_to_id"`
+ InReplyToAccountID int `json:"in_reply_to_account_id"`
+ Reblog *Status `json:"reblog"`
+ Content string `json:"content"`
+ CreatedAt time.Time `json:"created_at"`
+ ReblogsCount int `json:"reblogs_count"`
+ FavouritesCount int `json:"favourites_count"`
+ Reblogged bool `json:"reblogged"`
+ Favourited bool `json:"favourited"`
+ Sensitive bool `json:"sensitive"`
+ SpoilerText string `json:"spoiler_text"`
+ Visibility string `json:"visibility"`
+ MediaAttachments []Attachment `json:"media_attachments"`
+ Mentions []Mention `json:"mentions"`
+ Tags []Tag `json:"tags"`
+ Application Application `json:"application"`
}
+// Tag represents a Mastodon tag entity
type Tag struct {
- Name string
- URL string
+ Name string `json:"name"`
+ URL string `json:"url"`
}