/ internal / executor / add.go
add.go
  1  package executor
  2  
  3  import (
  4  	"fmt"
  5  	"net/rpc"
  6  
  7  	"codeflow.dananglin.me.uk/apollo/enbas/internal/gtsclient"
  8  	"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
  9  	"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
 10  	"codeflow.dananglin.me.uk/apollo/enbas/internal/server"
 11  )
 12  
 13  func (a *AddExecutor) Execute() error {
 14  	if a.toResourceType == "" {
 15  		return FlagNotSetError{flagText: flagTo}
 16  	}
 17  
 18  	funcMap := map[string]func(*rpc.Client) error{
 19  		resourceList:      a.addToList,
 20  		resourceAccount:   a.addToAccount,
 21  		resourceBookmarks: a.addToBookmarks,
 22  		resourceStatus:    a.addToStatus,
 23  	}
 24  
 25  	doFunc, ok := funcMap[a.toResourceType]
 26  	if !ok {
 27  		return UnsupportedTypeError{resourceType: a.toResourceType}
 28  	}
 29  
 30  	client, err := server.Connect(a.config.Server, a.configDir)
 31  	if err != nil {
 32  		return fmt.Errorf("error creating the client for the daemon process: %w", err)
 33  	}
 34  	defer client.Close()
 35  
 36  	return doFunc(client)
 37  }
 38  
 39  func (a *AddExecutor) addToList(client *rpc.Client) error {
 40  	if a.listID == "" {
 41  		return MissingIDError{
 42  			resource: resourceList,
 43  			action:   "add to",
 44  		}
 45  	}
 46  
 47  	funcMap := map[string]func(*rpc.Client) error{
 48  		resourceAccount: a.addAccountsToList,
 49  	}
 50  
 51  	doFunc, ok := funcMap[a.resourceType]
 52  	if !ok {
 53  		return UnsupportedAddOperationError{
 54  			resourceType:      a.resourceType,
 55  			addToResourceType: a.toResourceType,
 56  		}
 57  	}
 58  
 59  	return doFunc(client)
 60  }
 61  
 62  func (a *AddExecutor) addAccountsToList(client *rpc.Client) error {
 63  	if a.accountNames.Empty() {
 64  		return NoAccountSpecifiedError{}
 65  	}
 66  
 67  	accounts, err := getOtherAccounts(client, a.accountNames)
 68  	if err != nil {
 69  		return fmt.Errorf("unable to get the accounts: %w", err)
 70  	}
 71  
 72  	accountIDs := make([]string, len(accounts))
 73  
 74  	for ind := range accounts {
 75  		var relationship model.AccountRelationship
 76  		if err := client.Call("GTSClient.GetAccountRelationship", accounts[ind].ID, &relationship); err != nil {
 77  			return fmt.Errorf("unable to get your relationship to %s: %w", accounts[ind].Acct, err)
 78  		}
 79  
 80  		if !relationship.Following {
 81  			return NotFollowingError{account: accounts[ind].Acct}
 82  		}
 83  
 84  		accountIDs[ind] = accounts[ind].ID
 85  	}
 86  
 87  	if err := client.Call(
 88  		"GTSClient.AddAccountsToList",
 89  		gtsclient.AddAccountsToListArgs{
 90  			ListID:     a.listID,
 91  			AccountIDs: accountIDs,
 92  		},
 93  		nil,
 94  	); err != nil {
 95  		return fmt.Errorf("unable to add the accounts to the list: %w", err)
 96  	}
 97  
 98  	printer.PrintSuccess(a.printSettings, "Successfully added the account(s) to the list.")
 99  
100  	return nil
101  }
102  
103  func (a *AddExecutor) addToAccount(client *rpc.Client) error {
104  	funcMap := map[string]func(*rpc.Client) error{
105  		resourceNote: a.addNoteToAccount,
106  	}
107  
108  	doFunc, ok := funcMap[a.resourceType]
109  	if !ok {
110  		return UnsupportedAddOperationError{
111  			resourceType:      a.resourceType,
112  			addToResourceType: a.toResourceType,
113  		}
114  	}
115  
116  	return doFunc(client)
117  }
118  
119  func (a *AddExecutor) addNoteToAccount(client *rpc.Client) error {
120  	accountID, err := getAccountID(client, false, a.accountNames)
121  	if err != nil {
122  		return fmt.Errorf("received an error while getting the account ID: %w", err)
123  	}
124  
125  	if a.content == "" {
126  		return Error{"please add content to the note you want to add"}
127  	}
128  
129  	if err := client.Call(
130  		"GTSClient.SetPrivateNote",
131  		gtsclient.SetPrivateNoteArgs{
132  			AccountID: accountID,
133  			Note:      a.content,
134  		},
135  		nil,
136  	); err != nil {
137  		return fmt.Errorf("unable to add the private note to the account: %w", err)
138  	}
139  
140  	printer.PrintSuccess(a.printSettings, "Successfully added the private note to the account.")
141  
142  	return nil
143  }
144  
145  func (a *AddExecutor) addToBookmarks(client *rpc.Client) error {
146  	funcMap := map[string]func(*rpc.Client) error{
147  		resourceStatus: a.addStatusToBookmarks,
148  	}
149  
150  	doFunc, ok := funcMap[a.resourceType]
151  	if !ok {
152  		return UnsupportedAddOperationError{
153  			resourceType:      a.resourceType,
154  			addToResourceType: a.toResourceType,
155  		}
156  	}
157  
158  	return doFunc(client)
159  }
160  
161  func (a *AddExecutor) addStatusToBookmarks(client *rpc.Client) error {
162  	if a.statusID == "" {
163  		return MissingIDError{
164  			resource: resourceStatus,
165  			action:   "add to your bookmarks",
166  		}
167  	}
168  
169  	if err := client.Call("GTSClient.AddStatusToBookmarks", a.statusID, nil); err != nil {
170  		return fmt.Errorf("unable to add the status to your bookmarks: %w", err)
171  	}
172  
173  	printer.PrintSuccess(a.printSettings, "Successfully added the status to your bookmarks.")
174  
175  	return nil
176  }
177  
178  func (a *AddExecutor) addToStatus(client *rpc.Client) error {
179  	if a.statusID == "" {
180  		return MissingIDError{
181  			resource: resourceStatus,
182  			action:   "add to",
183  		}
184  	}
185  
186  	funcMap := map[string]func(*rpc.Client) error{
187  		resourceStar:  a.addStarToStatus,
188  		resourceLike:  a.addStarToStatus,
189  		resourceBoost: a.addBoostToStatus,
190  		resourceVote:  a.addVoteToStatus,
191  	}
192  
193  	doFunc, ok := funcMap[a.resourceType]
194  	if !ok {
195  		return UnsupportedAddOperationError{
196  			resourceType:      a.resourceType,
197  			addToResourceType: a.toResourceType,
198  		}
199  	}
200  
201  	return doFunc(client)
202  }
203  
204  func (a *AddExecutor) addStarToStatus(client *rpc.Client) error {
205  	if err := client.Call("GTSClient.LikeStatus", a.statusID, nil); err != nil {
206  		return fmt.Errorf("error adding the %s to the status: %w", a.resourceType, err)
207  	}
208  
209  	printer.PrintSuccess(a.printSettings, "Successfully added a "+a.resourceType+" to the status.")
210  
211  	return nil
212  }
213  
214  func (a *AddExecutor) addBoostToStatus(client *rpc.Client) error {
215  	if err := client.Call("GTSClient.ReblogStatus", a.statusID, nil); err != nil {
216  		return fmt.Errorf("unable to add the boost to the status: %w", err)
217  	}
218  
219  	printer.PrintSuccess(a.printSettings, "Successfully added the boost to the status.")
220  
221  	return nil
222  }
223  
224  func (a *AddExecutor) addVoteToStatus(client *rpc.Client) error {
225  	if a.votes.Empty() {
226  		return Error{"please add your vote(s) to the poll"}
227  	}
228  
229  	var status model.Status
230  	if err := client.Call("GTSClient.GetStatus", a.statusID, &status); err != nil {
231  		return fmt.Errorf("unable to get the status: %w", err)
232  	}
233  
234  	if status.Poll == nil {
235  		return Error{"this status does not have a poll"}
236  	}
237  
238  	if status.Poll.Expired {
239  		return Error{"this poll is closed"}
240  	}
241  
242  	if !status.Poll.Multiple && !a.votes.ExpectedLength(1) {
243  		return Error{"this poll does not allow multiple choices"}
244  	}
245  
246  	myAccountID, err := getAccountID(client, true, nil)
247  	if err != nil {
248  		return fmt.Errorf("unable to get your account ID: %w", err)
249  	}
250  
251  	if status.Account.ID == myAccountID {
252  		return Error{"you cannot vote in your own poll"}
253  	}
254  
255  	pollID := status.Poll.ID
256  
257  	if err := client.Call(
258  		"GTSClient.VoteInPoll",
259  		gtsclient.VoteInPollArgs{
260  			PollID:  pollID,
261  			Choices: a.votes,
262  		},
263  		nil,
264  	); err != nil {
265  		return fmt.Errorf("unable to add your vote(s) to the poll: %w", err)
266  	}
267  
268  	printer.PrintSuccess(a.printSettings, "Successfully added your vote(s) to the poll.")
269  
270  	return nil
271  }