runline 0.2.1 → 0.3.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/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.js +96 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.js +46 -0
- package/dist/core/engine.js +7 -1
- package/dist/core/oauth.d.ts +46 -0
- package/dist/core/oauth.js +145 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/main.js +28 -0
- package/dist/plugin/api.d.ts +7 -1
- package/dist/plugin/api.js +7 -0
- package/dist/plugin/types.d.ts +47 -0
- package/dist/plugins/actionNetwork/src/index.js +118 -25
- package/dist/plugins/activeCampaign/src/index.js +184 -38
- package/dist/plugins/adalo/src/index.js +40 -8
- package/dist/plugins/affinity/src/index.js +100 -20
- package/dist/plugins/agileCrm/src/index.js +115 -27
- package/dist/plugins/airtable/src/index.js +94 -19
- package/dist/plugins/airtop/src/index.js +266 -62
- package/dist/plugins/apiTemplateIo/src/index.js +25 -5
- package/dist/plugins/asana/src/index.js +195 -41
- package/dist/plugins/autopilot/src/index.js +39 -8
- package/dist/plugins/bambooHr/src/index.js +109 -22
- package/dist/plugins/bannerbear/src/index.js +36 -8
- package/dist/plugins/baserow/src/index.js +35 -7
- package/dist/plugins/beeminder/src/index.js +198 -40
- package/dist/plugins/bitly/src/index.js +46 -10
- package/dist/plugins/bitwarden/src/index.js +167 -36
- package/dist/plugins/box/src/index.js +172 -37
- package/dist/plugins/brandfetch/src/index.js +5 -1
- package/dist/plugins/brevo/src/index.js +136 -29
- package/dist/plugins/bubble/src/index.js +76 -17
- package/dist/plugins/chargebee/src/index.js +35 -7
- package/dist/plugins/circleci/src/index.js +50 -10
- package/dist/plugins/ciscoWebex/src/index.js +131 -27
- package/dist/plugins/clearbit/src/index.js +76 -17
- package/dist/plugins/clickup/src/index.js +500 -107
- package/dist/plugins/clockify/src/index.js +229 -47
- package/dist/plugins/cloudflare/src/index.js +28 -6
- package/dist/plugins/cockpit/src/index.js +54 -12
- package/dist/plugins/coda/src/index.js +81 -19
- package/dist/plugins/coingecko/src/index.js +157 -33
- package/dist/plugins/contentful/src/index.js +85 -17
- package/dist/plugins/convertkit/src/index.js +74 -18
- package/dist/plugins/copper/src/index.js +59 -11
- package/dist/plugins/cortex/src/index.js +55 -13
- package/dist/plugins/currents/src/index.js +310 -71
- package/dist/plugins/customerIo/src/index.js +112 -23
- package/dist/plugins/databricks/src/index.js +549 -115
- package/dist/plugins/deepl/src/index.js +26 -6
- package/dist/plugins/demio/src/index.js +56 -11
- package/dist/plugins/dhl/src/index.js +16 -3
- package/dist/plugins/discord/src/index.js +141 -31
- package/dist/plugins/discourse/src/index.js +136 -31
- package/dist/plugins/disqus/src/index.js +96 -20
- package/dist/plugins/docker/src/index.js +20 -4
- package/dist/plugins/drift/src/index.js +19 -5
- package/dist/plugins/dropbox/src/index.js +139 -30
- package/dist/plugins/dropcontact/src/index.js +21 -4
- package/dist/plugins/egoi/src/index.js +61 -15
- package/dist/plugins/elasticsearch/src/index.js +59 -13
- package/dist/plugins/emelia/src/index.js +95 -19
- package/dist/plugins/erpnext/src/index.js +74 -15
- package/dist/plugins/facebookGraph/src/index.js +52 -11
- package/dist/plugins/freshdesk/src/index.js +220 -48
- package/dist/plugins/freshservice/src/index.js +39 -9
- package/dist/plugins/freshworksCrm/src/index.js +58 -12
- package/dist/plugins/getresponse/src/index.js +87 -18
- package/dist/plugins/ghost/src/index.js +114 -26
- package/dist/plugins/github/src/index.js +483 -109
- package/dist/plugins/gitlab/src/index.js +193 -45
- package/dist/plugins/gmail/src/index.js +1075 -0
- package/dist/plugins/gong/src/index.js +68 -14
- package/dist/plugins/gotify/src/index.js +43 -9
- package/dist/plugins/gotowebinar/src/index.js +233 -47
- package/dist/plugins/grafana/src/index.js +92 -21
- package/dist/plugins/graphql/src/index.js +38 -8
- package/dist/plugins/grist/src/index.js +52 -10
- package/dist/plugins/hackernews/src/index.js +32 -6
- package/dist/plugins/halopsa/src/index.js +131 -26
- package/dist/plugins/harvest/src/index.js +182 -42
- package/dist/plugins/helpscout/src/index.js +153 -31
- package/dist/plugins/highlevel/src/index.js +291 -58
- package/dist/plugins/homeAssistant/src/index.js +124 -26
- package/dist/plugins/hubspot/src/index.js +163 -29
- package/dist/plugins/humanticAi/src/index.js +54 -5
- package/dist/plugins/hunter/src/index.js +21 -4
- package/dist/plugins/intercom/src/index.js +95 -20
- package/dist/plugins/iterable/src/index.js +96 -20
- package/dist/plugins/jenkins/src/index.js +75 -17
- package/dist/plugins/jira/src/index.js +193 -43
- package/dist/plugins/keap/src/index.js +222 -56
- package/dist/plugins/kobotoolbox/src/index.js +113 -25
- package/dist/plugins/lemlist/src/index.js +79 -18
- package/dist/plugins/linear/src/index.js +86 -19
- package/dist/plugins/lingvanex/src/index.js +38 -8
- package/dist/plugins/linkedin/src/index.js +37 -8
- package/dist/plugins/lonescale/src/index.js +41 -9
- package/dist/plugins/magento/src/index.js +98 -27
- package/dist/plugins/mailcheck/src/index.js +11 -2
- package/dist/plugins/mailchimp/src/index.js +193 -42
- package/dist/plugins/mailerlite/src/index.js +61 -12
- package/dist/plugins/mailgun/src/index.js +39 -7
- package/dist/plugins/mailjet/src/index.js +141 -30
- package/dist/plugins/mandrill/src/index.js +67 -14
- package/dist/plugins/marketstack/src/index.js +56 -10
- package/dist/plugins/matrix/src/index.js +97 -20
- package/dist/plugins/mattermost/src/index.js +124 -26
- package/dist/plugins/mautic/src/index.js +129 -26
- package/dist/plugins/medium/src/index.js +64 -13
- package/dist/plugins/messagebird/src/index.js +80 -15
- package/dist/plugins/metabase/src/index.js +57 -12
- package/dist/plugins/misp/src/index.js +135 -33
- package/dist/plugins/mocean/src/index.js +33 -7
- package/dist/plugins/monday/src/index.js +97 -23
- package/dist/plugins/monicaCrm/src/index.js +112 -23
- package/dist/plugins/msg91/src/index.js +11 -2
- package/dist/plugins/nasa/src/index.js +108 -21
- package/dist/plugins/netlify/src/index.js +28 -6
- package/dist/plugins/netscalerAdc/src/index.js +144 -29
- package/dist/plugins/nextcloud/src/index.js +103 -20
- package/dist/plugins/nocodb/src/index.js +57 -11
- package/dist/plugins/notion/src/index.js +148 -37
- package/dist/plugins/npm/src/index.js +59 -12
- package/dist/plugins/odoo/src/index.js +102 -20
- package/dist/plugins/okta/src/index.js +50 -10
- package/dist/plugins/oneSimpleApi/src/index.js +84 -17
- package/dist/plugins/onfleet/src/index.js +139 -32
- package/dist/plugins/openThesaurus/src/index.js +46 -9
- package/dist/plugins/openweathermap/src/index.js +31 -6
- package/dist/plugins/oura/src/index.js +36 -7
- package/dist/plugins/paddle/src/index.js +80 -17
- package/dist/plugins/pagerduty/src/index.js +53 -12
- package/dist/plugins/paypal/src/index.js +51 -11
- package/dist/plugins/peekalink/src/index.js +12 -3
- package/dist/plugins/phantombuster/src/index.js +39 -8
- package/dist/plugins/philipsHue/src/index.js +64 -13
- package/dist/plugins/pipedrive/src/index.js +167 -45
- package/dist/plugins/plivo/src/index.js +43 -8
- package/dist/plugins/postbin/src/index.js +9 -2
- package/dist/plugins/posthog/src/index.js +50 -13
- package/dist/plugins/profitwell/src/index.js +24 -5
- package/dist/plugins/pushbullet/src/index.js +45 -9
- package/dist/plugins/pushcut/src/index.js +31 -6
- package/dist/plugins/pushover/src/index.js +51 -10
- package/dist/plugins/quickbase/src/index.js +66 -13
- package/dist/plugins/quickbooks/src/index.js +86 -19
- package/dist/plugins/quickchart/src/index.js +35 -7
- package/dist/plugins/raindrop/src/index.js +54 -13
- package/dist/plugins/reddit/src/index.js +73 -18
- package/dist/plugins/rocketchat/src/index.js +47 -9
- package/dist/plugins/rundeck/src/index.js +26 -5
- package/dist/plugins/salesforce/src/index.js +161 -31
- package/dist/plugins/salesmate/src/index.js +75 -16
- package/dist/plugins/securityScorecard/src/index.js +73 -15
- package/dist/plugins/segment/src/index.js +21 -4
- package/dist/plugins/sendgrid/src/index.js +102 -24
- package/dist/plugins/sendy/src/index.js +54 -11
- package/dist/plugins/sentry/src/index.js +174 -34
- package/dist/plugins/servicenow/src/index.js +120 -27
- package/dist/plugins/shopify/src/index.js +53 -12
- package/dist/plugins/signl4/src/index.js +16 -3
- package/dist/plugins/slack/src/index.js +407 -105
- package/dist/plugins/sms77/src/index.js +26 -5
- package/dist/plugins/splunk/src/index.js +186 -45
- package/dist/plugins/spotify/src/index.js +265 -66
- package/dist/plugins/stackby/src/index.js +18 -6
- package/dist/plugins/storyblok/src/index.js +57 -11
- package/dist/plugins/strapi/src/index.js +63 -12
- package/dist/plugins/strava/src/index.js +58 -13
- package/dist/plugins/stripe/src/index.js +143 -30
- package/dist/plugins/supabase/src/index.js +49 -10
- package/dist/plugins/syncromsp/src/index.js +245 -67
- package/dist/plugins/tapfiliate/src/index.js +57 -14
- package/dist/plugins/telegram/src/index.js +202 -39
- package/dist/plugins/thehive/src/index.js +271 -66
- package/dist/plugins/thehiveProject/src/index.js +457 -89
- package/dist/plugins/todoist/src/index.js +326 -77
- package/dist/plugins/travisci/src/index.js +35 -8
- package/dist/plugins/trello/src/index.js +204 -46
- package/dist/plugins/twake/src/index.js +10 -2
- package/dist/plugins/twilio/src/index.js +56 -11
- package/dist/plugins/twist/src/index.js +241 -48
- package/dist/plugins/twitter/src/index.js +128 -30
- package/dist/plugins/unleashedSoftware/src/index.js +30 -6
- package/dist/plugins/uplead/src/index.js +9 -2
- package/dist/plugins/uproc/src/index.js +31 -6
- package/dist/plugins/uptimerobot/src/index.js +119 -25
- package/dist/plugins/urlscanio/src/index.js +25 -6
- package/dist/plugins/vero/src/index.js +68 -13
- package/dist/plugins/vonage/src/index.js +32 -6
- package/dist/plugins/wekan/src/index.js +297 -52
- package/dist/plugins/woocommerce/src/index.js +57 -12
- package/dist/plugins/wordpress/src/index.js +94 -18
- package/dist/plugins/xero/src/index.js +79 -13
- package/dist/plugins/yourls/src/index.js +33 -6
- package/dist/plugins/zammad/src/index.js +139 -36
- package/dist/plugins/zendesk/src/index.js +201 -48
- package/dist/plugins/zoho/src/index.js +88 -21
- package/dist/plugins/zoom/src/index.js +41 -7
- package/dist/plugins/zulip/src/index.js +101 -20
- package/package.json +3 -1
|
@@ -7,7 +7,13 @@ async function api(token, method, endpoint, body, qs) {
|
|
|
7
7
|
url.searchParams.set(k, String(v));
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
const init = {
|
|
10
|
+
const init = {
|
|
11
|
+
method,
|
|
12
|
+
headers: {
|
|
13
|
+
Authorization: `Bearer ${token}`,
|
|
14
|
+
"Content-Type": "application/json",
|
|
15
|
+
},
|
|
16
|
+
};
|
|
11
17
|
if (body && Object.keys(body).length > 0)
|
|
12
18
|
init.body = JSON.stringify(body);
|
|
13
19
|
const res = await fetch(url.toString(), init);
|
|
@@ -18,41 +24,119 @@ async function api(token, method, endpoint, body, qs) {
|
|
|
18
24
|
const text = await res.text();
|
|
19
25
|
return text ? JSON.parse(text) : { success: true };
|
|
20
26
|
}
|
|
21
|
-
function stripUri(uri, prefix) {
|
|
27
|
+
function stripUri(uri, prefix) {
|
|
28
|
+
return uri.replace(prefix, "");
|
|
29
|
+
}
|
|
22
30
|
export default function spotify(rl) {
|
|
23
31
|
rl.setName("spotify");
|
|
24
32
|
rl.setVersion("0.1.0");
|
|
25
|
-
rl.setConnectionSchema({
|
|
33
|
+
rl.setConnectionSchema({
|
|
34
|
+
accessToken: {
|
|
35
|
+
type: "string",
|
|
36
|
+
required: true,
|
|
37
|
+
description: "Spotify OAuth2 access token",
|
|
38
|
+
env: "SPOTIFY_ACCESS_TOKEN",
|
|
39
|
+
},
|
|
40
|
+
});
|
|
26
41
|
const t = (ctx) => ctx.connection.config.accessToken;
|
|
27
42
|
// ── Player ──────────────────────────────────────────
|
|
28
|
-
rl.registerAction("player.pause", {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
async execute(_i, ctx) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
rl.registerAction("player.pause", {
|
|
44
|
+
description: "Pause playback",
|
|
45
|
+
inputSchema: {},
|
|
46
|
+
async execute(_i, ctx) {
|
|
47
|
+
return api(t(ctx), "PUT", "/me/player/pause");
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
rl.registerAction("player.resume", {
|
|
51
|
+
description: "Resume playback",
|
|
52
|
+
inputSchema: {},
|
|
53
|
+
async execute(_i, ctx) {
|
|
54
|
+
return api(t(ctx), "PUT", "/me/player/play");
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
rl.registerAction("player.next", {
|
|
58
|
+
description: "Skip to next track",
|
|
59
|
+
inputSchema: {},
|
|
60
|
+
async execute(_i, ctx) {
|
|
61
|
+
return api(t(ctx), "POST", "/me/player/next");
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
rl.registerAction("player.previous", {
|
|
65
|
+
description: "Skip to previous track",
|
|
66
|
+
inputSchema: {},
|
|
67
|
+
async execute(_i, ctx) {
|
|
68
|
+
return api(t(ctx), "POST", "/me/player/previous");
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
rl.registerAction("player.currentlyPlaying", {
|
|
72
|
+
description: "Get currently playing track",
|
|
73
|
+
inputSchema: {},
|
|
74
|
+
async execute(_i, ctx) {
|
|
75
|
+
return api(t(ctx), "GET", "/me/player/currently-playing");
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
rl.registerAction("player.recentlyPlayed", {
|
|
79
|
+
description: "Get recently played tracks",
|
|
80
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
39
81
|
async execute(input, ctx) {
|
|
40
82
|
const qs = {};
|
|
41
83
|
if (input?.limit)
|
|
42
84
|
qs.limit = input.limit;
|
|
43
85
|
const data = (await api(t(ctx), "GET", "/me/player/recently-played", undefined, qs));
|
|
44
86
|
return data.items;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
rl.registerAction("player.addToQueue", {
|
|
90
|
+
description: "Add a track to the queue",
|
|
91
|
+
inputSchema: {
|
|
92
|
+
uri: { type: "string", required: true, description: "Track URI or ID" },
|
|
93
|
+
},
|
|
94
|
+
async execute(input, ctx) {
|
|
95
|
+
return api(t(ctx), "POST", "/me/player/queue", undefined, {
|
|
96
|
+
uri: input.uri,
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
rl.registerAction("player.setVolume", {
|
|
101
|
+
description: "Set playback volume",
|
|
102
|
+
inputSchema: {
|
|
103
|
+
volumePercent: { type: "number", required: true, description: "0-100" },
|
|
104
|
+
},
|
|
105
|
+
async execute(input, ctx) {
|
|
106
|
+
return api(t(ctx), "PUT", "/me/player/volume", undefined, {
|
|
107
|
+
volume_percent: input.volumePercent,
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
rl.registerAction("player.startMusic", {
|
|
112
|
+
description: "Start playing an album, artist, or playlist",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
contextUri: {
|
|
115
|
+
type: "string",
|
|
116
|
+
required: true,
|
|
117
|
+
description: "Spotify URI (e.g. spotify:album:...)",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
async execute(input, ctx) {
|
|
121
|
+
return api(t(ctx), "PUT", "/me/player/play", {
|
|
122
|
+
context_uri: input.contextUri,
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
});
|
|
52
126
|
// ── Album ───────────────────────────────────────────
|
|
53
|
-
rl.registerAction("album.get", {
|
|
54
|
-
|
|
55
|
-
|
|
127
|
+
rl.registerAction("album.get", {
|
|
128
|
+
description: "Get an album",
|
|
129
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
130
|
+
async execute(input, ctx) {
|
|
131
|
+
return api(t(ctx), "GET", `/albums/${stripUri(input.id, "spotify:album:")}`);
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
rl.registerAction("album.getTracks", {
|
|
135
|
+
description: "Get an album's tracks",
|
|
136
|
+
inputSchema: {
|
|
137
|
+
id: { type: "string", required: true },
|
|
138
|
+
limit: { type: "number", required: false },
|
|
139
|
+
},
|
|
56
140
|
async execute(input, ctx) {
|
|
57
141
|
const p = input;
|
|
58
142
|
const qs = {};
|
|
@@ -60,8 +144,14 @@ export default function spotify(rl) {
|
|
|
60
144
|
qs.limit = p.limit;
|
|
61
145
|
const data = (await api(t(ctx), "GET", `/albums/${stripUri(p.id, "spotify:album:")}/tracks`, undefined, qs));
|
|
62
146
|
return data.items;
|
|
63
|
-
}
|
|
64
|
-
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
rl.registerAction("album.getNewReleases", {
|
|
150
|
+
description: "Get new album releases",
|
|
151
|
+
inputSchema: {
|
|
152
|
+
limit: { type: "number", required: false },
|
|
153
|
+
country: { type: "string", required: false },
|
|
154
|
+
},
|
|
65
155
|
async execute(input, ctx) {
|
|
66
156
|
const p = (input ?? {});
|
|
67
157
|
const qs = {};
|
|
@@ -71,8 +161,14 @@ export default function spotify(rl) {
|
|
|
71
161
|
qs.country = p.country;
|
|
72
162
|
const data = (await api(t(ctx), "GET", "/browse/new-releases", undefined, qs));
|
|
73
163
|
return data.albums.items;
|
|
74
|
-
}
|
|
75
|
-
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
rl.registerAction("album.search", {
|
|
167
|
+
description: "Search albums",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
query: { type: "string", required: true },
|
|
170
|
+
limit: { type: "number", required: false },
|
|
171
|
+
},
|
|
76
172
|
async execute(input, ctx) {
|
|
77
173
|
const p = input;
|
|
78
174
|
const qs = { q: p.query, type: "album" };
|
|
@@ -82,11 +178,22 @@ export default function spotify(rl) {
|
|
|
82
178
|
qs.limit = 50;
|
|
83
179
|
const data = (await api(t(ctx), "GET", "/search", undefined, qs));
|
|
84
180
|
return data.albums.items;
|
|
85
|
-
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
86
183
|
// ── Artist ──────────────────────────────────────────
|
|
87
|
-
rl.registerAction("artist.get", {
|
|
88
|
-
|
|
89
|
-
|
|
184
|
+
rl.registerAction("artist.get", {
|
|
185
|
+
description: "Get an artist",
|
|
186
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
187
|
+
async execute(input, ctx) {
|
|
188
|
+
return api(t(ctx), "GET", `/artists/${stripUri(input.id, "spotify:artist:")}`);
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
rl.registerAction("artist.getAlbums", {
|
|
192
|
+
description: "Get an artist's albums",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
id: { type: "string", required: true },
|
|
195
|
+
limit: { type: "number", required: false },
|
|
196
|
+
},
|
|
90
197
|
async execute(input, ctx) {
|
|
91
198
|
const p = input;
|
|
92
199
|
const qs = {};
|
|
@@ -94,29 +201,59 @@ export default function spotify(rl) {
|
|
|
94
201
|
qs.limit = p.limit;
|
|
95
202
|
const data = (await api(t(ctx), "GET", `/artists/${stripUri(p.id, "spotify:artist:")}/albums`, undefined, qs));
|
|
96
203
|
return data.items;
|
|
97
|
-
}
|
|
98
|
-
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
rl.registerAction("artist.getRelatedArtists", {
|
|
207
|
+
description: "Get related artists",
|
|
208
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
99
209
|
async execute(input, ctx) {
|
|
100
210
|
const data = (await api(t(ctx), "GET", `/artists/${stripUri(input.id, "spotify:artist:")}/related-artists`));
|
|
101
211
|
return data.artists;
|
|
102
|
-
}
|
|
103
|
-
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
rl.registerAction("artist.getTopTracks", {
|
|
215
|
+
description: "Get an artist's top tracks",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
id: { type: "string", required: true },
|
|
218
|
+
country: { type: "string", required: true },
|
|
219
|
+
},
|
|
104
220
|
async execute(input, ctx) {
|
|
105
221
|
const p = input;
|
|
106
222
|
const data = (await api(t(ctx), "GET", `/artists/${stripUri(p.id, "spotify:artist:")}/top-tracks`, undefined, { country: p.country }));
|
|
107
223
|
return data.tracks;
|
|
108
|
-
}
|
|
109
|
-
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
rl.registerAction("artist.search", {
|
|
227
|
+
description: "Search artists",
|
|
228
|
+
inputSchema: {
|
|
229
|
+
query: { type: "string", required: true },
|
|
230
|
+
limit: { type: "number", required: false },
|
|
231
|
+
},
|
|
110
232
|
async execute(input, ctx) {
|
|
111
233
|
const p = input;
|
|
112
|
-
const qs = {
|
|
234
|
+
const qs = {
|
|
235
|
+
q: p.query,
|
|
236
|
+
type: "artist",
|
|
237
|
+
limit: p.limit ?? 50,
|
|
238
|
+
};
|
|
113
239
|
const data = (await api(t(ctx), "GET", "/search", undefined, qs));
|
|
114
240
|
return data.artists.items;
|
|
115
|
-
}
|
|
241
|
+
},
|
|
242
|
+
});
|
|
116
243
|
// ── Playlist ────────────────────────────────────────
|
|
117
|
-
rl.registerAction("playlist.get", {
|
|
118
|
-
|
|
119
|
-
|
|
244
|
+
rl.registerAction("playlist.get", {
|
|
245
|
+
description: "Get a playlist",
|
|
246
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
247
|
+
async execute(input, ctx) {
|
|
248
|
+
return api(t(ctx), "GET", `/playlists/${stripUri(input.id, "spotify:playlist:")}`);
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
rl.registerAction("playlist.getTracks", {
|
|
252
|
+
description: "Get a playlist's tracks",
|
|
253
|
+
inputSchema: {
|
|
254
|
+
id: { type: "string", required: true },
|
|
255
|
+
limit: { type: "number", required: false },
|
|
256
|
+
},
|
|
120
257
|
async execute(input, ctx) {
|
|
121
258
|
const p = input;
|
|
122
259
|
const qs = {};
|
|
@@ -124,65 +261,127 @@ export default function spotify(rl) {
|
|
|
124
261
|
qs.limit = p.limit;
|
|
125
262
|
const data = (await api(t(ctx), "GET", `/playlists/${stripUri(p.id, "spotify:playlist:")}/tracks`, undefined, qs));
|
|
126
263
|
return data.items;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
rl.registerAction("playlist.create", {
|
|
267
|
+
description: "Create a playlist",
|
|
268
|
+
inputSchema: {
|
|
269
|
+
name: { type: "string", required: true },
|
|
270
|
+
description: { type: "string", required: false },
|
|
271
|
+
public: { type: "boolean", required: false },
|
|
272
|
+
},
|
|
273
|
+
async execute(input, ctx) {
|
|
274
|
+
return api(t(ctx), "POST", "/me/playlists", input);
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
rl.registerAction("playlist.addTrack", {
|
|
278
|
+
description: "Add a track to a playlist",
|
|
279
|
+
inputSchema: {
|
|
280
|
+
id: { type: "string", required: true },
|
|
281
|
+
trackUri: { type: "string", required: true },
|
|
282
|
+
position: { type: "number", required: false },
|
|
283
|
+
},
|
|
131
284
|
async execute(input, ctx) {
|
|
132
285
|
const p = input;
|
|
133
286
|
const qs = { uris: p.trackUri };
|
|
134
287
|
if (p.position !== undefined)
|
|
135
288
|
qs.position = p.position;
|
|
136
289
|
return api(t(ctx), "POST", `/playlists/${stripUri(p.id, "spotify:playlist:")}/tracks`, {}, qs);
|
|
137
|
-
}
|
|
138
|
-
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
rl.registerAction("playlist.removeTrack", {
|
|
293
|
+
description: "Remove a track from a playlist",
|
|
294
|
+
inputSchema: {
|
|
295
|
+
id: { type: "string", required: true },
|
|
296
|
+
trackUri: { type: "string", required: true },
|
|
297
|
+
},
|
|
139
298
|
async execute(input, ctx) {
|
|
140
299
|
const p = input;
|
|
141
300
|
return api(t(ctx), "DELETE", `/playlists/${stripUri(p.id, "spotify:playlist:")}/tracks`, { tracks: [{ uri: p.trackUri }] });
|
|
142
|
-
}
|
|
143
|
-
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
rl.registerAction("playlist.listMine", {
|
|
304
|
+
description: "Get the current user's playlists",
|
|
305
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
144
306
|
async execute(input, ctx) {
|
|
145
307
|
const qs = {};
|
|
146
308
|
if (input?.limit)
|
|
147
309
|
qs.limit = input.limit;
|
|
148
310
|
const data = (await api(t(ctx), "GET", "/me/playlists", undefined, qs));
|
|
149
311
|
return data.items;
|
|
150
|
-
}
|
|
151
|
-
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
rl.registerAction("playlist.search", {
|
|
315
|
+
description: "Search playlists",
|
|
316
|
+
inputSchema: {
|
|
317
|
+
query: { type: "string", required: true },
|
|
318
|
+
limit: { type: "number", required: false },
|
|
319
|
+
},
|
|
152
320
|
async execute(input, ctx) {
|
|
153
321
|
const p = input;
|
|
154
|
-
const qs = {
|
|
322
|
+
const qs = {
|
|
323
|
+
q: p.query,
|
|
324
|
+
type: "playlist",
|
|
325
|
+
limit: p.limit ?? 50,
|
|
326
|
+
};
|
|
155
327
|
const data = (await api(t(ctx), "GET", "/search", undefined, qs));
|
|
156
328
|
return data.playlists.items;
|
|
157
|
-
}
|
|
329
|
+
},
|
|
330
|
+
});
|
|
158
331
|
// ── Track ───────────────────────────────────────────
|
|
159
|
-
rl.registerAction("track.get", {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
async execute(input, ctx) {
|
|
163
|
-
|
|
332
|
+
rl.registerAction("track.get", {
|
|
333
|
+
description: "Get a track",
|
|
334
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
335
|
+
async execute(input, ctx) {
|
|
336
|
+
return api(t(ctx), "GET", `/tracks/${stripUri(input.id, "spotify:track:")}`);
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
rl.registerAction("track.getAudioFeatures", {
|
|
340
|
+
description: "Get audio features for a track",
|
|
341
|
+
inputSchema: { id: { type: "string", required: true } },
|
|
342
|
+
async execute(input, ctx) {
|
|
343
|
+
return api(t(ctx), "GET", `/audio-features/${stripUri(input.id, "spotify:track:")}`);
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
rl.registerAction("track.search", {
|
|
347
|
+
description: "Search tracks",
|
|
348
|
+
inputSchema: {
|
|
349
|
+
query: { type: "string", required: true },
|
|
350
|
+
limit: { type: "number", required: false },
|
|
351
|
+
},
|
|
164
352
|
async execute(input, ctx) {
|
|
165
353
|
const p = input;
|
|
166
|
-
const qs = {
|
|
354
|
+
const qs = {
|
|
355
|
+
q: p.query,
|
|
356
|
+
type: "track",
|
|
357
|
+
limit: p.limit ?? 50,
|
|
358
|
+
};
|
|
167
359
|
const data = (await api(t(ctx), "GET", "/search", undefined, qs));
|
|
168
360
|
return data.tracks.items;
|
|
169
|
-
}
|
|
361
|
+
},
|
|
362
|
+
});
|
|
170
363
|
// ── Library ─────────────────────────────────────────
|
|
171
|
-
rl.registerAction("library.getLikedTracks", {
|
|
364
|
+
rl.registerAction("library.getLikedTracks", {
|
|
365
|
+
description: "Get liked tracks",
|
|
366
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
172
367
|
async execute(input, ctx) {
|
|
173
368
|
const qs = {};
|
|
174
369
|
if (input?.limit)
|
|
175
370
|
qs.limit = input.limit;
|
|
176
371
|
const data = (await api(t(ctx), "GET", "/me/tracks", undefined, qs));
|
|
177
372
|
return data.items;
|
|
178
|
-
}
|
|
373
|
+
},
|
|
374
|
+
});
|
|
179
375
|
// ── My Data ─────────────────────────────────────────
|
|
180
|
-
rl.registerAction("myData.getFollowingArtists", {
|
|
376
|
+
rl.registerAction("myData.getFollowingArtists", {
|
|
377
|
+
description: "Get followed artists",
|
|
378
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
181
379
|
async execute(input, ctx) {
|
|
182
380
|
const qs = { type: "artist" };
|
|
183
381
|
if (input?.limit)
|
|
184
382
|
qs.limit = input.limit;
|
|
185
383
|
const data = (await api(t(ctx), "GET", "/me/following", undefined, qs));
|
|
186
384
|
return data.artists.items;
|
|
187
|
-
}
|
|
385
|
+
},
|
|
386
|
+
});
|
|
188
387
|
}
|
|
@@ -7,7 +7,10 @@ async function apiRequest(apiKey, method, endpoint, body, qs) {
|
|
|
7
7
|
url.searchParams.set(k, String(v));
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
const init = {
|
|
10
|
+
const init = {
|
|
11
|
+
method,
|
|
12
|
+
headers: { "api-key": apiKey, "Content-Type": "application/json" },
|
|
13
|
+
};
|
|
11
14
|
if (body !== undefined)
|
|
12
15
|
init.body = JSON.stringify(body);
|
|
13
16
|
const res = await fetch(url.toString(), init);
|
|
@@ -19,7 +22,12 @@ export default function stackby(rl) {
|
|
|
19
22
|
rl.setName("stackby");
|
|
20
23
|
rl.setVersion("0.1.0");
|
|
21
24
|
rl.setConnectionSchema({
|
|
22
|
-
apiKey: {
|
|
25
|
+
apiKey: {
|
|
26
|
+
type: "string",
|
|
27
|
+
required: true,
|
|
28
|
+
description: "Stackby API key",
|
|
29
|
+
env: "STACKBY_API_KEY",
|
|
30
|
+
},
|
|
23
31
|
});
|
|
24
32
|
const key = (ctx) => ctx.connection.config.apiKey;
|
|
25
33
|
rl.registerAction("row.read", {
|
|
@@ -32,7 +40,7 @@ export default function stackby(rl) {
|
|
|
32
40
|
async execute(input, ctx) {
|
|
33
41
|
const p = input;
|
|
34
42
|
const data = (await apiRequest(key(ctx), "GET", `/rowlist/${p.stackId}/${encodeURIComponent(p.table)}`, undefined, { rowIds: p.rowId }));
|
|
35
|
-
return data.map(d => d.field);
|
|
43
|
+
return data.map((d) => d.field);
|
|
36
44
|
},
|
|
37
45
|
});
|
|
38
46
|
rl.registerAction("row.list", {
|
|
@@ -51,7 +59,7 @@ export default function stackby(rl) {
|
|
|
51
59
|
if (p.limit)
|
|
52
60
|
qs.maxrecord = p.limit;
|
|
53
61
|
const data = (await apiRequest(key(ctx), "GET", `/rowlist/${p.stackId}/${encodeURIComponent(p.table)}`, undefined, qs));
|
|
54
|
-
return data.map(d => d.field);
|
|
62
|
+
return data.map((d) => d.field);
|
|
55
63
|
},
|
|
56
64
|
});
|
|
57
65
|
rl.registerAction("row.append", {
|
|
@@ -59,12 +67,16 @@ export default function stackby(rl) {
|
|
|
59
67
|
inputSchema: {
|
|
60
68
|
stackId: { type: "string", required: true },
|
|
61
69
|
table: { type: "string", required: true },
|
|
62
|
-
records: {
|
|
70
|
+
records: {
|
|
71
|
+
type: "object",
|
|
72
|
+
required: true,
|
|
73
|
+
description: "Array of objects [{field: {col1: val1, col2: val2}}]",
|
|
74
|
+
},
|
|
63
75
|
},
|
|
64
76
|
async execute(input, ctx) {
|
|
65
77
|
const p = input;
|
|
66
78
|
const data = (await apiRequest(key(ctx), "POST", `/rowcreate/${p.stackId}/${encodeURIComponent(p.table)}`, { records: p.records }));
|
|
67
|
-
return data.map(d => d.field);
|
|
79
|
+
return data.map((d) => d.field);
|
|
68
80
|
},
|
|
69
81
|
});
|
|
70
82
|
rl.registerAction("row.delete", {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
function getConn(ctx) {
|
|
2
2
|
const c = ctx.connection.config;
|
|
3
|
-
return {
|
|
3
|
+
return {
|
|
4
|
+
contentToken: c.contentToken,
|
|
5
|
+
managementToken: c.managementToken,
|
|
6
|
+
};
|
|
4
7
|
}
|
|
5
8
|
async function contentApi(token, endpoint, qs) {
|
|
6
9
|
const url = new URL(`https://api.storyblok.com${endpoint}`);
|
|
@@ -24,7 +27,10 @@ async function managementApi(token, method, endpoint, body, qs) {
|
|
|
24
27
|
url.searchParams.set(k, String(v));
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
|
-
const init = {
|
|
30
|
+
const init = {
|
|
31
|
+
method,
|
|
32
|
+
headers: { Authorization: token, "Content-Type": "application/json" },
|
|
33
|
+
};
|
|
28
34
|
if (body && Object.keys(body).length > 0)
|
|
29
35
|
init.body = JSON.stringify(body);
|
|
30
36
|
const res = await fetch(url.toString(), init);
|
|
@@ -37,13 +43,29 @@ export default function storyblok(rl) {
|
|
|
37
43
|
rl.setName("storyblok");
|
|
38
44
|
rl.setVersion("0.1.0");
|
|
39
45
|
rl.setConnectionSchema({
|
|
40
|
-
contentToken: {
|
|
41
|
-
|
|
46
|
+
contentToken: {
|
|
47
|
+
type: "string",
|
|
48
|
+
required: false,
|
|
49
|
+
description: "Storyblok Content Delivery API token (for reading published content)",
|
|
50
|
+
env: "STORYBLOK_CONTENT_TOKEN",
|
|
51
|
+
},
|
|
52
|
+
managementToken: {
|
|
53
|
+
type: "string",
|
|
54
|
+
required: false,
|
|
55
|
+
description: "Storyblok Management API personal access token",
|
|
56
|
+
env: "STORYBLOK_MANAGEMENT_TOKEN",
|
|
57
|
+
},
|
|
42
58
|
});
|
|
43
59
|
// ── Content API ─────────────────────────────────────
|
|
44
60
|
rl.registerAction("content.story.get", {
|
|
45
61
|
description: "Get a published story by slug or ID (Content API)",
|
|
46
|
-
inputSchema: {
|
|
62
|
+
inputSchema: {
|
|
63
|
+
identifier: {
|
|
64
|
+
type: "string",
|
|
65
|
+
required: true,
|
|
66
|
+
description: "Story slug or numeric ID",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
47
69
|
async execute(input, ctx) {
|
|
48
70
|
const conn = getConn(ctx);
|
|
49
71
|
if (!conn.contentToken)
|
|
@@ -54,7 +76,14 @@ export default function storyblok(rl) {
|
|
|
54
76
|
});
|
|
55
77
|
rl.registerAction("content.story.list", {
|
|
56
78
|
description: "List published stories (Content API)",
|
|
57
|
-
inputSchema: {
|
|
79
|
+
inputSchema: {
|
|
80
|
+
limit: { type: "number", required: false },
|
|
81
|
+
startsWith: {
|
|
82
|
+
type: "string",
|
|
83
|
+
required: false,
|
|
84
|
+
description: "Filter by slug prefix",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
58
87
|
async execute(input, ctx) {
|
|
59
88
|
const conn = getConn(ctx);
|
|
60
89
|
if (!conn.contentToken)
|
|
@@ -72,7 +101,10 @@ export default function storyblok(rl) {
|
|
|
72
101
|
// ── Management API ──────────────────────────────────
|
|
73
102
|
rl.registerAction("management.story.get", {
|
|
74
103
|
description: "Get a story by ID (Management API)",
|
|
75
|
-
inputSchema: {
|
|
104
|
+
inputSchema: {
|
|
105
|
+
spaceId: { type: "string", required: true },
|
|
106
|
+
storyId: { type: "string", required: true },
|
|
107
|
+
},
|
|
76
108
|
async execute(input, ctx) {
|
|
77
109
|
const conn = getConn(ctx);
|
|
78
110
|
if (!conn.managementToken)
|
|
@@ -84,7 +116,10 @@ export default function storyblok(rl) {
|
|
|
84
116
|
});
|
|
85
117
|
rl.registerAction("management.story.list", {
|
|
86
118
|
description: "List stories in a space (Management API)",
|
|
87
|
-
inputSchema: {
|
|
119
|
+
inputSchema: {
|
|
120
|
+
spaceId: { type: "string", required: true },
|
|
121
|
+
limit: { type: "number", required: false },
|
|
122
|
+
},
|
|
88
123
|
async execute(input, ctx) {
|
|
89
124
|
const conn = getConn(ctx);
|
|
90
125
|
if (!conn.managementToken)
|
|
@@ -99,7 +134,10 @@ export default function storyblok(rl) {
|
|
|
99
134
|
});
|
|
100
135
|
rl.registerAction("management.story.delete", {
|
|
101
136
|
description: "Delete a story (Management API)",
|
|
102
|
-
inputSchema: {
|
|
137
|
+
inputSchema: {
|
|
138
|
+
spaceId: { type: "string", required: true },
|
|
139
|
+
storyId: { type: "string", required: true },
|
|
140
|
+
},
|
|
103
141
|
async execute(input, ctx) {
|
|
104
142
|
const conn = getConn(ctx);
|
|
105
143
|
if (!conn.managementToken)
|
|
@@ -111,7 +149,12 @@ export default function storyblok(rl) {
|
|
|
111
149
|
});
|
|
112
150
|
rl.registerAction("management.story.publish", {
|
|
113
151
|
description: "Publish a story (Management API)",
|
|
114
|
-
inputSchema: {
|
|
152
|
+
inputSchema: {
|
|
153
|
+
spaceId: { type: "string", required: true },
|
|
154
|
+
storyId: { type: "string", required: true },
|
|
155
|
+
releaseId: { type: "string", required: false },
|
|
156
|
+
language: { type: "string", required: false },
|
|
157
|
+
},
|
|
115
158
|
async execute(input, ctx) {
|
|
116
159
|
const conn = getConn(ctx);
|
|
117
160
|
if (!conn.managementToken)
|
|
@@ -128,7 +171,10 @@ export default function storyblok(rl) {
|
|
|
128
171
|
});
|
|
129
172
|
rl.registerAction("management.story.unpublish", {
|
|
130
173
|
description: "Unpublish a story (Management API)",
|
|
131
|
-
inputSchema: {
|
|
174
|
+
inputSchema: {
|
|
175
|
+
spaceId: { type: "string", required: true },
|
|
176
|
+
storyId: { type: "string", required: true },
|
|
177
|
+
},
|
|
132
178
|
async execute(input, ctx) {
|
|
133
179
|
const conn = getConn(ctx);
|
|
134
180
|
if (!conn.managementToken)
|