proca 1.7.3 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -209,24 +209,24 @@ EXAMPLES
209
209
  ```
210
210
  USAGE
211
211
  $ proca action list [TITLE] -o <organisation name> [--json | --human | --csv] [--env
212
- <value>] [-c <campaign title>] [--limit <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm
212
+ <value>] [-c <campaign name>] [--limit <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm
213
213
  | --simplify] [--comment | ]
214
214
 
215
215
  ARGUMENTS
216
216
  TITLE name of the campaign, % for wildchar
217
217
 
218
218
  FLAGS
219
- -c, --campaign=<campaign title> name of the campaign, % for wildchar
220
- -o, --org=<organisation name> (required) campaigns of the organisation (coordinator or partner)
221
- --after=2025-04-09 only actions after a date
222
- --[no-]comment display the comment
223
- --doi only export the double optin actions
224
- --env=<value> [default: default] allow to switch between configurations (server or users)
225
- --limit=<value> max number of actions
226
- --optin only export the optin actions
227
- --testing also export the test actions
228
- --today only actions today
229
- --[no-]utm display the utm tracking parameters
219
+ -c, --campaign=<campaign name> name of the campaign, % for wildchar
220
+ -o, --org=<organisation name> (required) campaigns of the organisation (coordinator or partner)
221
+ --after=2025-04-09 only actions after a date
222
+ --[no-]comment display the comment
223
+ --doi only export the double optin actions
224
+ --env=<value> [default: default] allow to switch between configurations (server or users)
225
+ --limit=<value> max number of actions
226
+ --optin only export the optin actions
227
+ --testing also export the test actions
228
+ --today only actions today
229
+ --[no-]utm display the utm tracking parameters
230
230
 
231
231
  OUTPUT FLAGS
232
232
  --csv Format output as csv
@@ -262,18 +262,28 @@ EXAMPLES
262
262
 
263
263
  ## `proca action requeue`
264
264
 
265
- requeue an action
265
+ requeue actions
266
266
 
267
267
  ```
268
268
  USAGE
269
- $ proca action requeue --id <value> -o <org name> -q <user email> [--json | --human |
270
- --csv] [--env <value>] [--simplify]
269
+ $ proca action requeue -o <org name> -q
270
+ CUSTOM_ACTION_CONFIRM|CUSTOM_ACTION_DELIVER|CUSTOM_SUPPORTER_CONFIRM|EMAIL_SUPPORTER|SQS|WEBHOOK [--json | --human |
271
+ --csv] [--env <value>] [--simplify] [-c <campaign name>] [--limit <value>] [--today | --after 2025-04-09] [--optin]
272
+ [--testing] [--doi]
271
273
 
272
274
  FLAGS
273
- -o, --org=<org name> (required) name of the org
274
- -q, --queue=<user email> (required) queue to redeliver to
275
- --env=<value> [default: default] allow to switch between configurations (server or users)
276
- --id=<value> (required) action id
275
+ -c, --campaign=<campaign name> name of the campaign, % for wildchar
276
+ -o, --org=<org name> (required) name of the org
277
+ -q, --queue=<option> (required) [default: CUSTOM_ACTION_DELIVER] queue to redeliver to
278
+ <options: CUSTOM_ACTION_CONFIRM|CUSTOM_ACTION_DELIVER|CUSTOM_SUPPORTER_CONFIRM|EMAIL_S
279
+ UPPORTER|SQS|WEBHOOK>
280
+ --after=2025-04-09 only actions after a date
281
+ --doi only export the double optin actions
282
+ --env=<value> [default: default] allow to switch between configurations (server or users)
283
+ --limit=<value> [default: 1000] how many actions per page
284
+ --optin only export the optin actions
285
+ --testing also export the test actions
286
+ --today only actions today
277
287
 
278
288
  OUTPUT FLAGS
279
289
  --csv Format output as csv
@@ -282,7 +292,7 @@ OUTPUT FLAGS
282
292
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
283
293
 
