feat: add support for muting and unmuting accounts
Now that muting and unmuting accounts are now supported in GoToSocial (as of version 0.16.0) Enbas can now allow users to do that. Users can also see a list of accounts that they've muted.
This commit is contained in:
parent
48666645c7
commit
899160d853
10 changed files with 199 additions and 0 deletions
|
@ -125,6 +125,12 @@ func run() error {
|
||||||
executor.CommandLogin,
|
executor.CommandLogin,
|
||||||
executor.CommandSummaryLookup(executor.CommandLogin),
|
executor.CommandSummaryLookup(executor.CommandLogin),
|
||||||
),
|
),
|
||||||
|
executor.CommandMute: executor.NewMuteOrUnmuteExecutor(
|
||||||
|
printer,
|
||||||
|
configDir,
|
||||||
|
executor.CommandMute,
|
||||||
|
executor.CommandSummaryLookup(executor.CommandMute),
|
||||||
|
),
|
||||||
executor.CommandReject: executor.NewAcceptOrRejectExecutor(
|
executor.CommandReject: executor.NewAcceptOrRejectExecutor(
|
||||||
printer,
|
printer,
|
||||||
configDir,
|
configDir,
|
||||||
|
@ -149,6 +155,12 @@ func run() error {
|
||||||
executor.CommandUnfollow,
|
executor.CommandUnfollow,
|
||||||
executor.CommandSummaryLookup(executor.CommandUnfollow),
|
executor.CommandSummaryLookup(executor.CommandUnfollow),
|
||||||
),
|
),
|
||||||
|
executor.CommandUnmute: executor.NewMuteOrUnmuteExecutor(
|
||||||
|
printer,
|
||||||
|
configDir,
|
||||||
|
executor.CommandUnmute,
|
||||||
|
executor.CommandSummaryLookup(executor.CommandUnmute),
|
||||||
|
),
|
||||||
executor.CommandUnblock: executor.NewBlockOrUnblockExecutor(
|
executor.CommandUnblock: executor.NewBlockOrUnblockExecutor(
|
||||||
printer,
|
printer,
|
||||||
configDir,
|
configDir,
|
||||||
|
|
|
@ -223,3 +223,51 @@ func (g *Client) RejectFollowRequest(accountID string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Client) GetMutedAccounts(limit int) (model.AccountList, error) {
|
||||||
|
url := g.Authentication.Instance + fmt.Sprintf("/api/v1/mutes?limit=%d", limit)
|
||||||
|
|
||||||
|
var accounts []model.Account
|
||||||
|
|
||||||
|
if err := g.sendRequest(http.MethodGet, url, nil, &accounts); err != nil {
|
||||||
|
return model.AccountList{}, fmt.Errorf("received an error after sending the request to get the list of muted accounts: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
muted := model.AccountList{
|
||||||
|
Type: model.AccountListMuted,
|
||||||
|
Accounts: accounts,
|
||||||
|
}
|
||||||
|
|
||||||
|
return muted, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MuteAccountForm struct {
|
||||||
|
Notifications bool `json:"notifications"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Client) MuteAccount(accountID string, form MuteAccountForm) error {
|
||||||
|
data, err := json.Marshal(form)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to marshal the form: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBody := bytes.NewBuffer(data)
|
||||||
|
url := g.Authentication.Instance + "/api/v1/accounts/" + accountID + "/mute"
|
||||||
|
|
||||||
|
if err := g.sendRequest(http.MethodPost, url, requestBody, nil); err != nil {
|
||||||
|
return fmt.Errorf("received an error after sending the request to mute the account: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Client) UnmuteAccount(accountID string) error {
|
||||||
|
url := g.Authentication.Instance + "/api/v1/accounts/" + accountID + "/unmute"
|
||||||
|
|
||||||
|
if err := g.sendRequest(http.MethodPost, url, nil, nil); err != nil {
|
||||||
|
return fmt.Errorf("received an error after sending the request to un-mute the account: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,10 @@ func (b *BlockOrUnblockExecutor) Execute() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error {
|
func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error {
|
||||||
|
if b.accountName == "" {
|
||||||
|
return FlagNotSetError{flagText: flagAccountName}
|
||||||
|
}
|
||||||
|
|
||||||
accountID, err := getAccountID(gtsClient, false, b.accountName, b.configDir)
|
accountID, err := getAccountID(gtsClient, false, b.accountName, b.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
|
|
|
@ -13,12 +13,14 @@ const (
|
||||||
CommandEdit string = "edit"
|
CommandEdit string = "edit"
|
||||||
CommandFollow string = "follow"
|
CommandFollow string = "follow"
|
||||||
CommandLogin string = "login"
|
CommandLogin string = "login"
|
||||||
|
CommandMute string = "mute"
|
||||||
CommandReject string = "reject"
|
CommandReject string = "reject"
|
||||||
CommandRemove string = "remove"
|
CommandRemove string = "remove"
|
||||||
CommandShow string = "show"
|
CommandShow string = "show"
|
||||||
CommandSwitch string = "switch"
|
CommandSwitch string = "switch"
|
||||||
CommandUnblock string = "unblock"
|
CommandUnblock string = "unblock"
|
||||||
CommandUnfollow string = "unfollow"
|
CommandUnfollow string = "unfollow"
|
||||||
|
CommandUnmute string = "unmute"
|
||||||
CommandVersion string = "version"
|
CommandVersion string = "version"
|
||||||
CommandWhoami string = "whoami"
|
CommandWhoami string = "whoami"
|
||||||
|
|
||||||
|
@ -30,12 +32,14 @@ const (
|
||||||
commandEditSummary string = "Edit a specific resource"
|
commandEditSummary string = "Edit a specific resource"
|
||||||
commandFollowSummary string = "Follow a resource (e.g. an account)"
|
commandFollowSummary string = "Follow a resource (e.g. an account)"
|
||||||
commandLoginSummary string = "Login to an account on GoToSocial"
|
commandLoginSummary string = "Login to an account on GoToSocial"
|
||||||
|
commandMuteSummary string = "Mute a resource (e.g. an account)"
|
||||||
commandRejectSummary string = "Reject a request (e.g. a follow request)"
|
commandRejectSummary string = "Reject a request (e.g. a follow request)"
|
||||||
commandRemoveSummary string = "Remove a resource from another resource"
|
commandRemoveSummary string = "Remove a resource from another resource"
|
||||||
commandShowSummary string = "Print details about a specified resource"
|
commandShowSummary string = "Print details about a specified resource"
|
||||||
commandSwitchSummary string = "Perform a switch operation (e.g. switch logged in accounts)"
|
commandSwitchSummary string = "Perform a switch operation (e.g. switch logged in accounts)"
|
||||||
commandUnblockSummary string = "Unblock a resource (e.g. an account)"
|
commandUnblockSummary string = "Unblock a resource (e.g. an account)"
|
||||||
commandUnfollowSummary string = "Unfollow a resource (e.g. an account)"
|
commandUnfollowSummary string = "Unfollow a resource (e.g. an account)"
|
||||||
|
commandUnmuteSummary string = "Unmute a resource (e.g. an account)"
|
||||||
commandVersionSummary string = "Print the application's version and build information"
|
commandVersionSummary string = "Print the application's version and build information"
|
||||||
commandWhoamiSummary string = "Print the account that you are currently logged in to"
|
commandWhoamiSummary string = "Print the account that you are currently logged in to"
|
||||||
)
|
)
|
||||||
|
@ -50,12 +54,14 @@ func CommandSummaryMap() map[string]string {
|
||||||
CommandEdit: commandEditSummary,
|
CommandEdit: commandEditSummary,
|
||||||
CommandFollow: commandFollowSummary,
|
CommandFollow: commandFollowSummary,
|
||||||
CommandLogin: commandLoginSummary,
|
CommandLogin: commandLoginSummary,
|
||||||
|
CommandMute: commandMuteSummary,
|
||||||
CommandReject: commandRejectSummary,
|
CommandReject: commandRejectSummary,
|
||||||
CommandRemove: commandRemoveSummary,
|
CommandRemove: commandRemoveSummary,
|
||||||
CommandShow: commandShowSummary,
|
CommandShow: commandShowSummary,
|
||||||
CommandSwitch: commandSwitchSummary,
|
CommandSwitch: commandSwitchSummary,
|
||||||
CommandUnblock: commandUnblockSummary,
|
CommandUnblock: commandUnblockSummary,
|
||||||
CommandUnfollow: commandUnfollowSummary,
|
CommandUnfollow: commandUnfollowSummary,
|
||||||
|
CommandUnmute: commandUnmuteSummary,
|
||||||
CommandVersion: commandVersionSummary,
|
CommandVersion: commandVersionSummary,
|
||||||
CommandWhoami: commandWhoamiSummary,
|
CommandWhoami: commandWhoamiSummary,
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ const (
|
||||||
flagListTitle = "list-title"
|
flagListTitle = "list-title"
|
||||||
flagListRepliesPolicy = "list-replies-policy"
|
flagListRepliesPolicy = "list-replies-policy"
|
||||||
flagMyAccount = "my-account"
|
flagMyAccount = "my-account"
|
||||||
|
flagMuteDuration = "mute-duration"
|
||||||
|
flagMuteNotifications = "mute-notifications"
|
||||||
flagNotify = "notify"
|
flagNotify = "notify"
|
||||||
flagPollAllowsMultipleChoices = "poll-allows-multiple-choices"
|
flagPollAllowsMultipleChoices = "poll-allows-multiple-choices"
|
||||||
flagPollExpiresIn = "poll-expires-in"
|
flagPollExpiresIn = "poll-expires-in"
|
||||||
|
|
107
internal/executor/mute_or_unmute.go
Normal file
107
internal/executor/mute_or_unmute.go
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package executor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MuteOrUnmuteExecutor struct {
|
||||||
|
*flag.FlagSet
|
||||||
|
|
||||||
|
printer *printer.Printer
|
||||||
|
accountName string
|
||||||
|
configDir string
|
||||||
|
command string
|
||||||
|
resourceType string
|
||||||
|
muteDuration TimeDurationFlagValue
|
||||||
|
muteNotifications bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMuteOrUnmuteExecutor(printer *printer.Printer, configDir, name, summary string) *MuteOrUnmuteExecutor {
|
||||||
|
exe := MuteOrUnmuteExecutor{
|
||||||
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
|
command: name,
|
||||||
|
}
|
||||||
|
|
||||||
|
exe.StringVar(&exe.accountName, flagAccountName, "", "Specify the account name in full (username@domain)")
|
||||||
|
exe.StringVar(&exe.resourceType, flagType, "", "Specify the type of resource to mute or unmute")
|
||||||
|
exe.BoolVar(&exe.muteNotifications, flagMuteNotifications, false, "Mute notifications as well as posts")
|
||||||
|
exe.Var(&exe.muteDuration, flagMuteDuration, "Specify how long the mute should last for. To mute indefinitely, set this to 0s")
|
||||||
|
|
||||||
|
exe.Usage = commandUsageFunc(name, summary, exe.FlagSet)
|
||||||
|
|
||||||
|
return &exe
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MuteOrUnmuteExecutor) Execute() error {
|
||||||
|
funcMap := map[string]func(*client.Client) error{
|
||||||
|
resourceAccount: m.muteOrUnmuteAccount,
|
||||||
|
}
|
||||||
|
|
||||||
|
doFunc, ok := funcMap[m.resourceType]
|
||||||
|
if !ok {
|
||||||
|
return UnsupportedTypeError{resourceType: m.resourceType}
|
||||||
|
}
|
||||||
|
|
||||||
|
gtsClient, err := client.NewClientFromConfig(m.configDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return doFunc(gtsClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MuteOrUnmuteExecutor) muteOrUnmuteAccount(gtsClient *client.Client) error {
|
||||||
|
if m.accountName == "" {
|
||||||
|
return FlagNotSetError{flagText: flagAccountName}
|
||||||
|
}
|
||||||
|
|
||||||
|
accountID, err := getAccountID(gtsClient, false, m.accountName, m.configDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.command {
|
||||||
|
case CommandMute:
|
||||||
|
return m.muteAccount(gtsClient, accountID)
|
||||||
|
case CommandUnmute:
|
||||||
|
return m.unmuteAccount(gtsClient, accountID)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MuteOrUnmuteExecutor) muteAccount(gtsClient *client.Client, accountID string) error {
|
||||||
|
form := client.MuteAccountForm{
|
||||||
|
Notifications: m.muteNotifications,
|
||||||
|
Duration: int(m.muteDuration.Duration.Seconds()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gtsClient.MuteAccount(accountID, form); err != nil {
|
||||||
|
return fmt.Errorf("unable to mute the account: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.printer.PrintSuccess("Successfully muted the account.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MuteOrUnmuteExecutor) unmuteAccount(gtsClient *client.Client, accountID string) error {
|
||||||
|
if err := gtsClient.UnmuteAccount(accountID); err != nil {
|
||||||
|
return fmt.Errorf("unable to unmute the account: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.printer.PrintSuccess("Successfully unmuted the account.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ const (
|
||||||
resourceLike = "like"
|
resourceLike = "like"
|
||||||
resourceLiked = "liked"
|
resourceLiked = "liked"
|
||||||
resourceList = "list"
|
resourceList = "list"
|
||||||
|
resourceMutedAccounts = "muted-accounts"
|
||||||
resourceNote = "note"
|
resourceNote = "note"
|
||||||
resourcePoll = "poll"
|
resourcePoll = "poll"
|
||||||
resourceStatus = "status"
|
resourceStatus = "status"
|
||||||
|
|
|
@ -78,6 +78,7 @@ func (s *ShowExecutor) Execute() error {
|
||||||
resourceStarred: s.showLiked,
|
resourceStarred: s.showLiked,
|
||||||
resourceFollowRequest: s.showFollowRequests,
|
resourceFollowRequest: s.showFollowRequests,
|
||||||
resourcePoll: s.showPoll,
|
resourcePoll: s.showPoll,
|
||||||
|
resourceMutedAccounts: s.showMutedAccounts,
|
||||||
}
|
}
|
||||||
|
|
||||||
doFunc, ok := funcMap[s.resourceType]
|
doFunc, ok := funcMap[s.resourceType]
|
||||||
|
@ -386,3 +387,18 @@ func (s *ShowExecutor) showPoll(gtsClient *client.Client) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error {
|
||||||
|
muted, err := gtsClient.GetMutedAccounts(s.limit)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to retrieve the list of muted accounts: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(muted.Accounts) > 0 {
|
||||||
|
s.printer.PrintAccountList(muted)
|
||||||
|
} else {
|
||||||
|
s.printer.PrintInfo("You have not muted any accounts.\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ const (
|
||||||
AccountListFollowing
|
AccountListFollowing
|
||||||
AccountListBlockedAccount
|
AccountListBlockedAccount
|
||||||
AccountListFollowRequests
|
AccountListFollowRequests
|
||||||
|
AccountListMuted
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountList struct {
|
type AccountList struct {
|
||||||
|
|
|
@ -117,6 +117,8 @@ func (p Printer) PrintAccountList(list model.AccountList) {
|
||||||
builder.WriteString(p.headerFormat("Blocked accounts:"))
|
builder.WriteString(p.headerFormat("Blocked accounts:"))
|
||||||
case model.AccountListFollowRequests:
|
case model.AccountListFollowRequests:
|
||||||
builder.WriteString(p.headerFormat("Accounts that have requested to follow you:"))
|
builder.WriteString(p.headerFormat("Accounts that have requested to follow you:"))
|
||||||
|
case model.AccountListMuted:
|
||||||
|
builder.WriteString(p.headerFormat("Muted accounts:"))
|
||||||
default:
|
default:
|
||||||
builder.WriteString(p.headerFormat("Accounts:"))
|
builder.WriteString(p.headerFormat("Accounts:"))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue