@moltflow/skills 1.4.0 → 2.0.0

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.
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MoltFlow Outreach - Bulk Send, Scheduled Messages, Custom Groups
4
+ """
5
+ import os
6
+ import json
7
+ import requests
8
+
9
+ API_KEY = os.environ.get("MOLTFLOW_API_KEY")
10
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
11
+
12
+ if not API_KEY:
13
+ print("Error: MOLTFLOW_API_KEY environment variable not set")
14
+ exit(1)
15
+
16
+ headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
17
+
18
+
19
+ # ============================================================================
20
+ # Custom Groups
21
+ # ============================================================================
22
+
23
+ def list_custom_groups(limit: int = 50, offset: int = 0):
24
+ """List all custom contact groups."""
25
+ r = requests.get(
26
+ f"{BASE_URL}/api/v2/custom-groups",
27
+ headers=headers,
28
+ params={"limit": limit, "offset": offset},
29
+ )
30
+ r.raise_for_status()
31
+ return r.json()
32
+
33
+
34
+ def create_custom_group(name: str, members: list = None):
35
+ """Create a new custom group. members = list of {"phone": str, "name": str?} dicts."""
36
+ data = {"name": name}
37
+ if members:
38
+ data["members"] = members
39
+ r = requests.post(f"{BASE_URL}/api/v2/custom-groups", headers=headers, json=data)
40
+ r.raise_for_status()
41
+ return r.json()
42
+
43
+
44
+ def add_members(group_id: str, contacts: list):
45
+ """Add members to a custom group. contacts = list of {"phone": str} dicts."""
46
+ r = requests.post(
47
+ f"{BASE_URL}/api/v2/custom-groups/{group_id}/members/add",
48
+ headers=headers,
49
+ json={"contacts": contacts},
50
+ )
51
+ r.raise_for_status()
52
+ return r.json()
53
+
54
+
55
+ def export_group_csv(group_id: str):
56
+ """Export group members as CSV."""
57
+ r = requests.get(
58
+ f"{BASE_URL}/api/v2/custom-groups/{group_id}/export/csv",
59
+ headers=headers,
60
+ )
61
+ r.raise_for_status()
62
+ return r.text
63
+
64
+
65
+ def export_group_json(group_id: str):
66
+ """Export group members as JSON."""
67
+ r = requests.get(
68
+ f"{BASE_URL}/api/v2/custom-groups/{group_id}/export/json",
69
+ headers=headers,
70
+ )
71
+ r.raise_for_status()
72
+ return r.json()
73
+
74
+
75
+ # ============================================================================
76
+ # Bulk Send
77
+ # ============================================================================
78
+
79
+ def create_bulk_job(session_id: str, custom_group_id: str, message_content: str):
80
+ """Create a bulk send job targeting a custom group."""
81
+ r = requests.post(
82
+ f"{BASE_URL}/api/v2/bulk-send",
83
+ headers=headers,
84
+ json={
85
+ "session_id": session_id,
86
+ "custom_group_id": custom_group_id,
87
+ "message_content": message_content,
88
+ },
89
+ )
90
+ r.raise_for_status()
91
+ return r.json()
92
+
93
+
94
+ def list_bulk_jobs(limit: int = 50):
95
+ """List all bulk send jobs."""
96
+ r = requests.get(
97
+ f"{BASE_URL}/api/v2/bulk-send",
98
+ headers=headers,
99
+ params={"limit": limit},
100
+ )
101
+ r.raise_for_status()
102
+ return r.json()
103
+
104
+
105
+ def get_bulk_job(job_id: str):
106
+ """Get bulk job details and progress."""
107
+ r = requests.get(f"{BASE_URL}/api/v2/bulk-send/{job_id}", headers=headers)
108
+ r.raise_for_status()
109
+ return r.json()
110
+
111
+
112
+ def pause_bulk_job(job_id: str):
113
+ """Pause a running bulk send job."""
114
+ r = requests.post(f"{BASE_URL}/api/v2/bulk-send/{job_id}/pause", headers=headers)
115
+ r.raise_for_status()
116
+ return r.json()
117
+
118
+
119
+ def resume_bulk_job(job_id: str):
120
+ """Resume a paused bulk send job."""
121
+ r = requests.post(f"{BASE_URL}/api/v2/bulk-send/{job_id}/resume", headers=headers)
122
+ r.raise_for_status()
123
+ return r.json()
124
+
125
+
126
+ def cancel_bulk_job(job_id: str):
127
+ """Cancel a bulk send job."""
128
+ r = requests.post(f"{BASE_URL}/api/v2/bulk-send/{job_id}/cancel", headers=headers)
129
+ r.raise_for_status()
130
+ return r.json()
131
+
132
+
133
+ # ============================================================================
134
+ # Scheduled Messages
135
+ # ============================================================================
136
+
137
+ def create_scheduled_message(
138
+ session_id: str,
139
+ custom_group_id: str,
140
+ message_content: str,
141
+ name: str = "Scheduled Message",
142
+ schedule_type: str = "one_time",
143
+ cron_expression: str = None,
144
+ timezone: str = "UTC",
145
+ scheduled_time: str = None,
146
+ ):
147
+ """Create a scheduled message.
148
+
149
+ schedule_type: one_time, daily, weekly, monthly, cron
150
+ scheduled_time: ISO 8601 datetime (required for 'one_time')
151
+ cron_expression: cron string (required for recurring types)
152
+ """
153
+ data = {
154
+ "session_id": session_id,
155
+ "custom_group_id": custom_group_id,
156
+ "message_content": message_content,
157
+ "name": name,
158
+ "schedule_type": schedule_type,
159
+ "timezone": timezone,
160
+ }
161
+ if scheduled_time:
162
+ data["scheduled_time"] = scheduled_time
163
+ if cron_expression:
164
+ data["cron_expression"] = cron_expression
165
+ r = requests.post(f"{BASE_URL}/api/v2/scheduled-messages", headers=headers, json=data)
166
+ r.raise_for_status()
167
+ return r.json()
168
+
169
+
170
+ def list_scheduled_messages(limit: int = 50):
171
+ """List all scheduled messages."""
172
+ r = requests.get(
173
+ f"{BASE_URL}/api/v2/scheduled-messages",
174
+ headers=headers,
175
+ params={"limit": limit},
176
+ )
177
+ r.raise_for_status()
178
+ return r.json()
179
+
180
+
181
+ def pause_scheduled(message_id: str):
182
+ """Pause a scheduled message."""
183
+ r = requests.post(
184
+ f"{BASE_URL}/api/v2/scheduled-messages/{message_id}/pause",
185
+ headers=headers,
186
+ )
187
+ r.raise_for_status()
188
+ return r.json()
189
+
190
+
191
+ def resume_scheduled(message_id: str):
192
+ """Resume a paused scheduled message."""
193
+ r = requests.post(
194
+ f"{BASE_URL}/api/v2/scheduled-messages/{message_id}/resume",
195
+ headers=headers,
196
+ )
197
+ r.raise_for_status()
198
+ return r.json()
199
+
200
+
201
+ def cancel_scheduled(message_id: str):
202
+ """Cancel a scheduled message."""
203
+ r = requests.post(
204
+ f"{BASE_URL}/api/v2/scheduled-messages/{message_id}/cancel",
205
+ headers=headers,
206
+ )
207
+ r.raise_for_status()
208
+ return r.json()
209
+
210
+
211
+ if __name__ == "__main__":
212
+ print("MoltFlow Outreach")
213
+ print("=" * 40)
214
+
215
+ # Custom groups
216
+ groups = list_custom_groups()
217
+ group_list = groups.get("groups", groups) if isinstance(groups, dict) else groups
218
+ print(f"\nCustom Groups: {len(group_list) if isinstance(group_list, list) else 0}")
219
+
220
+ # Bulk jobs
221
+ jobs = list_bulk_jobs()
222
+ job_list = jobs.get("jobs", jobs) if isinstance(jobs, dict) else jobs
223
+ print(f"Bulk Jobs: {len(job_list) if isinstance(job_list, list) else 0}")
224
+
225
+ # Scheduled messages
226
+ scheduled = list_scheduled_messages()
227
+ sched_list = scheduled.get("messages", scheduled) if isinstance(scheduled, dict) else scheduled
228
+ print(f"Scheduled Messages: {len(sched_list) if isinstance(sched_list, list) else 0}")
@@ -6,11 +6,11 @@ import os
6
6
  import requests
7
7
 
8
8
  API_KEY = os.environ.get("MOLTFLOW_API_KEY")
9
- BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://api.moltflow.com")
9
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
10
10
 
11
11
  if not API_KEY:
12
12
  print("Error: MOLTFLOW_API_KEY environment variable not set")
13
- print("Get your API key at https://moltflow.com")
13
+ print("Get your API key at https://waiflow.app")
14
14
  exit(1)
15
15
 
16
16
  headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
@@ -6,7 +6,7 @@ import os
6
6
  import requests
7
7
 
8
8
  API_KEY = os.environ.get("MOLTFLOW_API_KEY")
9
- BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://api.moltflow.com")
9
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
10
10
 
11
11
  if not API_KEY:
12
12
  print("Error: MOLTFLOW_API_KEY environment variable not set")
@@ -1,38 +1,47 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  Send WhatsApp Message Helper
4
- Wrapper around A2A Client for the most common task.
4
+ Simple wrapper for the most common task — sending a text message via the REST API.
5
5
  """