284
294
  DESCRIPTION
285
- requeue an action
295
+ requeue actions
286
296
 
287
297
  EXAMPLES
288
298
  $ proca action requeue
@@ -435,20 +445,22 @@ set the mail to target (mtt) params
435
445
 
436
446
  ```
437
447
  USAGE
438
- $ proca campaign mtt [ID_NAME_DXID] --from <value> --to <value> [--json | --human |
439
- --csv] [--env <value>] [--simplify] [-i <value> | -n <the_short_name> | -x <value>] [--template <value>] [--period
440
- <value>] [--email <value>]
448
+ $ proca campaign mtt [ID_NAME_DXID] [--json | --human | --csv] [--env <value>]
449
+ [--simplify] [-i <value> | -n <the_short_name> | -x <value>] [--from <value>] [--to <value>] [--template <value>]
450
+ [--period <value>] [--email <value>] [--cc <value>] [--sender]
441
451
 
442
452
  FLAGS
443
453
  -i, --id=<value>
444
454
  -n, --name=<the_short_name> name
445
455
  -x, --dxid=<value> dxid
456
+ --cc=<value> comma-separated list of CC email addresses
446
457
  --email=<value> test email address
447
458
  --env=<value> [default: default] allow to switch between configurations (server or users)
448
- --from=<value> (required) start date (yyyy-mm-dd)
459
+ --from=<value> start date (yyyy-mm-dd)
449
460
  --period=<value> [default: 09:09-18:18] period of the day (HH:HH-HH:HH)
461
+ --sender add sender to CC
450
462
  --template=<value> mtt template to use
451
- --to=<value> (required) end date (yyyy-mm-dd)
463
+ --to=<value> end date (yyyy-mm-dd)
452
464
 
453
465
  OUTPUT FLAGS
454
466
  --csv Format output as csv
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proca",
3
3
  "description": "Access the proca api",
4
- "version": "1.7.3",
4
+ "version": "1.7.5",
5
5
  "author": "Xavier",
6
6
  "bin": {
7
7
  "proca": "proca-cli"
@@ -30,7 +30,7 @@ export default class List extends Command {
30
30
  campaign: Flags.string({
31
31
  char: "c",
32
32
  description: "name of the campaign, % for wildchar",
33
- helpValue: "<campaign title>",
33
+ helpValue: "<campaign name>",
34
34
  }),
35
35
  limit: Flags.string({
36
36
  description: "max number of actions",
@@ -48,6 +48,8 @@ options: [
48
48
  const { args, flags } = await this.parse();
49
49
  let data = [];
50
50
  const ids = [];
51
+ this.fatal("not implemented yet");
52
+ process.exit(1);
51
53
  data = await this.mutate(flags.org, ids, flags.queue);
52
54
  return this.output(data);
53
55
  }
@@ -1,50 +1,147 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { error, stdout, ux } from "@oclif/core/ux";
3
3
  import Command from "#src/procaCommand.mjs";
4
- import { gql, mutation } from "#src/urql.mjs";
4
+ import { gql, mutation, query } from "#src/urql.mjs";
5
5
 
6
6
  export default class ActionRequeue extends Command {
7
- static description = "requeue an action";
7
+ static description = "requeue actions";
8
8
 
9
9
  static examples = ["<%= config.bin %> <%= command.id %>"];
10
10
 
11
11
  static flags = {
12
12
  ...super.globalFlags,
13
- id: Flags.string({
14
- description: "action id",
15
- parse: (input) => Number.parseInt(input, 10),
16
- required: true,
17
- }),
18
13
  org: Flags.string({
19
14
  char: "o",
20
15
  required: true,
21
16
  description: "name of the org",
22
17
  helpValue: "<org name>",
23
18
  }),
19
+ campaign: Flags.string({
20
+ char: "c",
21
+ description: "name of the campaign, % for wildchar",
22
+ helpValue: "<campaign name>",
23
+ }),
24
24
  queue: Flags.string({
25
25
  char: "q",
26
26
  required: true,
27
27
  description: "queue to redeliver to",
28
- helpValue: "<user email>",
28
+ default: "CUSTOM_ACTION_DELIVER",
29
+ options: [
30
+ "CUSTOM_ACTION_CONFIRM",
31
+ "CUSTOM_ACTION_DELIVER",
32
+ "CUSTOM_SUPPORTER_CONFIRM",
33
+ "EMAIL_SUPPORTER",
34
+ "SQS",
35
+ "WEBHOOK",
36
+ ],
37
+ }),
38
+ limit: Flags.string({
39
+ description: "how many actions per page",
40
+ default: 1000,
41
+ parse: (input) => Number.parseInt(input, 10),
42
+ }),
43
+ after: Flags.string({
44
+ description: "only actions after a date",
45
+ helpValue: "2025-04-09",
46
+ parse: (input) => new Date(input).toISOString(),
47
+ }),
48
+ today: Flags.boolean({
49
+ description: "only actions today",
50
+ exclusive: ["after"],
51
+ parse: (input) => `${new Date().toISOString().split("T")[0]}T00:00:00Z`,
52
+ }),
53
+ optin: Flags.boolean({
54
+ description: "only export the optin actions",
55
+ default: false,
56
+ }),
57
+ testing: Flags.boolean({
58
+ description: "also export the test actions",
59
+ default: false,
29
60
  }),
61
+ doi: Flags.boolean({
62
+ description: "only export the double optin actions",
63
+ default: false,
64
+ }),
65
+ };
66
+
67
+ process = async (flags) => {
68
+ let page = 0;
69
+ let actions = 0;
70
+ let requeued = 0;
71
+ let error = 0;
72
+ while (true) {
73
+ const ids = await this.fetch(flags);
74
+ if (ids.length === 0) break;
75
+ const result = await this.requeue(flags.org, flags.queue, ids);
76
+ requeued += result.count;
77
+ error += result.failed;
78
+ flags.start = ids[ids.length - 1] + 1;
79
+ process.stdout.write(`\rrequeued ${requeued}, id> ${flags.start}`);
80
+ page += 1;
81
+ actions += ids.length;
82
+ }
83
+ process.stdout.write("\r\x1b[K");
84
+ return { pages: page, actions, requeued, error };
30
85
  };
31
86
 
32
- mutate = async (org) => {
87
+ fetch = async (flags) => {
33
88
  const Document = gql`
