add subcommand for instance details

This commit is contained in:
Dan Anglin 2024-02-21 13:20:32 +00:00
parent e354456c0e
commit 1361482dd4
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
5 changed files with 212 additions and 6 deletions

64
cmd/enbas/instance.go Normal file
View file

@ -0,0 +1,64 @@
package main
import (
"flag"
"fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
)
var instanceDetailsFormat = `INSTANCE:
%s - %s
DOMAIN:
%s
VERSION:
Running GoToSocial %s
CONTACT:
name: %s
username: %s
email: %s
`
type instanceCommand struct {
*flag.FlagSet
summary string
}
func newInstanceCommand(name, summary string) *instanceCommand {
command := instanceCommand{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
summary: summary,
}
command.Usage = commandUsageFunc(command.Name(), command.summary, command.FlagSet)
return &command
}
func (c *instanceCommand) Execute() error {
gtsClient, err := client.NewClientFromConfig()
if err != nil {
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
}
instance, err := gtsClient.GetInstance()
if err != nil {
return fmt.Errorf("unable to retrieve the instance details; %w", err)
}
fmt.Printf(
instanceDetailsFormat,
instance.Title,
instance.Description,
instance.Domain,
instance.Version,
instance.Contact.Account.DisplayName,
instance.Contact.Account.Username,
instance.Contact.Email,
)
return nil
}

View file