6
6
  import argparse
7
+ import os
7
8
  import sys
8
9
  import json
9
- from a2a_client import A2AClient
10
+ import requests
11
+
12
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
13
+ API_KEY = os.environ.get("MOLTFLOW_API_KEY")
14
+
10
15
 
11
16
  def main():
12
- parser = argparse.ArgumentParser(description="Send WhatsApp message via A2A.")
13
- parser.add_argument("--url", required=True, help="Full A2A API URL")
14
- parser.add_argument("--key", required=True, help="API Key")
15
- parser.add_argument("--to", required=True, help="Target phone number (e.g. 1234567890)")
17
+ parser = argparse.ArgumentParser(description="Send a WhatsApp message via MoltFlow API.")
18
+ parser.add_argument("--session", required=True, help="Session UUID")
19
+ parser.add_argument("--to", required=True, help="Target chat ID (e.g. 1234567890@c.us)")
16
20
  parser.add_argument("--text", required=True, help="Message text content")
17
-
21
+ parser.add_argument("--key", default=API_KEY, help="API key (default: MOLTFLOW_API_KEY env)")
22
+
18
23
  args = parser.parse_args()
19
-
20
- client = A2AClient(args.url, args.key)
21
-
22
- # Construct standard A2A message payload
23
- params = {
24
- "phone": args.to,
25
- "text": args.text
26
- }
27
-
28
- response = client.send_rpc("message/send", params)
29
-
30
- # Output result
31
- print(json.dumps(response, indent=2))
32
-
33
- # Exit code based on success
34
- if "error" in response:
24
+
25
+ if not args.key:
26
+ print("Error: provide --key or set MOLTFLOW_API_KEY env var")
35
27
  sys.exit(1)
36
28
 
29
+ response = requests.post(
30
+ f"{BASE_URL}/api/v2/messages/send",
31
+ headers={"X-API-Key": args.key, "Content-Type": "application/json"},
32
+ json={
33
+ "session_id": args.session,
34
+ "chat_id": args.to,
35
+ "message": args.text,
36
+ },
37
+ )
38
+
39
+ result = response.json()
40
+ print(json.dumps(result, indent=2))
41
+
42
+ if not response.ok:
43
+ sys.exit(1)
44
+
45
+
37
46
  if __name__ == "__main__":
38
47
  main()