34
- mutation ($user: String!, $role: String!, $org: String!, message: String) {
35
- inviteOrgUser(orgName: $org, message: $message, input :{ email: $user, role: $role}) {
36
- objectId
37
- code
38
- }
39
- }
89
+ query (
90
+ $after: DateTime
91
+ $campaignId: Int
92
+ $campaignName: String
93
+ $includeTesting: Boolean
94
+ $limit: Int
95
+ $onlyDoubleOptIn: Boolean
96
+ $onlyOptIn: Boolean
97
+ $orgName: String!
98
+ $start: Int
99
+ ) {
100
+ actions (
101
+ after: $after
102
+ campaignId: $campaignId
103
+ campaignName: $campaignName
104
+ includeTesting: $includeTesting
105
+ limit: $limit
106
+ onlyDoubleOptIn: $onlyDoubleOptIn
107
+ onlyOptIn: $onlyOptIn
108
+ orgName: $orgName
109
+ start: $start
110
+ ) {
111
+ actionId
112
+ }
113
+ }
40
114
  `;
115
+ const result = await query(Document, {
116
+ after: flags.after,
117
+ campaignName: flags.campaign,
118
+ includeTesting: flags.testing,
119
+ limit: flags.limit,
120
+ onlyDoubleOptIn: flags.doi,
121
+ onlyOptIn: flags.optin,
122
+ orgName: flags.org,
123
+ start: flags.start,
124
+ });
125
+ const ids = [];
126
+ result.actions.forEach((d) => ids.push(d.actionId));
127
+ return ids;
128
+ };
129
+
130
+ requeue = async (org, queue, ids) => {
131
+ const Document = gql`
132
+ mutation ($ids: [Int!], $org: String!, $queue: Queue!) {
133
+ requeueActions(ids: $ids, orgName: $org, queue: $queue) {
134
+ count
135
+ failed
136
+ }
137
+ }`;
41
138
  const result = await mutation(Document, {
42
139
  org,
43
- role,
44
- user,
140
+ queue,
141
+ ids,
45
142
  });
46
143
  //return result.users.map (d => {d.config = JSON.parse(d.config); return d});
47
- return result.inviteOrg;
144
+ return result.requeueActions;
48
145
  };
49
146
 
50
147
  table = (r) => {
@@ -52,9 +149,8 @@ mutation ($user: String!, $role: String!, $org: String!, message: String) {
52
149
  };
53
150
 
54
151
  async run() {
55
- throw new Error("NOT IMPLEMENTED");
56
152
  const { args, flags } = await this.parse();
57
- const data = await this.mutate(flag);
153
+ const data = await this.process(flags);
58
154
  this.output(data);
59
155
  }
60
156
  }
@@ -83,6 +83,8 @@ export default class CampaignGet extends Command {
83
83
  result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
84
84
  result["test email"] = d.mtt.testEmail;
85
85
  result["mtt template"] = d.mtt.template;
86
+ result["cc contacts"] = d.mtt.ccContacts?.join(", ");
87
+ result["cc sender"] = d.mtt.ccSender;
86
88
  }
87
89
  if (this.flags.stats) {
88
90
  result["#Supporters"] = d.stats.supporterCount;
@@ -17,11 +17,11 @@ export default class CampaignMtt extends Command {
17
17
  ...this.flagify({ multiid: true }),
18
18
  from: Flags.string({
19
19
  description: "start date (yyyy-mm-dd)",
20
- required: true,
20
+ required: false,
21
21
  }),
22
22
  to: Flags.string({
23
23
  description: "end date (yyyy-mm-dd)",
24
- required: true,
24
+ required: false,
25
25
  }),
26
26
  template: Flags.string({
27
27
  description: "mtt template to use",
@@ -33,6 +33,13 @@ export default class CampaignMtt extends Command {
33
33
  email: Flags.string({
34
34
  description: "test email address",
35
35
  }),
36
+ cc: Flags.string({
37
+ description: "comma-separated list of CC email addresses",
38
+ }),
39
+ sender: Flags.boolean({
40
+ description: "add sender to CC",
41
+ default: false,
42
+ }),
36
43
  };
37
44
 
38
45
  updateMtt = async (flags) => {
@@ -45,53 +52,67 @@ $mtt: CampaignMttInput!
45
52
  updateCampaign (id:$id, name: $name, input: { mtt: $mtt }) {
46
53
  id, name
47
54
  ...Mtt
48
- }
49
- ${FragmentMtt}
50
- }
55
+ }
56
+ ${FragmentMtt}
57
+ }
51
58
  `;