@ -11,6 +11,7 @@ import (
const ( const (
login string = "login" login string = "login"
version string = "version" version string = "version"
instance string = "instance"
) )
type Executor interface { type Executor interface {
@ -23,6 +24,7 @@ func main() {
summaries := map[string]string{ summaries := map[string]string{
login: "login to an account on GoToSocial", login: "login to an account on GoToSocial",
version: "print the application's version and build information", version: "print the application's version and build information",
instance: "print the instance information",
} }
flag.Usage = enbasUsageFunc(summaries) flag.Usage = enbasUsageFunc(summaries)
@ -44,6 +46,8 @@ func main() {
executor = newLoginCommand(login, summaries[login]) executor = newLoginCommand(login, summaries[login])
case version: case version:
executor = newVersionCommand(version, summaries[version]) executor = newVersionCommand(version, summaries[version])
case instance:
executor = newInstanceCommand(instance, summaries[instance])
default: default:
fmt.Printf("ERROR: Unknown subcommand: %s\n", subcommand) fmt.Printf("ERROR: Unknown subcommand: %s\n", subcommand)
flag.Usage() flag.Usage()

View file

@ -19,6 +19,17 @@ type Client struct {
Timeout time.Duration Timeout time.Duration
} }
func NewClientFromConfig() (*Client, error) {
config, err := config.NewAuthenticationConfigFromFile()
if err != nil {
return nil, fmt.Errorf("unable to get the authentication configuration; %w", err)
}
currentAuthentication := config.Authentications[config.CurrentAccount]
return NewClient(currentAuthentication), nil
}
func NewClient(authentication config.Authentication) *Client { func NewClient(authentication config.Authentication) *Client {
httpClient := http.Client{} httpClient := http.Client{}
@ -53,6 +64,27 @@ func (g *Client) VerifyCredentials() (model.Account, error) {
return account, nil return account, nil
} }
func (g *Client) GetInstance() (model.InstanceV2, error) {
path := "/api/v2/instance"
url := g.Authentication.Instance + path
ctx, cancel := context.WithTimeout(context.Background(), g.Timeout)
defer cancel()
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return model.InstanceV2{}, fmt.Errorf("unable to create the HTTP request, %w", err)
}
var instance model.InstanceV2
if err := g.sendRequest(request, &instance); err != nil {
return model.InstanceV2{}, fmt.Errorf("received an error after sending the request to get the instance details; %w", err)
}
return instance, nil
}
func (g *Client) sendRequest(request *http.Request, object any) error { func (g *Client) sendRequest(request *http.Request, object any) error {
request.Header.Set("Content-Type", "application/json; charset=utf-8") request.Header.Set("Content-Type", "application/json; charset=utf-8")
request.Header.Set("Accept", "application/json; charset=utf-8") request.Header.Set("Accept", "application/json; charset=utf-8")

View file

@ -39,7 +39,7 @@ func SaveAuthentication(username string, authentication Authentication) (string,
config.Authentications = make(map[string]Authentication) config.Authentications = make(map[string]Authentication)
} else { } else {
config, err = newAuthenticationConfigFromFile() config, err = NewAuthenticationConfigFromFile()
if err != nil { if err != nil {
return "", fmt.Errorf("unable to retrieve the existing authentication configuration; %w", err) return "", fmt.Errorf("unable to retrieve the existing authentication configuration; %w", err)
} }
@ -71,7 +71,7 @@ func SaveAuthentication(username string, authentication Authentication) (string,
return authenticationName, nil return authenticationName, nil
} }
func newAuthenticationConfigFromFile() (AuthenticationConfig, error) { func NewAuthenticationConfigFromFile() (AuthenticationConfig, error) {
path := authenticationConfigFile() path := authenticationConfigFile()
file, err := os.Open(path) file, err := os.Open(path)

View file

@ -0,0 +1,106 @@
package model
type InstanceV2 struct {
AccountDomain string `json:"account_domain"`
Configuration InstanceConfiguration `json:"configuration"`
Contact InstanceV2Contact `json:"contact"`
Description string `json:"description"`
Domain string `json:"domain"`
Languages []string `json:"languages"`
Registrations InstanceV2Registrations `json:"registrations"`
Rules []InstanceRule `json:"rules"`
SourceURL string `json:"source_url"`
Terms string `json:"terms"`
Thumbnail InstanceV2Thumbnail `json:"thumbnail"`
Title string `json:"title"`
Usage InstanceV2Usage `json:"usage"`
Version string `json:"version"`
}
type InstanceConfiguration struct {
Accounts InstanceConfigurationAccounts `json:"accounts"`
Emojis InstanceConfigurationEmojis `json:"emojis"`
MediaAttachments InstanceConfigurationMediaAttachments `json:"media_attachments"`
Polls InstanceConfigurationPolls `json:"polls"`
Statuses InstanceConfigurationStatuses `json:"statuses"`
Translation InstanceV2ConfigurationTranslation `json:"translation"`
URLs InstanceV2URLs `json:"urls"`
}
type InstanceConfigurationAccounts struct {
AllowCustomCSS bool `json:"allow_custom_css"`
MaxFeaturedTags int `json:"max_featured_tags"`
MaxProfileFields int `json:"max_profile_fields"`
}
type InstanceConfigurationEmojis struct {
EmojiSizeLimit int `json:"emoji_size_limit"`
}
type InstanceConfigurationMediaAttachments struct {
ImageMatrixLimit int `json:"image_matrix_limit"`
ImageSizeLimit int `json:"image_size_limit"`
SupportedMimeTypes []string `json:"supported_mime_types"`
VideoFrameRateLimit int `json:"video_frame_rate_limit"`
VideoMatrixLimit int `json:"video_matrix_limit"`
VideoSizeLimit int `json:"video_size_limit"`
}
type InstanceConfigurationPolls struct {
MaxCharactersPerOption int `json:"max_characters_per_option"`
MaxExpiration int `json:"max_expiration"`
MaxOptions int `json:"max_options"`
MinExpiration int `json:"min_expiration"`
}
type InstanceConfigurationStatuses struct {
CharactersReservedPerURL int `json:"characters_reserved_per_url"`
MaxCharacters int `json:"max_characters"`
MaxMediaAttachments int `json:"max_media_attachments"`
SupportedMimeTypes []string `json:"supported_mime_types"`
}
type InstanceV2ConfigurationTranslation struct {
Enabled bool `json:"enabled"`
}
type InstanceV2URLs struct {
Streaming string `json:"streaming"`
}
type InstanceV2Contact struct {
Account Account `json:"account"`
Email string `json:"email"`
}
type InstanceV2Registrations struct {
ApprovalRequired bool `json:"approval_required"`
Enabled bool `json:"enabled"`
Message string `json:"message"`
}
type InstanceRule struct {
ID string `json:"id"`
Text string `json:"text"`
}
type InstanceV2Thumbnail struct {
BlurHash string `json:"blurhash"`
ThumbnailDescription string `json:"thumbnail_description"`
ThumbnailType string `json:"thumbnail_type"`
URL string `json:"url"`
Version InstanceV2ThumbnailVersions `json:"versions"`
}
type InstanceV2ThumbnailVersions struct {
Size1URL string `json:"@1x"`
Size2URL string `json:"@2x"`
}
type InstanceV2Usage struct {
Users InstanceV2Users `json:"users"`
}
type InstanceV2Users struct {
ActiveMonth int `json:"active_month"`
}