runline 0.1.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.
- package/.pi/extensions/runline-context/index.ts +135 -0
- package/.pi/extensions/runline-context/package.json +17 -0
- package/README.md +273 -0
- package/dist/commands/actions.d.ts +3 -0
- package/dist/commands/actions.js +43 -0
- package/dist/commands/connection.d.ts +11 -0
- package/dist/commands/connection.js +56 -0
- package/dist/commands/exec.d.ts +5 -0
- package/dist/commands/exec.js +46 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +26 -0
- package/dist/commands/plugin.d.ts +10 -0
- package/dist/commands/plugin.js +57 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +2 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.js +82 -0
- package/dist/config/types.d.ts +9 -0
- package/dist/config/types.js +5 -0
- package/dist/core/engine.d.ts +21 -0
- package/dist/core/engine.js +280 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +9 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +127 -0
- package/dist/plugin/api.d.ts +32 -0
- package/dist/plugin/api.js +68 -0
- package/dist/plugin/installer.d.ts +27 -0
- package/dist/plugin/installer.js +181 -0
- package/dist/plugin/loader.d.ts +13 -0
- package/dist/plugin/loader.js +164 -0
- package/dist/plugin/registry.d.ts +18 -0
- package/dist/plugin/registry.js +43 -0
- package/dist/plugin/types.d.ts +40 -0
- package/dist/plugin/types.js +1 -0
- package/dist/plugins/actionNetwork/src/index.js +353 -0
- package/dist/plugins/activeCampaign/src/index.js +711 -0
- package/dist/plugins/adalo/src/index.js +131 -0
- package/dist/plugins/affinity/src/index.js +279 -0
- package/dist/plugins/agileCrm/src/index.js +415 -0
- package/dist/plugins/airtable/src/index.js +280 -0
- package/dist/plugins/airtop/src/index.js +527 -0
- package/dist/plugins/apiTemplateIo/src/index.js +86 -0
- package/dist/plugins/asana/src/index.js +413 -0
- package/dist/plugins/autopilot/src/index.js +203 -0
- package/dist/plugins/bambooHr/src/index.js +252 -0
- package/dist/plugins/bannerbear/src/index.js +100 -0
- package/dist/plugins/baserow/src/index.js +180 -0
- package/dist/plugins/beeminder/src/index.js +298 -0
- package/dist/plugins/bitly/src/index.js +107 -0
- package/dist/plugins/bitwarden/src/index.js +383 -0
- package/dist/plugins/box/src/index.js +300 -0
- package/dist/plugins/brandfetch/src/index.js +80 -0
- package/dist/plugins/brevo/src/index.js +305 -0
- package/dist/plugins/bubble/src/index.js +181 -0
- package/dist/plugins/chargebee/src/index.js +126 -0
- package/dist/plugins/circleci/src/index.js +111 -0
- package/dist/plugins/ciscoWebex/src/index.js +245 -0
- package/dist/plugins/clearbit/src/index.js +103 -0
- package/dist/plugins/clickup/src/index.js +1043 -0
- package/dist/plugins/clockify/src/index.js +443 -0
- package/dist/plugins/cloudflare/src/index.js +93 -0
- package/dist/plugins/cockpit/src/index.js +131 -0
- package/dist/plugins/coda/src/index.js +327 -0
- package/dist/plugins/coingecko/src/index.js +244 -0
- package/dist/plugins/contentful/src/index.js +146 -0
- package/dist/plugins/convertkit/src/index.js +270 -0
- package/dist/plugins/copper/src/index.js +140 -0
- package/dist/plugins/cortex/src/index.js +147 -0
- package/dist/plugins/currents/src/index.js +405 -0
- package/dist/plugins/customerIo/src/index.js +184 -0
- package/dist/plugins/databricks/src/index.js +342 -0
- package/dist/plugins/deepl/src/index.js +87 -0
- package/dist/plugins/demio/src/index.js +111 -0
- package/dist/plugins/dhl/src/index.js +40 -0
- package/dist/plugins/discord/src/index.js +275 -0
- package/dist/plugins/discourse/src/index.js +273 -0
- package/dist/plugins/disqus/src/index.js +145 -0
- package/dist/plugins/docker/src/index.js +76 -0
- package/dist/plugins/drift/src/index.js +89 -0
- package/dist/plugins/dropbox/src/index.js +159 -0
- package/dist/plugins/dropcontact/src/index.js +59 -0
- package/dist/plugins/egoi/src/index.js +151 -0
- package/dist/plugins/elasticsearch/src/index.js +157 -0
- package/dist/plugins/emelia/src/index.js +174 -0
- package/dist/plugins/erpnext/src/index.js +121 -0
- package/dist/plugins/facebookGraph/src/index.js +57 -0
- package/dist/plugins/freshdesk/src/index.js +320 -0
- package/dist/plugins/freshservice/src/index.js +146 -0
- package/dist/plugins/freshworksCrm/src/index.js +149 -0
- package/dist/plugins/getresponse/src/index.js +140 -0
- package/dist/plugins/ghost/src/index.js +192 -0
- package/dist/plugins/github/src/index.js +630 -0
- package/dist/plugins/gitlab/src/index.js +358 -0
- package/dist/plugins/gong/src/index.js +126 -0
- package/dist/plugins/gotify/src/index.js +77 -0
- package/dist/plugins/gotowebinar/src/index.js +316 -0
- package/dist/plugins/grafana/src/index.js +250 -0
- package/dist/plugins/graphql/src/index.js +78 -0
- package/dist/plugins/grist/src/index.js +106 -0
- package/dist/plugins/hackernews/src/index.js +89 -0
- package/dist/plugins/halopsa/src/index.js +79 -0
- package/dist/plugins/harvest/src/index.js +163 -0
- package/dist/plugins/helpscout/src/index.js +176 -0
- package/dist/plugins/highlevel/src/index.js +172 -0
- package/dist/plugins/homeAssistant/src/index.js +148 -0
- package/dist/plugins/hubspot/src/index.js +176 -0
- package/dist/plugins/humanticAi/src/index.js +60 -0
- package/dist/plugins/hunter/src/index.js +59 -0
- package/dist/plugins/intercom/src/index.js +156 -0
- package/dist/plugins/iterable/src/index.js +139 -0
- package/dist/plugins/jenkins/src/index.js +132 -0
- package/dist/plugins/jira/src/index.js +229 -0
- package/dist/plugins/keap/src/index.js +502 -0
- package/dist/plugins/kobotoolbox/src/index.js +281 -0
- package/dist/plugins/lemlist/src/index.js +231 -0
- package/dist/plugins/linear/src/index.js +133 -0
- package/dist/plugins/lingvanex/src/index.js +31 -0
- package/dist/plugins/linkedin/src/index.js +80 -0
- package/dist/plugins/lonescale/src/index.js +119 -0
- package/dist/plugins/magento/src/index.js +300 -0
- package/dist/plugins/mailcheck/src/index.js +27 -0
- package/dist/plugins/mailchimp/src/index.js +321 -0
- package/dist/plugins/mailerlite/src/index.js +123 -0
- package/dist/plugins/mailgun/src/index.js +48 -0
- package/dist/plugins/mailjet/src/index.js +155 -0
- package/dist/plugins/mandrill/src/index.js +145 -0
- package/dist/plugins/marketstack/src/index.js +97 -0
- package/dist/plugins/matrix/src/index.js +194 -0
- package/dist/plugins/mattermost/src/index.js +331 -0
- package/dist/plugins/mautic/src/index.js +311 -0
- package/dist/plugins/medium/src/index.js +77 -0
- package/dist/plugins/messagebird/src/index.js +57 -0
- package/dist/plugins/metabase/src/index.js +130 -0
- package/dist/plugins/misp/src/index.js +476 -0
- package/dist/plugins/mocean/src/index.js +67 -0
- package/dist/plugins/monday/src/index.js +231 -0
- package/dist/plugins/monicaCrm/src/index.js +52 -0
- package/dist/plugins/msg91/src/index.js +31 -0
- package/dist/plugins/nasa/src/index.js +146 -0
- package/dist/plugins/netlify/src/index.js +151 -0
- package/dist/plugins/netscalerAdc/src/index.js +131 -0
- package/dist/plugins/nextcloud/src/index.js +263 -0
- package/dist/plugins/nocodb/src/index.js +130 -0
- package/dist/plugins/notion/src/index.js +112 -0
- package/dist/plugins/npm/src/index.js +104 -0
- package/dist/plugins/odoo/src/index.js +157 -0
- package/dist/plugins/okta/src/index.js +141 -0
- package/dist/plugins/oneSimpleApi/src/index.js +155 -0
- package/dist/plugins/onfleet/src/index.js +254 -0
- package/dist/plugins/openThesaurus/src/index.js +32 -0
- package/dist/plugins/openweathermap/src/index.js +60 -0
- package/dist/plugins/oura/src/index.js +62 -0
- package/dist/plugins/paddle/src/index.js +247 -0
- package/dist/plugins/pagerduty/src/index.js +201 -0
- package/dist/plugins/paypal/src/index.js +106 -0
- package/dist/plugins/peekalink/src/index.js +35 -0
- package/dist/plugins/phantombuster/src/index.js +94 -0
- package/dist/plugins/philipsHue/src/index.js +98 -0
- package/dist/plugins/pipedrive/src/index.js +169 -0
- package/dist/plugins/plivo/src/index.js +66 -0
- package/dist/plugins/postbin/src/index.js +93 -0
- package/dist/plugins/posthog/src/index.js +113 -0
- package/dist/plugins/profitwell/src/index.js +50 -0
- package/dist/plugins/pushbullet/src/index.js +102 -0
- package/dist/plugins/pushcut/src/index.js +39 -0
- package/dist/plugins/pushover/src/index.js +65 -0
- package/dist/plugins/quickbase/src/index.js +153 -0
- package/dist/plugins/quickbooks/src/index.js +73 -0
- package/dist/plugins/quickchart/src/index.js +36 -0
- package/dist/plugins/raindrop/src/index.js +209 -0
- package/dist/plugins/reddit/src/index.js +185 -0
- package/dist/plugins/rocketchat/src/index.js +53 -0
- package/dist/plugins/rundeck/src/index.js +62 -0
- package/dist/plugins/salesforce/src/index.js +94 -0
- package/dist/plugins/salesmate/src/index.js +83 -0
- package/dist/plugins/securityScorecard/src/index.js +200 -0
- package/dist/plugins/segment/src/index.js +125 -0
- package/dist/plugins/sendgrid/src/index.js +187 -0
- package/dist/plugins/sendy/src/index.js +138 -0
- package/dist/plugins/sentry/src/index.js +233 -0
- package/dist/plugins/servicenow/src/index.js +108 -0
- package/dist/plugins/shopify/src/index.js +222 -0
- package/dist/plugins/signl4/src/index.js +61 -0
- package/dist/plugins/slack/src/index.js +236 -0
- package/dist/plugins/sms77/src/index.js +63 -0
- package/dist/plugins/splunk/src/index.js +207 -0
- package/dist/plugins/spotify/src/index.js +188 -0
- package/dist/plugins/stackby/src/index.js +82 -0
- package/dist/plugins/storyblok/src/index.js +141 -0
- package/dist/plugins/strapi/src/index.js +152 -0
- package/dist/plugins/strava/src/index.js +137 -0
- package/dist/plugins/stripe/src/index.js +222 -0
- package/dist/plugins/supabase/src/index.js +121 -0
- package/dist/plugins/syncromsp/src/index.js +255 -0
- package/dist/plugins/tapfiliate/src/index.js +125 -0
- package/dist/plugins/telegram/src/index.js +233 -0
- package/dist/plugins/thehive/src/index.js +142 -0
- package/dist/plugins/thehiveProject/src/index.js +194 -0
- package/dist/plugins/todoist/src/index.js +244 -0
- package/dist/plugins/travisci/src/index.js +71 -0
- package/dist/plugins/trello/src/index.js +341 -0
- package/dist/plugins/twake/src/index.js +40 -0
- package/dist/plugins/twilio/src/index.js +75 -0
- package/dist/plugins/twist/src/index.js +90 -0
- package/dist/plugins/twitter/src/index.js +123 -0
- package/dist/plugins/unleashedSoftware/src/index.js +84 -0
- package/dist/plugins/uplead/src/index.js +59 -0
- package/dist/plugins/uproc/src/index.js +34 -0
- package/dist/plugins/uptimerobot/src/index.js +264 -0
- package/dist/plugins/urlscanio/src/index.js +64 -0
- package/dist/plugins/vero/src/index.js +80 -0
- package/dist/plugins/vonage/src/index.js +42 -0
- package/dist/plugins/wekan/src/index.js +91 -0
- package/dist/plugins/woocommerce/src/index.js +92 -0
- package/dist/plugins/wordpress/src/index.js +121 -0
- package/dist/plugins/xero/src/index.js +136 -0
- package/dist/plugins/yourls/src/index.js +56 -0
- package/dist/plugins/zammad/src/index.js +91 -0
- package/dist/plugins/zendesk/src/index.js +137 -0
- package/dist/plugins/zoho/src/index.js +85 -0
- package/dist/plugins/zoom/src/index.js +122 -0
- package/dist/plugins/zulip/src/index.js +170 -0
- package/dist/sdk.d.ts +38 -0
- package/dist/sdk.js +105 -0
- package/dist/utils/cli.d.ts +13 -0
- package/dist/utils/cli.js +32 -0
- package/dist/utils/output.d.ts +4 -0
- package/dist/utils/output.js +13 -0
- package/package.json +57 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
async function api(token, method, endpoint, body, qs) {
|
|
2
|
+
const url = new URL(`https://slack.com/api${endpoint}`);
|
|
3
|
+
if (qs) {
|
|
4
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
5
|
+
if (v !== undefined && v !== null)
|
|
6
|
+
url.searchParams.set(k, String(v));
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const init = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json; charset=utf-8" } };
|
|
10
|
+
if (body && Object.keys(body).length > 0)
|
|
11
|
+
init.body = JSON.stringify(body);
|
|
12
|
+
const res = await fetch(url.toString(), init);
|
|
13
|
+
if (!res.ok)
|
|
14
|
+
throw new Error(`Slack HTTP error ${res.status}: ${await res.text()}`);
|
|
15
|
+
const data = (await res.json());
|
|
16
|
+
if (data.ok === false)
|
|
17
|
+
throw new Error(`Slack API error: ${data.error}`);
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
export default function slack(rl) {
|
|
21
|
+
rl.setName("slack");
|
|
22
|
+
rl.setVersion("0.1.0");
|
|
23
|
+
rl.setConnectionSchema({ accessToken: { type: "string", required: true, description: "Slack Bot/User token", env: "SLACK_ACCESS_TOKEN" } });
|
|
24
|
+
const t = (ctx) => ctx.connection.config.accessToken;
|
|
25
|
+
// ── Message ─────────────────────────────────────────
|
|
26
|
+
rl.registerAction("message.post", { description: "Post a message to a channel or user",
|
|
27
|
+
inputSchema: { channel: { type: "string", required: true }, text: { type: "string", required: false }, blocks: { type: "object", required: false }, threadTs: { type: "string", required: false }, replyBroadcast: { type: "boolean", required: false }, unfurlLinks: { type: "boolean", required: false } },
|
|
28
|
+
async execute(input, ctx) {
|
|
29
|
+
const p = input;
|
|
30
|
+
const body = { channel: p.channel };
|
|
31
|
+
if (p.text)
|
|
32
|
+
body.text = p.text;
|
|
33
|
+
if (p.blocks)
|
|
34
|
+
body.blocks = p.blocks;
|
|
35
|
+
if (p.threadTs)
|
|
36
|
+
body.thread_ts = p.threadTs;
|
|
37
|
+
if (p.replyBroadcast)
|
|
38
|
+
body.reply_broadcast = true;
|
|
39
|
+
if (p.unfurlLinks !== undefined)
|
|
40
|
+
body.unfurl_links = p.unfurlLinks;
|
|
41
|
+
return api(t(ctx), "POST", "/chat.postMessage", body);
|
|
42
|
+
} });
|
|
43
|
+
rl.registerAction("message.update", { description: "Update a message",
|
|
44
|
+
inputSchema: { channel: { type: "string", required: true }, ts: { type: "string", required: true }, text: { type: "string", required: false }, blocks: { type: "object", required: false } },
|
|
45
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/chat.update", input); } });
|
|
46
|
+
rl.registerAction("message.delete", { description: "Delete a message",
|
|
47
|
+
inputSchema: { channel: { type: "string", required: true }, ts: { type: "string", required: true } },
|
|
48
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/chat.delete", input); } });
|
|
49
|
+
rl.registerAction("message.getPermalink", { description: "Get a message permalink",
|
|
50
|
+
inputSchema: { channel: { type: "string", required: true }, messageTs: { type: "string", required: true } },
|
|
51
|
+
async execute(input, ctx) { const p = input; return api(t(ctx), "GET", "/chat.getPermalink", undefined, { channel: p.channel, message_ts: p.messageTs }); } });
|
|
52
|
+
rl.registerAction("message.search", { description: "Search messages",
|
|
53
|
+
inputSchema: { query: { type: "string", required: true }, sort: { type: "string", required: false, description: "score or timestamp" }, limit: { type: "number", required: false } },
|
|
54
|
+
async execute(input, ctx) {
|
|
55
|
+
const p = input;
|
|
56
|
+
const qs = { query: p.query };
|
|
57
|
+
if (p.sort)
|
|
58
|
+
qs.sort = p.sort === "relevance" ? "score" : "timestamp";
|
|
59
|
+
if (p.limit)
|
|
60
|
+
qs.count = p.limit;
|
|
61
|
+
const data = (await api(t(ctx), "POST", "/search.messages", undefined, qs));
|
|
62
|
+
return data.messages?.matches;
|
|
63
|
+
} });
|
|
64
|
+
// ── Channel ─────────────────────────────────────────
|
|
65
|
+
rl.registerAction("channel.create", { description: "Create a channel",
|
|
66
|
+
inputSchema: { name: { type: "string", required: true }, isPrivate: { type: "boolean", required: false } },
|
|
67
|
+
async execute(input, ctx) {
|
|
68
|
+
const p = input;
|
|
69
|
+
const data = (await api(t(ctx), "POST", "/conversations.create", { name: p.name, is_private: p.isPrivate ?? false }));
|
|
70
|
+
return data.channel;
|
|
71
|
+
} });
|
|
72
|
+
rl.registerAction("channel.get", { description: "Get channel info",
|
|
73
|
+
inputSchema: { channel: { type: "string", required: true } },
|
|
74
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/conversations.info", undefined, { channel: input.channel })); return data.channel; } });
|
|
75
|
+
rl.registerAction("channel.list", { description: "List channels",
|
|
76
|
+
inputSchema: { limit: { type: "number", required: false }, types: { type: "string", required: false, description: "Comma-separated: public_channel,private_channel" }, excludeArchived: { type: "boolean", required: false } },
|
|
77
|
+
async execute(input, ctx) {
|
|
78
|
+
const p = (input ?? {});
|
|
79
|
+
const qs = { types: p.types ?? "public_channel,private_channel" };
|
|
80
|
+
if (p.limit)
|
|
81
|
+
qs.limit = p.limit;
|
|
82
|
+
if (p.excludeArchived)
|
|
83
|
+
qs.exclude_archived = true;
|
|
84
|
+
const data = (await api(t(ctx), "GET", "/conversations.list", undefined, qs));
|
|
85
|
+
return data.channels;
|
|
86
|
+
} });
|
|
87
|
+
rl.registerAction("channel.history", { description: "Get channel message history",
|
|
88
|
+
inputSchema: { channel: { type: "string", required: true }, limit: { type: "number", required: false }, oldest: { type: "string", required: false, description: "ISO datetime" }, latest: { type: "string", required: false } },
|
|
89
|
+
async execute(input, ctx) {
|
|
90
|
+
const p = input;
|
|
91
|
+
const qs = { channel: p.channel };
|
|
92
|
+
if (p.limit)
|
|
93
|
+
qs.limit = p.limit;
|
|
94
|
+
if (p.oldest)
|
|
95
|
+
qs.oldest = new Date(p.oldest).getTime() / 1000;
|
|
96
|
+
if (p.latest)
|
|
97
|
+
qs.latest = new Date(p.latest).getTime() / 1000;
|
|
98
|
+
const data = (await api(t(ctx), "GET", "/conversations.history", undefined, qs));
|
|
99
|
+
return data.messages;
|
|
100
|
+
} });
|
|
101
|
+
rl.registerAction("channel.replies", { description: "Get thread replies",
|
|
102
|
+
inputSchema: { channel: { type: "string", required: true }, ts: { type: "string", required: true }, limit: { type: "number", required: false } },
|
|
103
|
+
async execute(input, ctx) {
|
|
104
|
+
const p = input;
|
|
105
|
+
const qs = { channel: p.channel, ts: p.ts };
|
|
106
|
+
if (p.limit)
|
|
107
|
+
qs.limit = p.limit;
|
|
108
|
+
const data = (await api(t(ctx), "GET", "/conversations.replies", undefined, qs));
|
|
109
|
+
return data.messages;
|
|
110
|
+
} });
|
|
111
|
+
rl.registerAction("channel.invite", { description: "Invite users to a channel",
|
|
112
|
+
inputSchema: { channel: { type: "string", required: true }, users: { type: "string", required: true, description: "Comma-separated user IDs" } },
|
|
113
|
+
async execute(input, ctx) { const p = input; const data = (await api(t(ctx), "POST", "/conversations.invite", { channel: p.channel, users: p.users })); return data.channel; } });
|
|
114
|
+
rl.registerAction("channel.kick", { description: "Remove a user from a channel",
|
|
115
|
+
inputSchema: { channel: { type: "string", required: true }, user: { type: "string", required: true } },
|
|
116
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/conversations.kick", input); } });
|
|
117
|
+
rl.registerAction("channel.join", { description: "Join a channel",
|
|
118
|
+
inputSchema: { channel: { type: "string", required: true } },
|
|
119
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/conversations.join", { channel: input.channel })); return data.channel; } });
|
|
120
|
+
rl.registerAction("channel.leave", { description: "Leave a channel",
|
|
121
|
+
inputSchema: { channel: { type: "string", required: true } },
|
|
122
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/conversations.leave", { channel: input.channel }); } });
|
|
123
|
+
rl.registerAction("channel.archive", { description: "Archive a channel",
|
|
124
|
+
inputSchema: { channel: { type: "string", required: true } },
|
|
125
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/conversations.archive", { channel: input.channel }); } });
|
|
126
|
+
rl.registerAction("channel.unarchive", { description: "Unarchive a channel",
|
|
127
|
+
inputSchema: { channel: { type: "string", required: true } },
|
|
128
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/conversations.unarchive", { channel: input.channel }); } });
|
|
129
|
+
rl.registerAction("channel.rename", { description: "Rename a channel",
|
|
130
|
+
inputSchema: { channel: { type: "string", required: true }, name: { type: "string", required: true } },
|
|
131
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/conversations.rename", input)); return data.channel; } });
|
|
132
|
+
rl.registerAction("channel.setTopic", { description: "Set channel topic",
|
|
133
|
+
inputSchema: { channel: { type: "string", required: true }, topic: { type: "string", required: true } },
|
|
134
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/conversations.setTopic", input)); return data.channel; } });
|
|
135
|
+
rl.registerAction("channel.setPurpose", { description: "Set channel purpose",
|
|
136
|
+
inputSchema: { channel: { type: "string", required: true }, purpose: { type: "string", required: true } },
|
|
137
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/conversations.setPurpose", input)); return data.channel; } });
|
|
138
|
+
rl.registerAction("channel.members", { description: "List channel members",
|
|
139
|
+
inputSchema: { channel: { type: "string", required: true }, limit: { type: "number", required: false } },
|
|
140
|
+
async execute(input, ctx) {
|
|
141
|
+
const p = input;
|
|
142
|
+
const qs = { channel: p.channel };
|
|
143
|
+
if (p.limit)
|
|
144
|
+
qs.limit = p.limit;
|
|
145
|
+
const data = (await api(t(ctx), "GET", "/conversations.members", undefined, qs));
|
|
146
|
+
return data.members.map(m => ({ member: m }));
|
|
147
|
+
} });
|
|
148
|
+
// ── Reaction ────────────────────────────────────────
|
|
149
|
+
rl.registerAction("reaction.add", { description: "Add a reaction to a message",
|
|
150
|
+
inputSchema: { channel: { type: "string", required: true }, timestamp: { type: "string", required: true }, name: { type: "string", required: true, description: "Emoji name without colons" } },
|
|
151
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/reactions.add", input); } });
|
|
152
|
+
rl.registerAction("reaction.remove", { description: "Remove a reaction",
|
|
153
|
+
inputSchema: { channel: { type: "string", required: true }, timestamp: { type: "string", required: true }, name: { type: "string", required: true } },
|
|
154
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/reactions.remove", input); } });
|
|
155
|
+
rl.registerAction("reaction.get", { description: "Get reactions for a message",
|
|
156
|
+
inputSchema: { channel: { type: "string", required: true }, timestamp: { type: "string", required: true } },
|
|
157
|
+
async execute(input, ctx) { return api(t(ctx), "GET", "/reactions.get", undefined, input); } });
|
|
158
|
+
// ── User ────────────────────────────────────────────
|
|
159
|
+
rl.registerAction("user.info", { description: "Get user info",
|
|
160
|
+
inputSchema: { user: { type: "string", required: true } },
|
|
161
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "GET", "/users.info", undefined, { user: input.user })); return data.user; } });
|
|
162
|
+
rl.registerAction("user.list", { description: "List all users",
|
|
163
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
164
|
+
async execute(input, ctx) {
|
|
165
|
+
const qs = {};
|
|
166
|
+
if (input?.limit)
|
|
167
|
+
qs.limit = input.limit;
|
|
168
|
+
const data = (await api(t(ctx), "GET", "/users.list", undefined, qs));
|
|
169
|
+
return data.members;
|
|
170
|
+
} });
|
|
171
|
+
rl.registerAction("user.getPresence", { description: "Get a user's presence",
|
|
172
|
+
inputSchema: { user: { type: "string", required: true } },
|
|
173
|
+
async execute(input, ctx) { return api(t(ctx), "GET", "/users.getPresence", undefined, { user: input.user }); } });
|
|
174
|
+
rl.registerAction("user.getProfile", { description: "Get a user's profile",
|
|
175
|
+
inputSchema: { user: { type: "string", required: true } },
|
|
176
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "GET", "/users.profile.get", undefined, { user: input.user })); return data.profile; } });
|
|
177
|
+
rl.registerAction("user.updateProfile", { description: "Update the authenticated user's profile",
|
|
178
|
+
inputSchema: { profile: { type: "object", required: true, description: "Profile fields to set" } },
|
|
179
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/users.profile.set", { profile: input.profile })); return data.profile; } });
|
|
180
|
+
// ── User Group ──────────────────────────────────────
|
|
181
|
+
rl.registerAction("userGroup.create", { description: "Create a user group",
|
|
182
|
+
inputSchema: { name: { type: "string", required: true }, handle: { type: "string", required: false }, description: { type: "string", required: false } },
|
|
183
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/usergroups.create", input)); return data.usergroup; } });
|
|
184
|
+
rl.registerAction("userGroup.list", { description: "List user groups",
|
|
185
|
+
inputSchema: { includeUsers: { type: "boolean", required: false } },
|
|
186
|
+
async execute(input, ctx) {
|
|
187
|
+
const qs = {};
|
|
188
|
+
if (input?.includeUsers)
|
|
189
|
+
qs.include_users = true;
|
|
190
|
+
const data = (await api(t(ctx), "GET", "/usergroups.list", undefined, qs));
|
|
191
|
+
return data.usergroups;
|
|
192
|
+
} });
|
|
193
|
+
rl.registerAction("userGroup.update", { description: "Update a user group",
|
|
194
|
+
inputSchema: { usergroup: { type: "string", required: true }, name: { type: "string", required: false }, handle: { type: "string", required: false }, description: { type: "string", required: false } },
|
|
195
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/usergroups.update", input)); return data.usergroup; } });
|
|
196
|
+
rl.registerAction("userGroup.enable", { description: "Enable a user group",
|
|
197
|
+
inputSchema: { usergroup: { type: "string", required: true } },
|
|
198
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/usergroups.enable", { usergroup: input.usergroup })); return data.usergroup; } });
|
|
199
|
+
rl.registerAction("userGroup.disable", { description: "Disable a user group",
|
|
200
|
+
inputSchema: { usergroup: { type: "string", required: true } },
|
|
201
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "POST", "/usergroups.disable", { usergroup: input.usergroup })); return data.usergroup; } });
|
|
202
|
+
// ── File ────────────────────────────────────────────
|
|
203
|
+
rl.registerAction("file.get", { description: "Get file info",
|
|
204
|
+
inputSchema: { file: { type: "string", required: true } },
|
|
205
|
+
async execute(input, ctx) { const data = (await api(t(ctx), "GET", "/files.info", undefined, { file: input.file })); return data.file; } });
|
|
206
|
+
rl.registerAction("file.list", { description: "List files",
|
|
207
|
+
inputSchema: { channel: { type: "string", required: false }, limit: { type: "number", required: false }, types: { type: "string", required: false } },
|
|
208
|
+
async execute(input, ctx) {
|
|
209
|
+
const p = (input ?? {});
|
|
210
|
+
const qs = {};
|
|
211
|
+
if (p.channel)
|
|
212
|
+
qs.channel = p.channel;
|
|
213
|
+
if (p.limit)
|
|
214
|
+
qs.count = p.limit;
|
|
215
|
+
if (p.types)
|
|
216
|
+
qs.types = p.types;
|
|
217
|
+
const data = (await api(t(ctx), "GET", "/files.list", undefined, qs));
|
|
218
|
+
return data.files;
|
|
219
|
+
} });
|
|
220
|
+
// ── Star ────────────────────────────────────────────
|
|
221
|
+
rl.registerAction("star.add", { description: "Star an item",
|
|
222
|
+
inputSchema: { channel: { type: "string", required: false }, timestamp: { type: "string", required: false }, file: { type: "string", required: false } },
|
|
223
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/stars.add", input); } });
|
|
224
|
+
rl.registerAction("star.remove", { description: "Unstar an item",
|
|
225
|
+
inputSchema: { channel: { type: "string", required: false }, timestamp: { type: "string", required: false }, file: { type: "string", required: false } },
|
|
226
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/stars.remove", input); } });
|
|
227
|
+
rl.registerAction("star.list", { description: "List starred items",
|
|
228
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
229
|
+
async execute(input, ctx) {
|
|
230
|
+
const qs = {};
|
|
231
|
+
if (input?.limit)
|
|
232
|
+
qs.limit = input.limit;
|
|
233
|
+
const data = (await api(t(ctx), "GET", "/stars.list", undefined, qs));
|
|
234
|
+
return data.items;
|
|
235
|
+
} });
|
|
236
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const BASE = "https://gateway.seven.io/api";
|
|
2
|
+
async function apiRequest(apiKey, endpoint, body) {
|
|
3
|
+
const form = new URLSearchParams();
|
|
4
|
+
for (const [k, v] of Object.entries(body)) {
|
|
5
|
+
if (v !== undefined && v !== null)
|
|
6
|
+
form.set(k, String(v));
|
|
7
|
+
}
|
|
8
|
+
const res = await fetch(`${BASE}${endpoint}`, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: { "X-Api-Key": apiKey, SentWith: "runline" },
|
|
11
|
+
body: form,
|
|
12
|
+
});
|
|
13
|
+
if (!res.ok)
|
|
14
|
+
throw new Error(`seven API error ${res.status}: ${await res.text()}`);
|
|
15
|
+
return res.json();
|
|
16
|
+
}
|
|
17
|
+
export default function sms77(rl) {
|
|
18
|
+
rl.setName("sms77");
|
|
19
|
+
rl.setVersion("0.1.0");
|
|
20
|
+
rl.setConnectionSchema({
|
|
21
|
+
apiKey: { type: "string", required: true, description: "seven (sms77) API key", env: "SMS77_API_KEY" },
|
|
22
|
+
});
|
|
23
|
+
const key = (ctx) => ctx.connection.config.apiKey;
|
|
24
|
+
rl.registerAction("sms.send", {
|
|
25
|
+
description: "Send an SMS via seven",
|
|
26
|
+
inputSchema: {
|
|
27
|
+
to: { type: "string", required: true, description: "Recipient number(s), comma-separated" },
|
|
28
|
+
message: { type: "string", required: true, description: "Message text (max 1520 chars)" },
|
|
29
|
+
from: { type: "string", required: false, description: "Sender ID" },
|
|
30
|
+
flash: { type: "boolean", required: false },
|
|
31
|
+
delay: { type: "string", required: false, description: "Scheduled send time" },
|
|
32
|
+
ttl: { type: "number", required: false, description: "Time to live in minutes" },
|
|
33
|
+
},
|
|
34
|
+
async execute(input, ctx) {
|
|
35
|
+
const p = input;
|
|
36
|
+
const body = { to: p.to, text: p.message };
|
|
37
|
+
if (p.from)
|
|
38
|
+
body.from = p.from;
|
|
39
|
+
if (p.flash)
|
|
40
|
+
body.flash = 1;
|
|
41
|
+
if (p.delay)
|
|
42
|
+
body.delay = p.delay;
|
|
43
|
+
if (p.ttl)
|
|
44
|
+
body.ttl = p.ttl;
|
|
45
|
+
return apiRequest(key(ctx), "/sms", body);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
rl.registerAction("voice.send", {
|
|
49
|
+
description: "Convert text to voice and call a number",
|
|
50
|
+
inputSchema: {
|
|
51
|
+
to: { type: "string", required: true },
|
|
52
|
+
message: { type: "string", required: true, description: "Text to speak" },
|
|
53
|
+
from: { type: "string", required: false, description: "Caller ID" },
|
|
54
|
+
},
|
|
55
|
+
async execute(input, ctx) {
|
|
56
|
+
const p = input;
|
|
57
|
+
const body = { to: p.to, text: p.message };
|
|
58
|
+
if (p.from)
|
|
59
|
+
body.from = p.from;
|
|
60
|
+
return apiRequest(key(ctx), "/voice", body);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
function getConn(ctx) {
|
|
2
|
+
const baseUrl = ctx.connection.config.baseUrl.replace(/\/$/, "");
|
|
3
|
+
const authToken = ctx.connection.config.authToken;
|
|
4
|
+
return { baseUrl, authToken };
|
|
5
|
+
}
|
|
6
|
+
// Splunk REST API uses form-urlencoded for POST, returns JSON when output_mode=json
|
|
7
|
+
async function api(baseUrl, token, method, endpoint, body, qs) {
|
|
8
|
+
const url = new URL(`${baseUrl}${endpoint}`);
|
|
9
|
+
// Always request JSON output
|
|
10
|
+
url.searchParams.set("output_mode", "json");
|
|
11
|
+
if (qs) {
|
|
12
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
13
|
+
if (v !== undefined && v !== null)
|
|
14
|
+
url.searchParams.set(k, String(v));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
18
|
+
const init = { method, headers };
|
|
19
|
+
if (body && Object.keys(body).length > 0) {
|
|
20
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
21
|
+
const params = new URLSearchParams();
|
|
22
|
+
for (const [k, v] of Object.entries(body)) {
|
|
23
|
+
if (v === undefined || v === null)
|
|
24
|
+
continue;
|
|
25
|
+
if (Array.isArray(v)) {
|
|
26
|
+
for (const item of v)
|
|
27
|
+
params.append(k, String(item));
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
params.set(k, String(v));
|
|
31
|
+
}
|
|
32
|
+
init.body = params.toString();
|
|
33
|
+
}
|
|
34
|
+
const res = await fetch(url.toString(), init);
|
|
35
|
+
if (!res.ok)
|
|
36
|
+
throw new Error(`Splunk error ${res.status}: ${await res.text()}`);
|
|
37
|
+
const text = await res.text();
|
|
38
|
+
if (!text)
|
|
39
|
+
return { success: true };
|
|
40
|
+
const json = JSON.parse(text);
|
|
41
|
+
// Format entry array if present
|
|
42
|
+
if (json.entry && Array.isArray(json.entry)) {
|
|
43
|
+
return json.entry.map((e) => {
|
|
44
|
+
const { content, link, ...rest } = e;
|
|
45
|
+
const flat = { ...rest, ...(content ?? {}) };
|
|
46
|
+
if (flat.id && typeof flat.id === "string") {
|
|
47
|
+
flat.entryUrl = flat.id;
|
|
48
|
+
flat.id = flat.id.split("/").pop();
|
|
49
|
+
}
|
|
50
|
+
return flat;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return json;
|
|
54
|
+
}
|
|
55
|
+
export default function splunk(rl) {
|
|
56
|
+
rl.setName("splunk");
|
|
57
|
+
rl.setVersion("0.1.0");
|
|
58
|
+
rl.setConnectionSchema({
|
|
59
|
+
baseUrl: { type: "string", required: true, description: "Splunk instance URL, e.g. https://localhost:8089", env: "SPLUNK_BASE_URL" },
|
|
60
|
+
authToken: { type: "string", required: true, description: "Splunk auth token", env: "SPLUNK_AUTH_TOKEN" },
|
|
61
|
+
});
|
|
62
|
+
// ── Search Jobs ─────────────────────────────────────
|
|
63
|
+
rl.registerAction("search.create", { description: "Create a search job",
|
|
64
|
+
inputSchema: { search: { type: "string", required: true, description: "SPL query" }, execMode: { type: "string", required: false, description: "blocking, normal, or oneshot" }, earliestTime: { type: "string", required: false }, latestTime: { type: "string", required: false }, maxTime: { type: "number", required: false }, namespace: { type: "string", required: false } },
|
|
65
|
+
async execute(input, ctx) {
|
|
66
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
67
|
+
const p = input;
|
|
68
|
+
const body = { search: p.search };
|
|
69
|
+
if (p.execMode)
|
|
70
|
+
body.exec_mode = p.execMode;
|
|
71
|
+
if (p.earliestTime)
|
|
72
|
+
body.earliest_time = p.earliestTime;
|
|
73
|
+
if (p.latestTime)
|
|
74
|
+
body.latest_time = p.latestTime;
|
|
75
|
+
if (p.maxTime)
|
|
76
|
+
body.max_time = p.maxTime;
|
|
77
|
+
if (p.namespace)
|
|
78
|
+
body.namespace = p.namespace;
|
|
79
|
+
// Create returns XML with sid, then we fetch JSON
|
|
80
|
+
const createRes = await api(baseUrl, authToken, "POST", "/services/search/jobs", body);
|
|
81
|
+
const sid = createRes.sid;
|
|
82
|
+
if (sid)
|
|
83
|
+
return api(baseUrl, authToken, "GET", `/services/search/jobs/${sid}`);
|
|
84
|
+
return createRes;
|
|
85
|
+
} });
|
|
86
|
+
rl.registerAction("search.get", { description: "Get a search job by ID",
|
|
87
|
+
inputSchema: { searchJobId: { type: "string", required: true } },
|
|
88
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); return api(baseUrl, authToken, "GET", `/services/search/jobs/${input.searchJobId}`); } });
|
|
89
|
+
rl.registerAction("search.list", { description: "List search jobs",
|
|
90
|
+
inputSchema: { limit: { type: "number", required: false }, sortKey: { type: "string", required: false }, sortDir: { type: "string", required: false, description: "asc or desc" } },
|
|
91
|
+
async execute(input, ctx) {
|
|
92
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
93
|
+
const p = (input ?? {});
|
|
94
|
+
const qs = {};
|
|
95
|
+
if (p.limit)
|
|
96
|
+
qs.count = p.limit;
|
|
97
|
+
else
|
|
98
|
+
qs.count = 0;
|
|
99
|
+
if (p.sortKey)
|
|
100
|
+
qs.sort_key = p.sortKey;
|
|
101
|
+
if (p.sortDir)
|
|
102
|
+
qs.sort_dir = p.sortDir;
|
|
103
|
+
return api(baseUrl, authToken, "GET", "/services/search/jobs", undefined, qs);
|
|
104
|
+
} });
|
|
105
|
+
rl.registerAction("search.delete", { description: "Delete a search job",
|
|
106
|
+
inputSchema: { searchJobId: { type: "string", required: true } },
|
|
107
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); await api(baseUrl, authToken, "DELETE", `/services/search/jobs/${input.searchJobId}`); return { success: true }; } });
|
|
108
|
+
rl.registerAction("search.getResults", { description: "Get results of a search job",
|
|
109
|
+
inputSchema: { searchJobId: { type: "string", required: true }, limit: { type: "number", required: false }, filterKey: { type: "string", required: false, description: "Filter field name" }, filterValue: { type: "string", required: false, description: "Filter field value" } },
|
|
110
|
+
async execute(input, ctx) {
|
|
111
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
112
|
+
const p = input;
|
|
113
|
+
const qs = {};
|
|
114
|
+
if (p.limit)
|
|
115
|
+
qs.count = p.limit;
|
|
116
|
+
else
|
|
117
|
+
qs.count = 0;
|
|
118
|
+
if (p.filterKey && p.filterValue)
|
|
119
|
+
qs.search = `search ${p.filterKey}=${p.filterValue}`;
|
|
120
|
+
return api(baseUrl, authToken, "GET", `/services/search/jobs/${p.searchJobId}/results`, undefined, qs);
|
|
121
|
+
} });
|
|
122
|
+
// ── Alerts ──────────────────────────────────────────
|
|
123
|
+
rl.registerAction("alert.getMetrics", { description: "Get metric alerts", inputSchema: {},
|
|
124
|
+
async execute(_input, ctx) { const { baseUrl, authToken } = getConn(ctx); return api(baseUrl, authToken, "GET", "/services/alerts/metric_alerts"); } });
|
|
125
|
+
rl.registerAction("alert.getFired", { description: "Get fired alerts report", inputSchema: {},
|
|
126
|
+
async execute(_input, ctx) { const { baseUrl, authToken } = getConn(ctx); return api(baseUrl, authToken, "GET", "/services/alerts/fired_alerts"); } });
|
|
127
|
+
// ── Reports (Saved Searches) ────────────────────────
|
|
128
|
+
rl.registerAction("report.create", { description: "Create a saved search / report from a search job",
|
|
129
|
+
inputSchema: { name: { type: "string", required: true }, search: { type: "string", required: true, description: "SPL query for the report" }, cronSchedule: { type: "string", required: false }, earliestTime: { type: "string", required: false }, latestTime: { type: "string", required: false } },
|
|
130
|
+
async execute(input, ctx) {
|
|
131
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
132
|
+
const p = input;
|
|
133
|
+
const body = { name: p.name, search: p.search, alert_type: "always" };
|
|
134
|
+
if (p.cronSchedule)
|
|
135
|
+
body.cron_schedule = p.cronSchedule;
|
|
136
|
+
if (p.earliestTime)
|
|
137
|
+
body["dispatch.earliest_time"] = p.earliestTime;
|
|
138
|
+
if (p.latestTime)
|
|
139
|
+
body["dispatch.latest_time"] = p.latestTime;
|
|
140
|
+
return api(baseUrl, authToken, "POST", "/services/saved/searches", body);
|
|
141
|
+
} });
|
|
142
|
+
rl.registerAction("report.get", { description: "Get a saved search / report",
|
|
143
|
+
inputSchema: { reportId: { type: "string", required: true } },
|
|
144
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); return api(baseUrl, authToken, "GET", `/services/saved/searches/${input.reportId}`); } });
|
|
145
|
+
rl.registerAction("report.list", { description: "List saved searches / reports",
|
|
146
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
147
|
+
async execute(input, ctx) {
|
|
148
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
149
|
+
const p = (input ?? {});
|
|
150
|
+
const qs = {};
|
|
151
|
+
if (p.limit)
|
|
152
|
+
qs.count = p.limit;
|
|
153
|
+
else
|
|
154
|
+
qs.count = 0;
|
|
155
|
+
return api(baseUrl, authToken, "GET", "/services/saved/searches", undefined, qs);
|
|
156
|
+
} });
|
|
157
|
+
rl.registerAction("report.delete", { description: "Delete a saved search / report",
|
|
158
|
+
inputSchema: { reportId: { type: "string", required: true } },
|
|
159
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); await api(baseUrl, authToken, "DELETE", `/services/saved/searches/${input.reportId}`); return { success: true }; } });
|
|
160
|
+
// ── Users ───────────────────────────────────────────
|
|
161
|
+
rl.registerAction("user.create", { description: "Create a Splunk user",
|
|
162
|
+
inputSchema: { name: { type: "string", required: true, description: "Login name" }, password: { type: "string", required: true }, roles: { type: "object", required: true, description: "Array of role names" }, email: { type: "string", required: false }, realname: { type: "string", required: false, description: "Full name" } },
|
|
163
|
+
async execute(input, ctx) {
|
|
164
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
165
|
+
const p = input;
|
|
166
|
+
const body = { name: p.name, password: p.password, roles: p.roles };
|
|
167
|
+
if (p.email)
|
|
168
|
+
body.email = p.email;
|
|
169
|
+
if (p.realname)
|
|
170
|
+
body.realname = p.realname;
|
|
171
|
+
return api(baseUrl, authToken, "POST", "/services/authentication/users", body);
|
|
172
|
+
} });
|
|
173
|
+
rl.registerAction("user.get", { description: "Get a user",
|
|
174
|
+
inputSchema: { userId: { type: "string", required: true, description: "Username" } },
|
|
175
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); return api(baseUrl, authToken, "GET", `/services/authentication/users/${input.userId}`); } });
|
|
176
|
+
rl.registerAction("user.list", { description: "List users",
|
|
177
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
178
|
+
async execute(input, ctx) {
|
|
179
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
180
|
+
const p = (input ?? {});
|
|
181
|
+
const qs = {};
|
|
182
|
+
if (p.limit)
|
|
183
|
+
qs.count = p.limit;
|
|
184
|
+
else
|
|
185
|
+
qs.count = 0;
|
|
186
|
+
return api(baseUrl, authToken, "GET", "/services/authentication/users", undefined, qs);
|
|
187
|
+
} });
|
|
188
|
+
rl.registerAction("user.update", { description: "Update a user",
|
|
189
|
+
inputSchema: { userId: { type: "string", required: true, description: "Username" }, email: { type: "string", required: false }, realname: { type: "string", required: false }, password: { type: "string", required: false }, roles: { type: "object", required: false, description: "Array of role names" } },
|
|
190
|
+
async execute(input, ctx) {
|
|
191
|
+
const { baseUrl, authToken } = getConn(ctx);
|
|
192
|
+
const { userId, ...fields } = input;
|
|
193
|
+
const body = {};
|
|
194
|
+
if (fields.email)
|
|
195
|
+
body.email = fields.email;
|
|
196
|
+
if (fields.realname)
|
|
197
|
+
body.realname = fields.realname;
|
|
198
|
+
if (fields.password)
|
|
199
|
+
body.password = fields.password;
|
|
200
|
+
if (fields.roles)
|
|
201
|
+
body.roles = fields.roles;
|
|
202
|
+
return api(baseUrl, authToken, "POST", `/services/authentication/users/${userId}`, body);
|
|
203
|
+
} });
|
|
204
|
+
rl.registerAction("user.delete", { description: "Delete a user",
|
|
205
|
+
inputSchema: { userId: { type: "string", required: true, description: "Username" } },
|
|
206
|
+
async execute(input, ctx) { const { baseUrl, authToken } = getConn(ctx); await api(baseUrl, authToken, "DELETE", `/services/authentication/users/${input.userId}`); return { success: true }; } });
|
|
207
|
+
}
|