59
+
52
60
  const testEmail = flags.email || `campaign+${flags.name}@proca.app`;
53
61
 
54
62
  const [startPeriod, endPeriod] = flags.period.split("-");
55
63
  const [startHour, startMinute] = startPeriod.split(":");
56
64
  const [endHour, endMinute] = endPeriod.split(":");
57
65
 
58
- const startAt = new Date(flags.from);
59
- startAt.setHours(startHour, startMinute, 0, 0);
66
+ const mtt = {
67
+ testEmail,
68
+ };
69
+
70
+ if (flags.template) mtt.messageTemplate = flags.template;
71
+ if (flags.email) mtt.testEmail = testEmail;
72
+ if (flags.cc) mtt.ccContacts = flags.cc.split(",").map((e) => e.trim());
73
+ if (flags.sender) mtt.ccSender = flags.sender;
60
74
 
61
- const endAt = new Date(flags.to);
62
- endAt.setHours(endHour, endMinute, 0, 0);
75
+ if (flags.from) {
76
+ const startAt = new Date(flags.from);
77
+ startAt.setHours(startHour, startMinute, 0, 0);
78
+ mtt.startAt = startAt.toISOString();
79
+ }
80
+
81
+ if (flags.to) {
82
+ const endAt = new Date(flags.to);
83
+ endAt.setHours(endHour, endMinute, 0, 0);
84
+ mtt.endAt = endAt.toISOString();
85
+ }
63
86
 
