Skip to content

Commit 79274c3

Browse files
authored
Fix commands (#30)
* Fix max vote * Set default for connect * Fix topic toggle work * Fix work motion toggle for other meetings
1 parent 8c70c19 commit 79274c3

File tree

3 files changed

+146
-33
lines changed

3 files changed

+146
-33
lines changed

connect/connect.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import (
1919

2020
// Run runs the command.
2121
func (o Options) Run(ctx context.Context, cfg config.Config) error {
22+
if o.Body == "" {
23+
o.Body = `[{"collection":"organization","ids":[1],"fields":{"committee_ids":{"type":"relation-list","collection":"committee","fields":{"name":null}}}}]`
24+
}
25+
2226
c, err := client.New(cfg)
2327
if err != nil {
2428
return fmt.Errorf("creating client: %w", err)

internal/client/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (c *Client) Login(ctx context.Context) error {
8080
// config.
8181
func (c *Client) LoginWithCredentials(ctx context.Context, username, password string) error {
8282
url := c.cfg.Addr() + "/system/auth/login"
83-
payload := fmt.Sprintf(`{"username": "%s", "password": "%s"}`, c.cfg.Username, c.cfg.Password)
83+
payload := fmt.Sprintf(`{"username": "%s", "password": "%s"}`, username, password)
8484

8585
req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(payload))
8686
if err != nil {

work/work.go

Lines changed: 141 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,27 @@ import (
1515

1616
// Run runs the command.
1717
func (o Options) Run(ctx context.Context, cfg config.Config) error {
18+
workFunc := topicDone
19+
switch o.Strategy {
20+
case "topic-done":
21+
workFunc = topicDone
22+
case "motion-state":
23+
workFunc = motionState
24+
}
25+
1826
eg, ctx := errgroup.WithContext(ctx)
1927
for i := 0; i < o.Amount; i++ {
2028
eg.Go(func() error {
21-
c, err := client.New(cfg)
29+
cli, err := client.New(cfg)
2230
if err != nil {
2331
return fmt.Errorf("creating client: %w", err)
2432
}
2533

26-
if err := c.Login(ctx); err != nil {
34+
if err := cli.Login(ctx); err != nil {
2735
return fmt.Errorf("login client: %w", err)
2836
}
2937

30-
f := topicDone
31-
switch o.Strategy {
32-
case "topic-done":
33-
f = topicDone
34-
case "motion-state":
35-
f = motionState
36-
}
37-
38-
return f(ctx, c, o.MeetingID)
38+
return workFunc(ctx, cli, o.MeetingID)
3939
})
4040
}
4141

@@ -48,14 +48,19 @@ func motionState(ctx context.Context, client *client.Client, meetingID int) (err
4848
return fmt.Errorf("creating motion: %w", err)
4949
}
5050

51+
nextStateID, err := motionNextStateID(ctx, client, motionID)
52+
if err != nil {
53+
return fmt.Errorf("getting id of next state: %w", err)
54+
}
55+
5156
defer func() {
5257
deleteErr := deleteWorkerMotion(context.Background(), client, motionID)
5358
if err == nil && deleteErr != nil {
5459
err = fmt.Errorf("deleting motion: %w", err)
5560
}
5661
}()
5762

58-
if err := toggleWorkerMotion(ctx, client, motionID); err != nil {
63+
if err := toggleWorkerMotion(ctx, client, motionID, nextStateID); err != nil {
5964
return fmt.Errorf("toggle motion: %w", err)
6065
}
6166

@@ -64,7 +69,7 @@ func motionState(ctx context.Context, client *client.Client, meetingID int) (err
6469

6570
func createWorkerMotion(ctx context.Context, client *client.Client, meetingID int) (int, error) {
6671
body := fmt.Sprintf(
67-
`[{"action":"motion.create","data":[{"meeting_id":%d,"title":"worker-motion","text":"<p>dummy</p>","workflow_id":1}]}]`,
72+
`[{"action":"motion.create","data":[{"meeting_id":%d,"title":"worker-motion","text":"<p>dummy</p>"}]}]`,
6873
meetingID,
6974
)
7075

@@ -86,18 +91,77 @@ func createWorkerMotion(ctx context.Context, client *client.Client, meetingID in
8691
return respBody.Results[0][0].MotionID, nil
8792
}
8893

89-
func toggleWorkerMotion(ctx context.Context, client *client.Client, motionID int) error {
94+
func motionNextStateID(ctx context.Context, client *client.Client, motionID int) (int, error) {
95+
reqBody := fmt.Sprintf(
96+
`[{"collection":"motion","ids":[%d],"fields":{"state_id":{"type":"relation","collection":"motion_state","fields":{"next_state_ids":null}}}}]`,
97+
motionID,
98+
)
99+
100+
req, err := http.NewRequestWithContext(
101+
ctx,
102+
"GET",
103+
"/system/autoupdate?single=1",
104+
strings.NewReader(reqBody),
105+
)
106+
if err != nil {
107+
return 0, fmt.Errorf("creating request: %w", err)
108+
}
109+
110+
resp, err := client.Do(req)
111+
if err != nil {
112+
return 0, fmt.Errorf("sending request: %w", err)
113+
}
114+
defer resp.Body.Close()
115+
116+
var body map[string]json.RawMessage
117+
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
118+
return 0, fmt.Errorf("decoding body: %w", err)
119+
}
120+
121+
motionStateIDRaw, ok := body[fmt.Sprintf("motion/%d/state_id", motionID)]
122+
if !ok {
123+
return 0, fmt.Errorf("motion does not exist: %d", motionID)
124+
}
125+
126+
var motionStateID int
127+
if err := json.Unmarshal(motionStateIDRaw, &motionStateID); err != nil {
128+
return 0, fmt.Errorf("decoding motion state id: %w", err)
129+
}
130+
131+
nextStateIDsRaw, ok := body[fmt.Sprintf("motion_state/%d/next_state_ids", motionStateID)]
132+
if !ok {
133+
return 0, fmt.Errorf("motion state does not exist: %d", motionStateID)
134+
}
135+
136+
var nextStateIDs []int
137+
if err := json.Unmarshal(nextStateIDsRaw, &nextStateIDs); err != nil {
138+
return 0, fmt.Errorf("decoding next state ids: %w", err)
139+
}
140+
141+
if len(nextStateIDs) == 0 {
142+
return 0, fmt.Errorf("no next state")
143+
}
144+
145+
return nextStateIDs[0], nil
146+
}
147+
148+
func toggleWorkerMotion(ctx context.Context, client *client.Client, motionID int, nextStateID int) error {
149+
bodyNextState := fmt.Sprintf(
150+
`[{"action":"motion.set_state","data":[{"id":%d,"state_id":%d}]}]`,
151+
motionID,
152+
nextStateID,
153+
)
154+
155+
bodyReset := fmt.Sprintf(
156+
`[{"action":"motion.reset_state","data":[{"id":%d}]}]`,
157+
motionID,
158+
)
159+
90160
toggleState := false
91161
for {
92-
body := fmt.Sprintf(
93-
`[{"action":"motion.set_state","data":[{"id":%d,"state_id":2}]}]`,
94-
motionID,
95-
)
162+
body := bodyNextState
96163
if toggleState {
97-
body = fmt.Sprintf(
98-
`[{"action":"motion.reset_state","data":[{"id":%d}]}]`,
99-
motionID,
100-
)
164+
body = bodyReset
101165
}
102166

103167
var respBody struct {
@@ -146,15 +210,20 @@ func topicDone(ctx context.Context, client *client.Client, meetingID int) (err e
146210
return fmt.Errorf("creating topic: %w", err)
147211
}
148212

213+
aid, err := agendaID(ctx, client, topicID)
214+
if err != nil {
215+
return fmt.Errorf("fetching agenda id for topic %d: %w", topicID, err)
216+
}
217+
149218
defer func() {
150219
deleteErr := deleteWorkerTopic(context.Background(), client, topicID)
151220
if err == nil && deleteErr != nil {
152221
err = fmt.Errorf("deleting topic: %w", err)
153222
}
154223
}()
155224

156-
if err := toggleWorkerTopic(ctx, client, topicID); err != nil {
157-
return fmt.Errorf("toggle topic: %w", err)
225+
if err := toggleWorkerAgendaItem(ctx, client, aid); err != nil {
226+
return fmt.Errorf("toggle agenda item: %w", err)
158227
}
159228

160229
return nil
@@ -184,13 +253,57 @@ func createWorkerTopic(ctx context.Context, client *client.Client, meetingID int
184253
return respBody.Results[0][0].TopicID, nil
185254
}
186255

187-
func toggleWorkerTopic(ctx context.Context, client *client.Client, topicID int) error {
188-
toState := "true"
256+
func agendaID(ctx context.Context, client *client.Client, topicID int) (int, error) {
257+
key := fmt.Sprintf("topic/%d/agenda_item_id", topicID)
258+
259+
req, err := http.NewRequestWithContext(
260+
ctx,
261+
"GET",
262+
fmt.Sprintf("/system/autoupdate?k=%s&single=1", key),
263+
nil,
264+
)
265+
if err != nil {
266+
return 0, fmt.Errorf("creating request: %w", err)
267+
}
268+
269+
resp, err := client.Do(req)
270+
if err != nil {
271+
return 0, fmt.Errorf("sending request: %w", err)
272+
}
273+
defer resp.Body.Close()
274+
275+
var body map[string]json.RawMessage
276+
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
277+
return 0, fmt.Errorf("decoding body: %w", err)
278+
}
279+
280+
val, ok := body[key]
281+
if !ok {
282+
return 0, fmt.Errorf("topic %d does not exist", topicID)
283+
}
284+
285+
var agendaID int
286+
if err := json.Unmarshal(val, &agendaID); err != nil {
287+
return 0, fmt.Errorf("decoding agenda id: %w", err)
288+
}
289+
290+
return agendaID, nil
291+
}
292+
293+
func boolToStr(b bool) string {
294+
if b {
295+
return "true"
296+
}
297+
return "false"
298+
}
299+
300+
func toggleWorkerAgendaItem(ctx context.Context, client *client.Client, topicID int) error {
301+
toState := true
189302
for {
190303
body := fmt.Sprintf(
191304
`[{"action":"agenda_item.update","data":[{"id":%d,"closed":%s}]}]`,
192305
topicID,
193-
toState,
306+
boolToStr(toState),
194307
)
195308

196309
var respBody struct {
@@ -208,11 +321,7 @@ func toggleWorkerTopic(ctx context.Context, client *client.Client, topicID int)
208321
return fmt.Errorf("backend returned no success")
209322
}
210323

211-
if toState == "true" {
212-
toState = "false"
213-
} else {
214-
toState = "true"
215-
}
324+
toState = !toState
216325
}
217326
}
218327

0 commit comments

Comments
 (0)