64
87
  const result = await mutation(Query, {
65
- // org: props.org,
66
88
  id: flags.id,
67
89
  name: flags.name,
68
- mtt: {
69
- startAt: startAt.toISOString(),
70
- endAt: endAt.toISOString(),
71
- messageTemplate: flags.template,
72
- testEmail: testEmail,
73
- },
90
+ mtt,
74
91
  });
75
-
76
92
  return result.updateCampaign;
77
93
  };
78
94
 
79
95
  simplify = (d) => {
80
- const result = {
81
- id: d.id,
82
- Name: d.name,
83
- };
96
+ const result = { id: d.id, Name: d.name };
84
97
  const hhmm = (date) =>
85
98
  new Date(date).toLocaleTimeString(undefined, {
86
99
  hour: "2-digit",
87
100
  minute: "2-digit",
88
101
  hour12: false,
89
102
  });
90
- result.from = d.mtt.startAt.substring(0, 10);
91
- result.to = d.mtt.endAt.substring(0, 10);
92
- result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
103
+ if (d.mtt.startAt && d.mtt.endAt) {
104
+ result.from = d.mtt.startAt.substring(0, 10);
105
+ result.to = d.mtt.endAt.substring(0, 10);
106
+ result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
107
+ }
93
108
  result["test email"] = d.mtt.testEmail;
94
- result["mtt template"] = d.mtt.template;
109
+ result["mtt template"] = d.mtt.messageTemplate;
110
+ if (d.mtt.ccContacts?.length)
111
+ result["cc contacts"] = d.mtt.ccContacts.join(", ");
112
+ if (typeof d.mtt.ccSender !== "undefined") {
113
+ result["cc sender"] = d.mtt.ccSender ? "yes" : "no";
114
+ }
115
+
95
116
  return result;
96
117
  };
97
118
 
@@ -101,7 +122,6 @@ $mtt: CampaignMttInput!
101
122
 
102
123
  async run() {
103
124
  const { args, flags } = await this.parse();
104
-
105
125
  const result = await this.updateMtt(flags);
106
126
  this.output(result);
107
127
  }
@@ -60,6 +60,9 @@ export default class WidgetAdd extends Command {
60
60
  const campapi = new CampaignGet();
61
61
  campaign = await campapi.fetch({ name: flag.campaign });
62
62
  flag.org = campaign.org.name;
63
+ if (!flag.name) {
64
+ flag.name = `${campaign.name}/${flag.lang}`;
65
+ }
63
66
  } catch (e) {
64
67
  console.log("error", e);
65
68
  throw e;
@@ -70,6 +73,9 @@ export default class WidgetAdd extends Command {
70
73
  throw new Error(`campaign not found: ${flag.campaign}`);
71
74
  }
72
75
 
76
+ if (!flag.name) {
77
+ flag.name = `${flag.campaign}/${flag.org}/${flag.lang}`;
78
+ }
73
79
  try {
74
80
  const r = await mutation(addWidgetDocument, flag);
75
81
  return { id: r.addActionPage.id };
@@ -9,6 +9,8 @@ export const FragmentMtt = gql`
9
9
  endAt
10
10
  messageTemplate
11
11
  testEmail
12
+ ccContacts
13
+ ccSender
12
14
  }
13
15
  }
14
16
  `;