n8n-nodes-upload-post 0.6.0 → 0.7.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/README.md +34 -4
- package/dist/nodes/UploadPost/NetworkOperations.d.ts +14 -0
- package/dist/nodes/UploadPost/NetworkOperations.js +1322 -0
- package/dist/nodes/UploadPost/NetworkOperations.js.map +1 -0
- package/dist/nodes/UploadPost/UploadPost.node.js +117 -14
- package/dist/nodes/UploadPost/UploadPost.node.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildNetworkRequest = exports.networkProperties = exports.uploadExtraProperties = exports.applyNetworkUploadOptions = exports.NETWORK_RESOURCES = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
exports.NETWORK_RESOURCES = ['queue', 'telegram', 'bluesky', 'googleBusiness'];
|
|
6
|
+
const MANUAL_PLATFORM_VALUE = '__manual_platform__';
|
|
7
|
+
const param = (ctx, name, fallback) => ctx.node.getNodeParameter(name, ctx.itemIndex, fallback);
|
|
8
|
+
const str = (ctx, name) => { var _a; return String((_a = param(ctx, name, '')) !== null && _a !== void 0 ? _a : '').trim(); };
|
|
9
|
+
const bool = (ctx, name) => param(ctx, name, false) === true;
|
|
10
|
+
const fail = (ctx, message) => {
|
|
11
|
+
throw new n8n_workflow_1.NodeOperationError(ctx.node.getNode(), message, { itemIndex: ctx.itemIndex });
|
|
12
|
+
};
|
|
13
|
+
const parseJson = (ctx, raw, label) => {
|
|
14
|
+
if (raw === undefined || raw === null || raw === '')
|
|
15
|
+
return undefined;
|
|
16
|
+
if (typeof raw !== 'string')
|
|
17
|
+
return raw;
|
|
18
|
+
const trimmed = raw.trim();
|
|
19
|
+
if (!trimmed)
|
|
20
|
+
return undefined;
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(trimmed);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return fail(ctx, `${label} is not valid JSON`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const jsonObjectParam = (ctx, name, label) => {
|
|
29
|
+
const parsed = parseJson(ctx, param(ctx, name, ''), label);
|
|
30
|
+
if (parsed === undefined)
|
|
31
|
+
return {};
|
|
32
|
+
if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) {
|
|
33
|
+
return fail(ctx, `${label} must be a JSON object`);
|
|
34
|
+
}
|
|
35
|
+
return parsed;
|
|
36
|
+
};
|
|
37
|
+
const putFilled = (ctx, target, pairs) => {
|
|
38
|
+
for (const [name, field] of pairs) {
|
|
39
|
+
const value = param(ctx, name, '');
|
|
40
|
+
if (value === undefined || value === null || value === '' || value === 0)
|
|
41
|
+
continue;
|
|
42
|
+
if (typeof value === 'string') {
|
|
43
|
+
if (value.trim())
|
|
44
|
+
target[field] = value.trim();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
target[field] = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const requireStr = (ctx, name, label) => {
|
|
52
|
+
const value = str(ctx, name);
|
|
53
|
+
if (!value)
|
|
54
|
+
fail(ctx, `${label} is required`);
|
|
55
|
+
return value;
|
|
56
|
+
};
|
|
57
|
+
const request = (method, endpoint, payload) => {
|
|
58
|
+
const base = { endpoint, method, isUploadOperation: false, waitForCompletion: false };
|
|
59
|
+
return method === 'GET' ? { ...base, qs: payload } : { ...base, body: payload };
|
|
60
|
+
};
|
|
61
|
+
const TELEGRAM_UPLOAD_OPTIONS = [
|
|
62
|
+
['audioTitle', 'telegram_title_audio', 'string'],
|
|
63
|
+
['captionOverflow', 'telegram_caption_overflow', 'string'],
|
|
64
|
+
['contact', 'telegram_contact', 'json'],
|
|
65
|
+
['cover', 'telegram_cover', 'string'],
|
|
66
|
+
['dice', 'telegram_dice', 'string'],
|
|
67
|
+
['directMessagesTopicId', 'telegram_direct_messages_topic_id', 'number'],
|
|
68
|
+
['duration', 'telegram_duration', 'number'],
|
|
69
|
+
['emoji', 'telegram_emoji', 'string'],
|
|
70
|
+
['firstComment', 'telegram_first_comment', 'string'],
|
|
71
|
+
['firstCommentAsReply', 'telegram_first_comment_as_reply', 'boolean'],
|
|
72
|
+
['length', 'telegram_length', 'number'],
|
|
73
|
+
['linkPreviewOptions', 'telegram_link_preview_options', 'json'],
|
|
74
|
+
['livePhotoPhoto', 'telegram_live_photo_photo', 'string'],
|
|
75
|
+
['location', 'telegram_location', 'json'],
|
|
76
|
+
['mediaUrls', 'telegram_media_urls', 'string'],
|
|
77
|
+
['messageEffectId', 'telegram_message_effect_id', 'string'],
|
|
78
|
+
['paidPayload', 'telegram_paid_payload', 'string'],
|
|
79
|
+
['paidStarCount', 'telegram_paid_star_count', 'number'],
|
|
80
|
+
['performer', 'telegram_performer', 'string'],
|
|
81
|
+
['pin', 'telegram_pin', 'boolean'],
|
|
82
|
+
['pinNotify', 'telegram_pin_notify', 'boolean'],
|
|
83
|
+
['poll', 'telegram_poll', 'json'],
|
|
84
|
+
['replyMarkup', 'telegram_reply_markup', 'json'],
|
|
85
|
+
['replyQuote', 'telegram_reply_quote', 'string'],
|
|
86
|
+
['replyToMessageId', 'telegram_reply_to_message_id', 'number'],
|
|
87
|
+
['richMessage', 'telegram_rich_message', 'string'],
|
|
88
|
+
['sendAs', 'telegram_send_as', 'string'],
|
|
89
|
+
['sendByUrl', 'telegram_send_by_url', 'boolean'],
|
|
90
|
+
['sendTitle', 'telegram_send_title', 'boolean'],
|
|
91
|
+
['showCaptionAboveMedia', 'telegram_show_caption_above_media', 'boolean'],
|
|
92
|
+
['startTimestamp', 'telegram_start_timestamp', 'number'],
|
|
93
|
+
['telegramTitle', 'telegram_title', 'string'],
|
|
94
|
+
['thumbnail', 'telegram_thumbnail', 'string'],
|
|
95
|
+
['venue', 'telegram_venue', 'json'],
|
|
96
|
+
];
|
|
97
|
+
const BLUESKY_UPLOAD_OPTIONS = [
|
|
98
|
+
['captions', 'bluesky_captions', 'json'],
|
|
99
|
+
['createdAt', 'bluesky_created_at', 'string'],
|
|
100
|
+
['gifAsVideo', 'bluesky_gif_as_video', 'boolean'],
|
|
101
|
+
['tags', 'bluesky_tags', 'string'],
|
|
102
|
+
['threadOverflow', 'bluesky_thread_overflow', 'boolean'],
|
|
103
|
+
['videoPresentation', 'bluesky_video_presentation', 'string'],
|
|
104
|
+
];
|
|
105
|
+
const GBP_UPLOAD_OPTIONS = [
|
|
106
|
+
['alertType', 'gbp_alert_type', 'string'],
|
|
107
|
+
['multiMedia', 'gbp_multi_media', 'boolean'],
|
|
108
|
+
['recurrence', 'gbp_recurrence', 'string'],
|
|
109
|
+
['recurrenceDayOfMonth', 'gbp_recurrence_day_of_month', 'number'],
|
|
110
|
+
['recurrenceDays', 'gbp_recurrence_days', 'string'],
|
|
111
|
+
['recurrenceEnd', 'gbp_recurrence_end', 'string'],
|
|
112
|
+
['recurrenceWeekOccurrence', 'gbp_recurrence_week_occurrence', 'string'],
|
|
113
|
+
['scheduledTime', 'gbp_scheduled_time', 'string'],
|
|
114
|
+
['uploadToGallery', 'gbp_upload_to_gallery', 'boolean'],
|
|
115
|
+
];
|
|
116
|
+
const applyCollection = (ctx, collectionName, label, table, formData) => {
|
|
117
|
+
var _a;
|
|
118
|
+
const values = ((_a = param(ctx, collectionName, {})) !== null && _a !== void 0 ? _a : {});
|
|
119
|
+
for (const [key, field, kind] of table) {
|
|
120
|
+
if (!Object.prototype.hasOwnProperty.call(values, key))
|
|
121
|
+
continue;
|
|
122
|
+
const value = values[key];
|
|
123
|
+
if (kind === 'boolean') {
|
|
124
|
+
formData[field] = value === true ? 'true' : 'false';
|
|
125
|
+
}
|
|
126
|
+
else if (kind === 'number') {
|
|
127
|
+
if (value === '' || value === null || value === undefined)
|
|
128
|
+
continue;
|
|
129
|
+
formData[field] = String(value);
|
|
130
|
+
}
|
|
131
|
+
else if (kind === 'json') {
|
|
132
|
+
const parsed = parseJson(ctx, value, `${label}: ${key}`);
|
|
133
|
+
if (parsed === undefined)
|
|
134
|
+
continue;
|
|
135
|
+
formData[field] = JSON.stringify(parsed);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const text = String(value !== null && value !== void 0 ? value : '').trim();
|
|
139
|
+
if (text)
|
|
140
|
+
formData[field] = text;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const applyNetworkUploadOptions = (node, itemIndex, operation, platforms, formData) => {
|
|
145
|
+
const ctx = { node, itemIndex, operation };
|
|
146
|
+
const manual = platforms.includes(MANUAL_PLATFORM_VALUE);
|
|
147
|
+
const has = (platform) => platforms.includes(platform) || manual;
|
|
148
|
+
if (has('telegram')) {
|
|
149
|
+
applyCollection(ctx, 'telegramOptions', 'Telegram Options', TELEGRAM_UPLOAD_OPTIONS, formData);
|
|
150
|
+
}
|
|
151
|
+
if (operation === 'uploadDocument')
|
|
152
|
+
return;
|
|
153
|
+
if (bool(ctx, 'paidPartnership'))
|
|
154
|
+
formData.paid_partnership = 'true';
|
|
155
|
+
if (has('facebook')) {
|
|
156
|
+
const sponsor = str(ctx, 'facebookSponsorId');
|
|
157
|
+
if (sponsor)
|
|
158
|
+
formData.facebook_sponsor_id = sponsor;
|
|
159
|
+
}
|
|
160
|
+
if (has('pinterest') && operation !== 'uploadText') {
|
|
161
|
+
const sponsor = str(ctx, 'pinterestSponsorId');
|
|
162
|
+
if (sponsor)
|
|
163
|
+
formData.pinterest_sponsor_id = sponsor;
|
|
164
|
+
}
|
|
165
|
+
if (has('bluesky')) {
|
|
166
|
+
applyCollection(ctx, 'blueskyOptions', 'Bluesky Options', BLUESKY_UPLOAD_OPTIONS, formData);
|
|
167
|
+
}
|
|
168
|
+
if (has('google_business')) {
|
|
169
|
+
applyCollection(ctx, 'gbpOptions', 'Google Business Options', GBP_UPLOAD_OPTIONS, formData);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
exports.applyNetworkUploadOptions = applyNetworkUploadOptions;
|
|
173
|
+
const MEDIA_AND_TEXT = ['uploadPhotos', 'uploadVideo', 'uploadText'];
|
|
174
|
+
exports.uploadExtraProperties = [
|
|
175
|
+
{
|
|
176
|
+
displayName: 'Paid Partnership',
|
|
177
|
+
name: 'paidPartnership',
|
|
178
|
+
type: 'boolean',
|
|
179
|
+
default: false,
|
|
180
|
+
description: 'Whether the post is sponsored or made in partnership with a brand. Upload-Post sets each network\'s native label: TikTok branded content, YouTube paid promotion and X paid partnership (Facebook and Pinterest also need their sponsor ID). Networks without a label publish without it and the response carries a warning. A network-specific field always wins. TikTok refuses it with the Only Me privacy level (commercial_disclosure_privacy_conflict) and drafts do not carry it.',
|
|
181
|
+
displayOptions: { show: { resource: ['uploads'], operation: MEDIA_AND_TEXT } },
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
displayName: 'Facebook Sponsor ID',
|
|
185
|
+
name: 'facebookSponsorId',
|
|
186
|
+
type: 'string',
|
|
187
|
+
default: '',
|
|
188
|
+
description: 'Numeric ID of the sponsor\'s Facebook Page for the branded content tag. Page photos, Page videos and text/link posts only (Reels and Stories have no sponsor field). Your Page needs access to Meta\'s branded content tool.',
|
|
189
|
+
displayOptions: { show: { operation: MEDIA_AND_TEXT, platform: ['facebook', MANUAL_PLATFORM_VALUE] } },
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
displayName: 'Pinterest Sponsor ID',
|
|
193
|
+
name: 'pinterestSponsorId',
|
|
194
|
+
type: 'string',
|
|
195
|
+
default: '',
|
|
196
|
+
description: 'Numeric ID of the sponsor\'s Pinterest account for the paid partnership label. Pinterest only opens it to accounts in its closed beta; outside it the Pin is rejected.',
|
|
197
|
+
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['pinterest', MANUAL_PLATFORM_VALUE] } },
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
displayName: 'Telegram Options',
|
|
201
|
+
name: 'telegramOptions',
|
|
202
|
+
type: 'collection',
|
|
203
|
+
placeholder: 'Add Telegram Option',
|
|
204
|
+
default: {},
|
|
205
|
+
description: 'Telegram Bot API options (see docs.upload-post.com/api/telegram). JSON options take the official Bot API object as is.',
|
|
206
|
+
displayOptions: {
|
|
207
|
+
show: {
|
|
208
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText', 'uploadDocument'],
|
|
209
|
+
platform: ['telegram', MANUAL_PLATFORM_VALUE],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
options: [
|
|
213
|
+
{ displayName: 'Audio Title', name: 'audioTitle', type: 'string', default: '', description: 'Upload Document with Send As = audio: track title' },
|
|
214
|
+
{
|
|
215
|
+
displayName: 'Caption Overflow',
|
|
216
|
+
name: 'captionOverflow',
|
|
217
|
+
type: 'options',
|
|
218
|
+
options: [
|
|
219
|
+
{ name: 'Split (Rest of the Caption as a Reply)', value: 'split' },
|
|
220
|
+
{ name: 'Truncate (Refuse Captions Over 1024 Characters)', value: 'truncate' },
|
|
221
|
+
],
|
|
222
|
+
default: 'split',
|
|
223
|
+
description: 'Media captions over 1,024 characters',
|
|
224
|
+
},
|
|
225
|
+
{ displayName: 'Contact (JSON)', name: 'contact', type: 'json', default: '', description: 'Upload Text: send a contact, e.g. {"phone_number": "+34600000000", "first_name": "Ana"}' },
|
|
226
|
+
{ displayName: 'Cover', name: 'cover', type: 'string', default: '', description: 'Upload Video: cover image (public URL or Telegram file_id)' },
|
|
227
|
+
{ displayName: 'Dice', name: 'dice', type: 'string', default: '', description: 'Upload Text: send an animated dice. One of 🎲 🎯 🏀 ⚽ 🎳 🎰, or true for 🎲.' },
|
|
228
|
+
{ displayName: 'Direct Messages Topic ID', name: 'directMessagesTopicId', type: 'number', default: 0, description: 'Topic of a channel direct messages chat (required by Telegram when the connected chat is one)' },
|
|
229
|
+
{ displayName: 'Duration', name: 'duration', type: 'number', default: 0, description: 'Upload Document (audio, voice, animation, video note): duration in seconds' },
|
|
230
|
+
{ displayName: 'Emoji', name: 'emoji', type: 'string', default: '', description: 'Upload Document with Send As = sticker: emoji of the sticker' },
|
|
231
|
+
{ displayName: 'First Comment', name: 'firstComment', type: 'string', default: '', description: 'Telegram-only first comment (falls back to First Comment)' },
|
|
232
|
+
{ displayName: 'First Comment As Reply', name: 'firstCommentAsReply', type: 'boolean', default: true, description: 'Whether the first comment is sent as a reply to the post (default) instead of a separate message' },
|
|
233
|
+
{ displayName: 'Length', name: 'length', type: 'number', default: 0, description: 'Video note diameter in pixels' },
|
|
234
|
+
{ displayName: 'Link Preview Options (JSON)', name: 'linkPreviewOptions', type: 'json', default: '', description: 'Upload Text: Telegram LinkPreviewOptions object, e.g. {"is_disabled": true} or {"prefer_large_media": true, "show_above_text": true}' },
|
|
235
|
+
{ displayName: 'Live Photo Still', name: 'livePhotoPhoto', type: 'string', default: '', description: 'Upload Video with Send As = live_photo: URL of the still photo' },
|
|
236
|
+
{ displayName: 'Location (JSON)', name: 'location', type: 'json', default: '', description: 'Upload Text: send a location, e.g. {"latitude": 40.41, "longitude": -3.70}. Add live_period (60-86400 s) for a live location.' },
|
|
237
|
+
{ displayName: 'Media URLs', name: 'mediaUrls', type: 'string', default: '', description: 'Upload Video / Upload Document: up to 9 extra comma-separated URLs sent with the file as one album' },
|
|
238
|
+
{ displayName: 'Message Effect ID', name: 'messageEffectId', type: 'string', default: '', description: 'Message effect (Telegram shows effects in private chats only)' },
|
|
239
|
+
{ displayName: 'Paid Media Payload', name: 'paidPayload', type: 'string', default: '', description: 'Internal reference for paid media (max 128 bytes, never shown to readers)' },
|
|
240
|
+
{ displayName: 'Paid Media Stars', name: 'paidStarCount', type: 'number', typeOptions: { minValue: 1, maxValue: 25000 }, default: 1, description: 'Upload Photo(s) / Upload Video: readers pay this many Telegram Stars to unlock the media. The Stars go to your channel or bot.' },
|
|
241
|
+
{ displayName: 'Performer', name: 'performer', type: 'string', default: '', description: 'Upload Document with Send As = audio: performer' },
|
|
242
|
+
{ displayName: 'Pin', name: 'pin', type: 'boolean', default: true, description: 'Whether to pin the post after publishing (silently). A failed pin never fails the post.' },
|
|
243
|
+
{ displayName: 'Pin Notify', name: 'pinNotify', type: 'boolean', default: true, description: 'Whether to notify the members about the pin (groups only)' },
|
|
244
|
+
{ displayName: 'Poll (JSON)', name: 'poll', type: 'json', default: '', description: 'Upload Text: send a poll, e.g. {"options": ["Monday", "Friday"], "is_anonymous": false}. The question defaults to the post text.' },
|
|
245
|
+
{ displayName: 'Reply Markup (JSON)', name: 'replyMarkup', type: 'json', default: '', description: 'Inline keyboard with URL buttons: a Telegram InlineKeyboardMarkup object ({"inline_keyboard": [[button, ...]]}, each button with text and a link). Buttons with callback_data need your own bot to answer them.' },
|
|
246
|
+
{ displayName: 'Reply Quote', name: 'replyQuote', type: 'string', default: '', description: 'With Reply To Message ID: exact part of the message to quote' },
|
|
247
|
+
{ displayName: 'Reply To Message ID', name: 'replyToMessageId', type: 'number', default: 0, description: 'Publish as a reply to this message of the chat' },
|
|
248
|
+
{ displayName: 'Rich Message', name: 'richMessage', type: 'string', default: '', description: 'Upload Text: send a rich message (headings, lists, tables). True = the post text is rich Markdown, or markdown / html.' },
|
|
249
|
+
{
|
|
250
|
+
displayName: 'Send As',
|
|
251
|
+
name: 'sendAs',
|
|
252
|
+
type: 'options',
|
|
253
|
+
options: [
|
|
254
|
+
{ name: 'Animation', value: 'animation' },
|
|
255
|
+
{ name: 'Audio', value: 'audio' },
|
|
256
|
+
{ name: 'Document', value: 'document' },
|
|
257
|
+
{ name: 'Live Photo', value: 'live_photo' },
|
|
258
|
+
{ name: 'Photo', value: 'photo' },
|
|
259
|
+
{ name: 'Sticker', value: 'sticker' },
|
|
260
|
+
{ name: 'Video', value: 'video' },
|
|
261
|
+
{ name: 'Video Note', value: 'video_note' },
|
|
262
|
+
{ name: 'Voice', value: 'voice' },
|
|
263
|
+
],
|
|
264
|
+
default: 'document',
|
|
265
|
+
description: 'Upload Video: animation, video_note, live_photo or document. Upload Document: any type (default document).',
|
|
266
|
+
},
|
|
267
|
+
{ displayName: 'Send By URL', name: 'sendByUrl', type: 'boolean', default: true, description: 'Whether Telegram downloads the media URLs itself (max 5 MB per photo and 20 MB per file)' },
|
|
268
|
+
{ displayName: 'Send Title', name: 'sendTitle', type: 'boolean', default: false, description: 'Whether to send the post text before a location, contact, dice, sticker or video note (default true)' },
|
|
269
|
+
{ displayName: 'Show Caption Above Media', name: 'showCaptionAboveMedia', type: 'boolean', default: true, description: 'Whether to show the caption above the media' },
|
|
270
|
+
{ displayName: 'Start Timestamp', name: 'startTimestamp', type: 'number', default: 0, description: 'Upload Video: second where the video starts playing' },
|
|
271
|
+
{ displayName: 'Telegram Title', name: 'telegramTitle', type: 'string', default: '', description: 'Telegram text or caption (falls back to Title)' },
|
|
272
|
+
{ displayName: 'Thumbnail URL', name: 'thumbnail', type: 'string', default: '', description: 'Public URL of a JPEG under 200 kB, max 320×320' },
|
|
273
|
+
{ displayName: 'Venue (JSON)', name: 'venue', type: 'json', default: '', description: 'Upload Text: send a venue, e.g. {"latitude": 40.41, "longitude": -3.70, "address": "Gran Vía 1", "title": "Our shop"}' },
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
displayName: 'Bluesky Options',
|
|
278
|
+
name: 'blueskyOptions',
|
|
279
|
+
type: 'collection',
|
|
280
|
+
placeholder: 'Add Bluesky Option',
|
|
281
|
+
default: {},
|
|
282
|
+
description: 'An invalid value only fails the Bluesky part of the request (bluesky_invalid_parameter)',
|
|
283
|
+
displayOptions: { show: { operation: MEDIA_AND_TEXT, platform: ['bluesky', MANUAL_PLATFORM_VALUE] } },
|
|
284
|
+
options: [
|
|
285
|
+
{ displayName: 'Captions (JSON)', name: 'captions', type: 'json', default: '', description: 'Upload Video: up to 20 WebVTT subtitle tracks, one per language: objects with lang plus either a public link to the .vtt file or the WebVTT text in vtt (see docs.upload-post.com/api/upload-video)' },
|
|
286
|
+
{ displayName: 'Created At', name: 'createdAt', type: 'string', default: '', description: 'Date Bluesky shows and sorts the post by (ISO 8601 with time zone, not in the future), to import older posts' },
|
|
287
|
+
{ displayName: 'GIF As Video', name: 'gifAsVideo', type: 'boolean', default: true, description: 'Whether to publish a single animated GIF as a looping video (counts against the daily Bluesky video quota)' },
|
|
288
|
+
{ displayName: 'Tags', name: 'tags', type: 'string', default: '', description: 'Up to 8 comma-separated hashtags stored on the post without appearing in the text' },
|
|
289
|
+
{ displayName: 'Thread Overflow', name: 'threadOverflow', type: 'boolean', default: true, description: 'Whether a text longer than 300 characters continues as replies instead of being cut' },
|
|
290
|
+
{
|
|
291
|
+
displayName: 'Video Presentation',
|
|
292
|
+
name: 'videoPresentation',
|
|
293
|
+
type: 'options',
|
|
294
|
+
options: [
|
|
295
|
+
{ name: 'Default', value: 'default' },
|
|
296
|
+
{ name: 'GIF (Looping, Muted, No Controls)', value: 'gif' },
|
|
297
|
+
],
|
|
298
|
+
default: 'default',
|
|
299
|
+
description: 'Upload Video: how Bluesky plays the video',
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
displayName: 'Google Business Options',
|
|
305
|
+
name: 'gbpOptions',
|
|
306
|
+
type: 'collection',
|
|
307
|
+
placeholder: 'Add Google Business Option',
|
|
308
|
+
default: {},
|
|
309
|
+
displayOptions: { show: { operation: MEDIA_AND_TEXT, platform: ['google_business', MANUAL_PLATFORM_VALUE] } },
|
|
310
|
+
options: [
|
|
311
|
+
{ displayName: 'Alert Type', name: 'alertType', type: 'string', default: 'COVID_19', description: 'Topic Type ALERT: kind of alert (Google only accepts COVID_19 today)' },
|
|
312
|
+
{ displayName: 'Multiple Media', name: 'multiMedia', type: 'boolean', default: true, description: 'Whether to send every attached photo to Google (photos only, max 10). Without it only the first one is sent.' },
|
|
313
|
+
{
|
|
314
|
+
displayName: 'Recurrence',
|
|
315
|
+
name: 'recurrence',
|
|
316
|
+
type: 'options',
|
|
317
|
+
options: [
|
|
318
|
+
{ name: 'Daily', value: 'DAILY' },
|
|
319
|
+
{ name: 'Monthly', value: 'MONTHLY' },
|
|
320
|
+
{ name: 'Weekly', value: 'WEEKLY' },
|
|
321
|
+
],
|
|
322
|
+
default: 'WEEKLY',
|
|
323
|
+
description: 'EVENT and OFFER posts: repeat the post. Needs the event start and end dates.',
|
|
324
|
+
},
|
|
325
|
+
{ displayName: 'Recurrence Day of Month', name: 'recurrenceDayOfMonth', type: 'number', typeOptions: { minValue: 1, maxValue: 31 }, default: 1, description: 'MONTHLY: day of the month' },
|
|
326
|
+
{ displayName: 'Recurrence Days', name: 'recurrenceDays', type: 'string', default: '', placeholder: 'MON,THU', description: 'WEEKLY: comma-separated days (MONDAY,THURSDAY or MON,THU)' },
|
|
327
|
+
{ displayName: 'Recurrence End', name: 'recurrenceEnd', type: 'string', default: '', description: 'End of the series: YYYY-MM-DD or RFC 3339, at most a year after the event start' },
|
|
328
|
+
{
|
|
329
|
+
displayName: 'Recurrence Week Occurrence',
|
|
330
|
+
name: 'recurrenceWeekOccurrence',
|
|
331
|
+
type: 'options',
|
|
332
|
+
options: [
|
|
333
|
+
{ name: 'First', value: 'FIRST' },
|
|
334
|
+
{ name: 'Fourth', value: 'FOURTH' },
|
|
335
|
+
{ name: 'Last', value: 'LAST' },
|
|
336
|
+
{ name: 'Second', value: 'SECOND' },
|
|
337
|
+
{ name: 'Third', value: 'THIRD' },
|
|
338
|
+
],
|
|
339
|
+
default: 'FIRST',
|
|
340
|
+
description: 'MONTHLY: occurrence of the weekday of the event start',
|
|
341
|
+
},
|
|
342
|
+
{ displayName: 'Scheduled Time (Google)', name: 'scheduledTime', type: 'string', default: '', description: 'Google\'s own scheduling: RFC 3339 with time zone, at most a year ahead. Cancelling in Upload-Post does not stop it (use Unpublish Post).' },
|
|
343
|
+
{ displayName: 'Upload To Gallery', name: 'uploadToGallery', type: 'boolean', default: true, description: 'Whether to publish the photo to the Media/Gallery tab (same as Post Type = Media)' },
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
const opsFor = (resource) => ({ show: { resource: [resource] } });
|
|
348
|
+
const showFor = (resource, operation) => ({ show: { resource: [resource], operation } });
|
|
349
|
+
const BEST_TIME_PLATFORMS = [
|
|
350
|
+
{ name: 'Bluesky', value: 'bluesky' },
|
|
351
|
+
{ name: 'Facebook', value: 'facebook' },
|
|
352
|
+
{ name: 'Instagram', value: 'instagram' },
|
|
353
|
+
{ name: 'LinkedIn', value: 'linkedin' },
|
|
354
|
+
{ name: 'Pinterest', value: 'pinterest' },
|
|
355
|
+
{ name: 'Threads', value: 'threads' },
|
|
356
|
+
{ name: 'TikTok', value: 'tiktok' },
|
|
357
|
+
{ name: 'YouTube', value: 'youtube' },
|
|
358
|
+
];
|
|
359
|
+
const confirmProperty = (resource, operation, what) => ({
|
|
360
|
+
displayName: 'Confirm',
|
|
361
|
+
name: `${resource}Confirm`,
|
|
362
|
+
type: 'boolean',
|
|
363
|
+
default: false,
|
|
364
|
+
description: `Whether you confirm ${what}. The API refuses the call (confirmation_required) without it.`,
|
|
365
|
+
displayOptions: showFor(resource, operation),
|
|
366
|
+
});
|
|
367
|
+
const extraJsonProperty = (resource, operation, description) => ({
|
|
368
|
+
displayName: 'Extra Fields (JSON)',
|
|
369
|
+
name: `${resource}ExtraFields`,
|
|
370
|
+
type: 'json',
|
|
371
|
+
default: '',
|
|
372
|
+
description,
|
|
373
|
+
displayOptions: showFor(resource, operation),
|
|
374
|
+
});
|
|
375
|
+
exports.networkProperties = [
|
|
376
|
+
{
|
|
377
|
+
displayName: 'Operation',
|
|
378
|
+
name: 'operation',
|
|
379
|
+
type: 'options',
|
|
380
|
+
noDataExpression: true,
|
|
381
|
+
options: [
|
|
382
|
+
{ name: 'Get Best Times', value: 'getBestTimes', action: 'Get the best times to post', description: 'Best hours to publish for a connected account, with source (audience activity, account posts or Upload-Post history) and confidence' },
|
|
383
|
+
{ name: 'Get Next Queue Slot', value: 'getNextQueueSlot', action: 'Get the next free queue slot', description: 'Next free slot of the profile queue' },
|
|
384
|
+
{ name: 'Get Queue Preview', value: 'getQueuePreview', action: 'Preview the queue', description: 'Upcoming queue slots and how many posts each one has' },
|
|
385
|
+
{ name: 'Get Queue Settings', value: 'getQueueSettings', action: 'Get the queue settings', description: 'Queue settings, including slots_mode, auto_slots and effective_slots' },
|
|
386
|
+
{ name: 'Update Queue Settings', value: 'updateQueueSettings', action: 'Update the queue settings', description: 'Change the queue: automatic slots from the best times (slots=auto) or fixed slots, time zone, days and posts per slot' },
|
|
387
|
+
],
|
|
388
|
+
default: 'getBestTimes',
|
|
389
|
+
displayOptions: opsFor('queue'),
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
displayName: 'Operation',
|
|
393
|
+
name: 'operation',
|
|
394
|
+
type: 'options',
|
|
395
|
+
noDataExpression: true,
|
|
396
|
+
options: [
|
|
397
|
+
{ name: 'Create Invite Link', value: 'createTelegramInviteLink', action: 'Create a telegram invite link', description: 'Create an invite link for the connected chat' },
|
|
398
|
+
{ name: 'Get Boosts', value: 'getTelegramBoosts', action: 'Get telegram boosts', description: 'Boosts of the chat, or of one user' },
|
|
399
|
+
{ name: 'Get Bot Commands', value: 'getTelegramBotCommands', action: 'Get telegram bot commands', description: 'Commands of the connected bot' },
|
|
400
|
+
{ name: 'Get Bot Profile', value: 'getTelegramBotProfile', action: 'Get the telegram bot profile', description: 'Bot name, descriptions, photo, menu button and default administrator rights' },
|
|
401
|
+
{ name: 'Get Chat Info', value: 'getTelegramChatInfo', action: 'Get telegram chat info', description: 'Chat details, subscribers or members and administrators' },
|
|
402
|
+
{ name: 'Get Member', value: 'getTelegramMember', action: 'Get a telegram member', description: 'Read one member, or list the administrators when User ID is empty' },
|
|
403
|
+
{ name: 'Moderate Member', value: 'moderateTelegramMember', action: 'Moderate a telegram member', description: 'Ban, unban, restrict, promote, demote or give a custom title to a member' },
|
|
404
|
+
{ name: 'Revoke Invite Link', value: 'revokeTelegramInviteLink', action: 'Revoke a telegram invite link', description: 'Revoke an invite link the bot created' },
|
|
405
|
+
{ name: 'Set Bot Commands', value: 'setTelegramBotCommands', action: 'Set telegram bot commands', description: 'Replace the commands of the connected bot' },
|
|
406
|
+
{ name: 'Update Bot Profile', value: 'updateTelegramBotProfile', action: 'Update the telegram bot profile', description: 'Change the bot name, descriptions, menu button or default administrator rights' },
|
|
407
|
+
{ name: 'Update Chat Info', value: 'updateTelegramChatInfo', action: 'Update telegram chat info', description: 'Change the chat title, description, permissions and other settings' },
|
|
408
|
+
],
|
|
409
|
+
default: 'getTelegramChatInfo',
|
|
410
|
+
displayOptions: opsFor('telegram'),
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
displayName: 'Operation',
|
|
414
|
+
name: 'operation',
|
|
415
|
+
type: 'options',
|
|
416
|
+
noDataExpression: true,
|
|
417
|
+
options: [
|
|
418
|
+
{ name: 'Create Draft', value: 'createBlueskyDraft', action: 'Create a bluesky draft', description: 'Create a draft (text only) that shows up in the Bluesky app drafts list' },
|
|
419
|
+
{ name: 'Delete Draft', value: 'deleteBlueskyDraft', action: 'Delete a bluesky draft', description: 'Delete a draft' },
|
|
420
|
+
{ name: 'Get Notifications', value: 'getBlueskyNotifications', action: 'Get bluesky notifications', description: 'Notifications of the connected account (replies, mentions, quotes, likes, reposts, follows...)' },
|
|
421
|
+
{ name: 'Get Profile', value: 'getBlueskyProfile', action: 'Get bluesky profiles', description: 'One or several Bluesky profiles, or the connected account when Actor is empty' },
|
|
422
|
+
{ name: 'Get Unread Count', value: 'getBlueskyUnreadCount', action: 'Get the bluesky unread count', description: 'Unread notification count' },
|
|
423
|
+
{ name: 'List Drafts', value: 'listBlueskyDrafts', action: 'List bluesky drafts', description: 'Drafts of the connected account' },
|
|
424
|
+
{ name: 'Search Accounts', value: 'searchBlueskyActors', action: 'Search bluesky accounts', description: 'Search Bluesky accounts' },
|
|
425
|
+
{ name: 'Search Posts', value: 'searchBlueskyPosts', action: 'Search bluesky posts', description: 'Search Bluesky posts as the connected account' },
|
|
426
|
+
],
|
|
427
|
+
default: 'getBlueskyProfile',
|
|
428
|
+
displayOptions: opsFor('bluesky'),
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
displayName: 'Operation',
|
|
432
|
+
name: 'operation',
|
|
433
|
+
type: 'options',
|
|
434
|
+
noDataExpression: true,
|
|
435
|
+
options: [
|
|
436
|
+
{ name: 'Get Location Info', value: 'getGbpLocationInfo', action: 'Get google business location info', description: 'Name, address, hours, phones, categories, service area and open status of the location' },
|
|
437
|
+
{ name: 'Get Performance', value: 'getGbpPerformance', action: 'Get google business performance', description: 'Daily metrics for a date range (impressions, calls, website clicks, directions...)' },
|
|
438
|
+
{ name: 'Get Post', value: 'getGbpPost', action: 'Get a google business post', description: 'Read one post. Edit it with Post Action > Edit Post and delete it with Post Action > Unpublish Post.' },
|
|
439
|
+
{ name: 'Get Review', value: 'getGbpReview', action: 'Get a google business review', description: 'Read one review' },
|
|
440
|
+
{ name: 'Get Search Keywords', value: 'getGbpSearchKeywords', action: 'Get google business search keywords', description: 'Monthly search keywords that showed the location' },
|
|
441
|
+
{ name: 'List Posts', value: 'listGbpPosts', action: 'List google business posts', description: 'Posts of the location' },
|
|
442
|
+
{ name: 'List Reviews', value: 'listGbpReviews', action: 'List google business reviews', description: 'Reviews of the location' },
|
|
443
|
+
{ name: 'Update Location Info', value: 'updateGbpLocationInfo', action: 'Update google business location info', description: 'Edit the location info. Legacy mode (default) or strict mode, which can also change name, address, categories and open status.' },
|
|
444
|
+
],
|
|
445
|
+
default: 'listGbpPosts',
|
|
446
|
+
displayOptions: opsFor('googleBusiness'),
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
displayName: 'Profile Name or ID',
|
|
450
|
+
name: 'networkProfile',
|
|
451
|
+
type: 'options',
|
|
452
|
+
noDataExpression: true,
|
|
453
|
+
required: true,
|
|
454
|
+
default: '',
|
|
455
|
+
description: 'Choose from your created profiles. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
456
|
+
typeOptions: { loadOptionsMethod: 'getUserProfiles' },
|
|
457
|
+
displayOptions: { show: { resource: exports.NETWORK_RESOURCES } },
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
displayName: 'Platform',
|
|
461
|
+
name: 'bestTimesPlatform',
|
|
462
|
+
type: 'options',
|
|
463
|
+
required: true,
|
|
464
|
+
options: BEST_TIME_PLATFORMS,
|
|
465
|
+
default: 'instagram',
|
|
466
|
+
description: 'Connected network to analyse',
|
|
467
|
+
displayOptions: showFor('queue', ['getBestTimes']),
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
displayName: 'Time Zone',
|
|
471
|
+
name: 'queueTimezone',
|
|
472
|
+
type: 'string',
|
|
473
|
+
default: '',
|
|
474
|
+
placeholder: 'Europe/Madrid',
|
|
475
|
+
description: 'IANA time zone. Best times: the hours of the answer (default: the queue time zone, else UTC). Update queue: the queue time zone.',
|
|
476
|
+
displayOptions: showFor('queue', ['getBestTimes', 'updateQueueSettings']),
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
displayName: 'Top Hours',
|
|
480
|
+
name: 'bestTimesTop',
|
|
481
|
+
type: 'number',
|
|
482
|
+
typeOptions: { minValue: 0, maxValue: 24 },
|
|
483
|
+
default: 0,
|
|
484
|
+
description: 'How many hours to return (1-24). 0 = API default (5).',
|
|
485
|
+
displayOptions: showFor('queue', ['getBestTimes']),
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
displayName: 'Refresh',
|
|
489
|
+
name: 'queueRefresh',
|
|
490
|
+
type: 'boolean',
|
|
491
|
+
default: false,
|
|
492
|
+
description: 'Whether to recompute instead of using the cached answer (only when it is at least 24 hours old; YouTube 7 days)',
|
|
493
|
+
displayOptions: showFor('queue', ['getBestTimes', 'updateQueueSettings']),
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
displayName: 'LinkedIn Page URN',
|
|
497
|
+
name: 'bestTimesPageUrn',
|
|
498
|
+
type: 'string',
|
|
499
|
+
default: '',
|
|
500
|
+
description: 'LinkedIn only: organization ID or urn:li:organization:ID of a Page this connection administers',
|
|
501
|
+
displayOptions: { show: { resource: ['queue'], operation: ['getBestTimes'], bestTimesPlatform: ['linkedin'] } },
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
displayName: 'Facebook Page ID',
|
|
505
|
+
name: 'bestTimesFacebookPageId',
|
|
506
|
+
type: 'string',
|
|
507
|
+
default: '',
|
|
508
|
+
description: 'Facebook only: numeric ID of one of the connection\'s Pages',
|
|
509
|
+
displayOptions: { show: { resource: ['queue'], operation: ['getBestTimes'], bestTimesPlatform: ['facebook'] } },
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
displayName: 'Slots Mode',
|
|
513
|
+
name: 'queueSlotsMode',
|
|
514
|
+
type: 'options',
|
|
515
|
+
options: [
|
|
516
|
+
{ name: 'Automatic (Best Times)', value: 'auto' },
|
|
517
|
+
{ name: 'Fixed Slots', value: 'fixed' },
|
|
518
|
+
{ name: 'Keep Current', value: '' },
|
|
519
|
+
],
|
|
520
|
+
default: '',
|
|
521
|
+
description: 'Automatic fills the queue with the best hours of the profile\'s networks (posts already scheduled do not move). Fixed uses the Fixed Slots below, or the stored ones.',
|
|
522
|
+
displayOptions: showFor('queue', ['updateQueueSettings']),
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
displayName: 'Automatic Slots per Day',
|
|
526
|
+
name: 'queueAutoSlotsCount',
|
|
527
|
+
type: 'number',
|
|
528
|
+
typeOptions: { minValue: 0, maxValue: 12 },
|
|
529
|
+
default: 0,
|
|
530
|
+
description: 'Automatic mode: hours per day (1-12). 0 = API default (the number of fixed slots, or 3).',
|
|
531
|
+
displayOptions: { show: { resource: ['queue'], operation: ['updateQueueSettings'], queueSlotsMode: ['auto'] } },
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
displayName: 'Automatic Slots Platforms',
|
|
535
|
+
name: 'queueAutoPlatforms',
|
|
536
|
+
type: 'multiOptions',
|
|
537
|
+
options: [...BEST_TIME_PLATFORMS],
|
|
538
|
+
default: [],
|
|
539
|
+
description: 'Automatic mode: networks to take into account (up to 6). Empty = every connected network with best times.',
|
|
540
|
+
displayOptions: { show: { resource: ['queue'], operation: ['updateQueueSettings'], queueSlotsMode: ['auto'] } },
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
displayName: 'Fixed Slots (JSON)',
|
|
544
|
+
name: 'queueSlots',
|
|
545
|
+
type: 'json',
|
|
546
|
+
default: '',
|
|
547
|
+
description: 'Fixed mode: array of slots, e.g. [{"hour": 9, "minute": 0}, {"hour": 17, "minute": 30}] (max 24)',
|
|
548
|
+
displayOptions: { show: { resource: ['queue'], operation: ['updateQueueSettings'], queueSlotsMode: ['fixed'] } },
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
displayName: 'Days of Week',
|
|
552
|
+
name: 'queueDaysOfWeek',
|
|
553
|
+
type: 'string',
|
|
554
|
+
default: '',
|
|
555
|
+
placeholder: '0,1,2,3,4',
|
|
556
|
+
description: 'Active days, comma-separated: 0 = Monday ... 6 = Sunday. Empty = unchanged.',
|
|
557
|
+
displayOptions: showFor('queue', ['updateQueueSettings']),
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
displayName: 'Max Posts per Slot',
|
|
561
|
+
name: 'queueMaxPostsPerSlot',
|
|
562
|
+
type: 'number',
|
|
563
|
+
typeOptions: { minValue: 0, maxValue: 100 },
|
|
564
|
+
default: 0,
|
|
565
|
+
description: '1-100. 0 = unchanged.',
|
|
566
|
+
displayOptions: showFor('queue', ['updateQueueSettings']),
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
displayName: 'Slots to Preview',
|
|
570
|
+
name: 'queuePreviewCount',
|
|
571
|
+
type: 'number',
|
|
572
|
+
typeOptions: { minValue: 0, maxValue: 50 },
|
|
573
|
+
default: 0,
|
|
574
|
+
description: 'Number of slots to return (max 50). 0 = API default (10).',
|
|
575
|
+
displayOptions: showFor('queue', ['getQueuePreview']),
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
displayName: 'Include Administrators',
|
|
579
|
+
name: 'telegramIncludeAdministrators',
|
|
580
|
+
type: 'boolean',
|
|
581
|
+
default: true,
|
|
582
|
+
description: 'Whether to add the chat administrators',
|
|
583
|
+
displayOptions: showFor('telegram', ['getTelegramChatInfo']),
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
displayName: 'Return Bots',
|
|
587
|
+
name: 'telegramReturnBots',
|
|
588
|
+
type: 'boolean',
|
|
589
|
+
default: false,
|
|
590
|
+
description: 'Whether to also list other bots that are administrators',
|
|
591
|
+
displayOptions: showFor('telegram', ['getTelegramChatInfo', 'getTelegramMember']),
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
displayName: 'Telegram User ID',
|
|
595
|
+
name: 'telegramUserId',
|
|
596
|
+
type: 'string',
|
|
597
|
+
default: '',
|
|
598
|
+
description: 'Numeric Telegram user ID. Get Member: empty lists the administrators. Get Boosts: empty returns the chat boosts.',
|
|
599
|
+
displayOptions: showFor('telegram', ['getTelegramBoosts', 'getTelegramMember', 'moderateTelegramMember']),
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
displayName: 'Member Action',
|
|
603
|
+
name: 'telegramMemberAction',
|
|
604
|
+
type: 'options',
|
|
605
|
+
options: [
|
|
606
|
+
{ name: 'Ban', value: 'ban' },
|
|
607
|
+
{ name: 'Demote', value: 'demote' },
|
|
608
|
+
{ name: 'Promote', value: 'promote' },
|
|
609
|
+
{ name: 'Restrict', value: 'restrict' },
|
|
610
|
+
{ name: 'Set Custom Title', value: 'set_title' },
|
|
611
|
+
{ name: 'Unban', value: 'unban' },
|
|
612
|
+
],
|
|
613
|
+
default: 'restrict',
|
|
614
|
+
description: 'Ban, promote and demote need Confirm. Put permissions, rights, until_date or custom_title in Extra Fields.',
|
|
615
|
+
displayOptions: showFor('telegram', ['moderateTelegramMember']),
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
displayName: 'Title',
|
|
619
|
+
name: 'telegramChatTitle',
|
|
620
|
+
type: 'string',
|
|
621
|
+
default: '',
|
|
622
|
+
description: 'New chat title (1-128 characters)',
|
|
623
|
+
displayOptions: showFor('telegram', ['updateTelegramChatInfo']),
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
displayName: 'Description',
|
|
627
|
+
name: 'telegramChatDescription',
|
|
628
|
+
type: 'string',
|
|
629
|
+
default: '',
|
|
630
|
+
description: 'New chat description (0-255 characters)',
|
|
631
|
+
displayOptions: showFor('telegram', ['updateTelegramChatInfo']),
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
displayName: 'Link Name',
|
|
635
|
+
name: 'telegramInviteName',
|
|
636
|
+
type: 'string',
|
|
637
|
+
default: '',
|
|
638
|
+
description: 'Name of the invite link (0-32 characters)',
|
|
639
|
+
displayOptions: showFor('telegram', ['createTelegramInviteLink']),
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
displayName: 'Expire Date',
|
|
643
|
+
name: 'telegramInviteExpireDate',
|
|
644
|
+
type: 'number',
|
|
645
|
+
default: 0,
|
|
646
|
+
description: 'Unix time when the link expires. 0 = never.',
|
|
647
|
+
displayOptions: showFor('telegram', ['createTelegramInviteLink']),
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
displayName: 'Member Limit',
|
|
651
|
+
name: 'telegramInviteMemberLimit',
|
|
652
|
+
type: 'number',
|
|
653
|
+
typeOptions: { minValue: 0, maxValue: 99999 },
|
|
654
|
+
default: 0,
|
|
655
|
+
description: 'Members that can join with the link (1-99999). 0 = no limit. Not together with Creates Join Request.',
|
|
656
|
+
displayOptions: showFor('telegram', ['createTelegramInviteLink']),
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
displayName: 'Creates Join Request',
|
|
660
|
+
name: 'telegramInviteCreatesJoinRequest',
|
|
661
|
+
type: 'boolean',
|
|
662
|
+
default: false,
|
|
663
|
+
description: 'Whether people joining with the link need to be approved by an administrator',
|
|
664
|
+
displayOptions: showFor('telegram', ['createTelegramInviteLink']),
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
displayName: 'Invite Link',
|
|
668
|
+
name: 'telegramInviteLink',
|
|
669
|
+
type: 'string',
|
|
670
|
+
required: true,
|
|
671
|
+
default: '',
|
|
672
|
+
description: 'The invite link to revoke (only links created by the bot)',
|
|
673
|
+
displayOptions: showFor('telegram', ['revokeTelegramInviteLink']),
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
displayName: 'Bot Name',
|
|
677
|
+
name: 'telegramBotName',
|
|
678
|
+
type: 'string',
|
|
679
|
+
default: '',
|
|
680
|
+
description: 'Bot name (0-64 characters)',
|
|
681
|
+
displayOptions: showFor('telegram', ['updateTelegramBotProfile']),
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
displayName: 'Bot Description',
|
|
685
|
+
name: 'telegramBotDescription',
|
|
686
|
+
type: 'string',
|
|
687
|
+
default: '',
|
|
688
|
+
description: 'Shown in an empty chat with the bot (0-512 characters)',
|
|
689
|
+
displayOptions: showFor('telegram', ['updateTelegramBotProfile']),
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
displayName: 'Bot Short Description',
|
|
693
|
+
name: 'telegramBotShortDescription',
|
|
694
|
+
type: 'string',
|
|
695
|
+
default: '',
|
|
696
|
+
description: 'Shown on the bot profile and when it is shared (0-120 characters)',
|
|
697
|
+
displayOptions: showFor('telegram', ['updateTelegramBotProfile']),
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
displayName: 'Commands',
|
|
701
|
+
name: 'telegramCommands',
|
|
702
|
+
type: 'fixedCollection',
|
|
703
|
+
typeOptions: { multipleValues: true, maxValue: 100 },
|
|
704
|
+
default: {},
|
|
705
|
+
placeholder: 'Add Command',
|
|
706
|
+
options: [
|
|
707
|
+
{
|
|
708
|
+
name: 'command',
|
|
709
|
+
displayName: 'Command',
|
|
710
|
+
values: [
|
|
711
|
+
{ displayName: 'Command', name: 'command', type: 'string', default: '', description: '1-32 lowercase letters, digits or underscores, without the slash' },
|
|
712
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '', description: 'Description shown in the menu (1-256 characters)' },
|
|
713
|
+
],
|
|
714
|
+
},
|
|
715
|
+
],
|
|
716
|
+
displayOptions: showFor('telegram', ['setTelegramBotCommands']),
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
displayName: 'Language Code',
|
|
720
|
+
name: 'telegramLanguageCode',
|
|
721
|
+
type: 'string',
|
|
722
|
+
default: '',
|
|
723
|
+
description: 'Two-letter ISO 639-1 code: the texts or commands apply to that language only. Empty = every language without its own.',
|
|
724
|
+
displayOptions: showFor('telegram', ['updateTelegramBotProfile', 'getTelegramBotCommands', 'setTelegramBotCommands']),
|
|
725
|
+
},
|
|
726
|
+
confirmProperty('telegram', ['moderateTelegramMember', 'revokeTelegramInviteLink'], 'the change (ban, promote, demote, revoke)'),
|
|
727
|
+
extraJsonProperty('telegram', ['updateTelegramChatInfo', 'moderateTelegramMember', 'updateTelegramBotProfile', 'setTelegramBotCommands'], 'Other fields merged into the request body as is, e.g. {"permissions": {"can_send_messages": false}}, {"rights": {"can_post_messages": true}}, {"until_date": 0}, {"menu_button": {"type": "commands"}} or {"scope": {"type": "all_private_chats"}}'),
|
|
728
|
+
{
|
|
729
|
+
displayName: 'Actor',
|
|
730
|
+
name: 'blueskyActor',
|
|
731
|
+
type: 'string',
|
|
732
|
+
default: '',
|
|
733
|
+
description: 'Handle or DID, or several separated by commas (up to 25). Empty = the connected account.',
|
|
734
|
+
displayOptions: showFor('bluesky', ['getBlueskyProfile']),
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
displayName: 'Search Query',
|
|
738
|
+
name: 'blueskyQuery',
|
|
739
|
+
type: 'string',
|
|
740
|
+
required: true,
|
|
741
|
+
default: '',
|
|
742
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts', 'searchBlueskyActors']),
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
displayName: 'Sort',
|
|
746
|
+
name: 'blueskySort',
|
|
747
|
+
type: 'options',
|
|
748
|
+
options: [
|
|
749
|
+
{ name: 'API Default', value: '' },
|
|
750
|
+
{ name: 'Latest', value: 'latest' },
|
|
751
|
+
{ name: 'Top', value: 'top' },
|
|
752
|
+
],
|
|
753
|
+
default: '',
|
|
754
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts']),
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
displayName: 'Author',
|
|
758
|
+
name: 'blueskyAuthor',
|
|
759
|
+
type: 'string',
|
|
760
|
+
default: '',
|
|
761
|
+
description: 'Only posts by this handle or DID',
|
|
762
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts']),
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
displayName: 'Language',
|
|
766
|
+
name: 'blueskyLang',
|
|
767
|
+
type: 'string',
|
|
768
|
+
default: '',
|
|
769
|
+
placeholder: 'en',
|
|
770
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts']),
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
displayName: 'Since',
|
|
774
|
+
name: 'blueskySince',
|
|
775
|
+
type: 'string',
|
|
776
|
+
default: '',
|
|
777
|
+
description: 'YYYY-MM-DD or ISO 8601 with time zone',
|
|
778
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts']),
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
displayName: 'Until',
|
|
782
|
+
name: 'blueskyUntil',
|
|
783
|
+
type: 'string',
|
|
784
|
+
default: '',
|
|
785
|
+
description: 'YYYY-MM-DD or ISO 8601 with time zone',
|
|
786
|
+
displayOptions: showFor('bluesky', ['searchBlueskyPosts']),
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
displayName: 'Reasons',
|
|
790
|
+
name: 'blueskyReasons',
|
|
791
|
+
type: 'multiOptions',
|
|
792
|
+
options: [
|
|
793
|
+
{ name: 'Follow', value: 'follow' },
|
|
794
|
+
{ name: 'Like', value: 'like' },
|
|
795
|
+
{ name: 'Mention', value: 'mention' },
|
|
796
|
+
{ name: 'Quote', value: 'quote' },
|
|
797
|
+
{ name: 'Reply', value: 'reply' },
|
|
798
|
+
{ name: 'Repost', value: 'repost' },
|
|
799
|
+
],
|
|
800
|
+
default: [],
|
|
801
|
+
description: 'Only these kinds of notification. Empty = all.',
|
|
802
|
+
displayOptions: showFor('bluesky', ['getBlueskyNotifications']),
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
displayName: 'Page Size',
|
|
806
|
+
name: 'blueskyPageSize',
|
|
807
|
+
type: 'number',
|
|
808
|
+
typeOptions: { minValue: 0, maxValue: 100 },
|
|
809
|
+
default: 0,
|
|
810
|
+
description: '1-100. 0 = API default.',
|
|
811
|
+
displayOptions: showFor('bluesky', ['getBlueskyNotifications', 'searchBlueskyPosts', 'searchBlueskyActors', 'listBlueskyDrafts']),
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
displayName: 'Cursor',
|
|
815
|
+
name: 'blueskyCursor',
|
|
816
|
+
type: 'string',
|
|
817
|
+
default: '',
|
|
818
|
+
description: 'Cursor of the previous page',
|
|
819
|
+
displayOptions: showFor('bluesky', ['getBlueskyNotifications', 'searchBlueskyPosts', 'searchBlueskyActors', 'listBlueskyDrafts']),
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
displayName: 'Draft Text',
|
|
823
|
+
name: 'blueskyDraftText',
|
|
824
|
+
type: 'string',
|
|
825
|
+
default: '',
|
|
826
|
+
typeOptions: { rows: 3 },
|
|
827
|
+
description: 'Text of a one-post draft (up to 1,000 characters). For a thread use Draft Posts.',
|
|
828
|
+
displayOptions: showFor('bluesky', ['createBlueskyDraft']),
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
displayName: 'Draft Posts (JSON)',
|
|
832
|
+
name: 'blueskyDraftPosts',
|
|
833
|
+
type: 'json',
|
|
834
|
+
default: '',
|
|
835
|
+
description: 'Thread of 1-100 posts, e.g. [{"text": "Part 1", "link_url": "https://example.com"}, {"text": "Part 2"}]. Images and video are not accepted in drafts.',
|
|
836
|
+
displayOptions: showFor('bluesky', ['createBlueskyDraft']),
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
displayName: 'Languages',
|
|
840
|
+
name: 'blueskyDraftLangs',
|
|
841
|
+
type: 'string',
|
|
842
|
+
default: '',
|
|
843
|
+
placeholder: 'en,es',
|
|
844
|
+
description: 'Up to 3 comma-separated language codes',
|
|
845
|
+
displayOptions: showFor('bluesky', ['createBlueskyDraft']),
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
displayName: 'Reply Settings',
|
|
849
|
+
name: 'blueskyDraftReplySettings',
|
|
850
|
+
type: 'string',
|
|
851
|
+
default: '',
|
|
852
|
+
description: 'Who can reply once published: nobody, mention, following, followers, or list: followed by the list AT-URI',
|
|
853
|
+
displayOptions: showFor('bluesky', ['createBlueskyDraft']),
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
displayName: 'Draft ID',
|
|
857
|
+
name: 'blueskyDraftId',
|
|
858
|
+
type: 'string',
|
|
859
|
+
required: true,
|
|
860
|
+
default: '',
|
|
861
|
+
displayOptions: showFor('bluesky', ['deleteBlueskyDraft']),
|
|
862
|
+
},
|
|
863
|
+
confirmProperty('bluesky', ['deleteBlueskyDraft'], 'deleting the draft'),
|
|
864
|
+
{
|
|
865
|
+
displayName: 'Location ID',
|
|
866
|
+
name: 'gbpApiLocationId',
|
|
867
|
+
type: 'string',
|
|
868
|
+
default: '',
|
|
869
|
+
description: 'Location as locations/123, 123 or accounts/456/locations/123. Empty = the location selected for the profile.',
|
|
870
|
+
displayOptions: { show: { resource: ['googleBusiness'], operation: ['listGbpPosts', 'listGbpReviews', 'getGbpPerformance', 'getGbpSearchKeywords', 'getGbpLocationInfo', 'updateGbpLocationInfo'] } },
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
displayName: 'Post ID',
|
|
874
|
+
name: 'gbpApiPostId',
|
|
875
|
+
type: 'string',
|
|
876
|
+
required: true,
|
|
877
|
+
default: '',
|
|
878
|
+
description: 'Full post name returned on upload or by List Posts: accounts/{a}/locations/{l}/localPosts/{p}',
|
|
879
|
+
displayOptions: showFor('googleBusiness', ['getGbpPost']),
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
displayName: 'Review Name',
|
|
883
|
+
name: 'gbpApiReviewName',
|
|
884
|
+
type: 'string',
|
|
885
|
+
required: true,
|
|
886
|
+
default: '',
|
|
887
|
+
description: 'Full review name from List Reviews: accounts/.../locations/.../reviews/{ID}',
|
|
888
|
+
displayOptions: showFor('googleBusiness', ['getGbpReview']),
|
|
889
|
+
},
|
|
890
|
+
{
|
|
891
|
+
displayName: 'Order By',
|
|
892
|
+
name: 'gbpApiOrderBy',
|
|
893
|
+
type: 'options',
|
|
894
|
+
options: [
|
|
895
|
+
{ name: 'Highest Rating', value: 'rating desc' },
|
|
896
|
+
{ name: 'Lowest Rating', value: 'rating' },
|
|
897
|
+
{ name: 'Newest', value: 'updateTime desc' },
|
|
898
|
+
],
|
|
899
|
+
default: 'updateTime desc',
|
|
900
|
+
displayOptions: showFor('googleBusiness', ['listGbpReviews']),
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
displayName: 'Page Size',
|
|
904
|
+
name: 'gbpApiPageSize',
|
|
905
|
+
type: 'number',
|
|
906
|
+
typeOptions: { minValue: 0, maxValue: 100 },
|
|
907
|
+
default: 0,
|
|
908
|
+
description: 'Items per page. 0 = API default.',
|
|
909
|
+
displayOptions: showFor('googleBusiness', ['listGbpPosts', 'listGbpReviews', 'getGbpSearchKeywords']),
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
displayName: 'Page Token',
|
|
913
|
+
name: 'gbpApiPageCursor',
|
|
914
|
+
type: 'string',
|
|
915
|
+
default: '',
|
|
916
|
+
description: 'The next_page_token of the previous page',
|
|
917
|
+
displayOptions: showFor('googleBusiness', ['listGbpPosts', 'listGbpReviews', 'getGbpSearchKeywords']),
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
displayName: 'Metrics',
|
|
921
|
+
name: 'gbpApiMetrics',
|
|
922
|
+
type: 'string',
|
|
923
|
+
default: '',
|
|
924
|
+
placeholder: 'CALL_CLICKS,WEBSITE_CLICKS',
|
|
925
|
+
description: 'Comma-separated metrics. Empty = all of them.',
|
|
926
|
+
displayOptions: showFor('googleBusiness', ['getGbpPerformance']),
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
displayName: 'Start Date',
|
|
930
|
+
name: 'gbpApiStartDate',
|
|
931
|
+
type: 'string',
|
|
932
|
+
default: '',
|
|
933
|
+
placeholder: '2026-10-01',
|
|
934
|
+
description: 'YYYY-MM-DD (at most 18 months back). Default: 29 days before the end date.',
|
|
935
|
+
displayOptions: showFor('googleBusiness', ['getGbpPerformance']),
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
displayName: 'End Date',
|
|
939
|
+
name: 'gbpApiEndDate',
|
|
940
|
+
type: 'string',
|
|
941
|
+
default: '',
|
|
942
|
+
description: 'YYYY-MM-DD. Default: today (UTC).',
|
|
943
|
+
displayOptions: showFor('googleBusiness', ['getGbpPerformance']),
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
displayName: 'Start Month',
|
|
947
|
+
name: 'gbpApiStartMonth',
|
|
948
|
+
type: 'string',
|
|
949
|
+
default: '',
|
|
950
|
+
placeholder: '2026-09',
|
|
951
|
+
description: 'YYYY-MM (at most 18 months back)',
|
|
952
|
+
displayOptions: showFor('googleBusiness', ['getGbpSearchKeywords']),
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
displayName: 'End Month',
|
|
956
|
+
name: 'gbpApiEndMonth',
|
|
957
|
+
type: 'string',
|
|
958
|
+
default: '',
|
|
959
|
+
description: 'YYYY-MM. Default: the current month.',
|
|
960
|
+
displayOptions: showFor('googleBusiness', ['getGbpSearchKeywords']),
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
displayName: 'Read Mask',
|
|
964
|
+
name: 'gbpApiReadMask',
|
|
965
|
+
type: 'string',
|
|
966
|
+
default: '',
|
|
967
|
+
description: 'Comma-separated Location fields to return (e.g. name,title,regularHours). Empty = all.',
|
|
968
|
+
displayOptions: showFor('googleBusiness', ['getGbpLocationInfo']),
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
displayName: 'Edit Mode',
|
|
972
|
+
name: 'gbpApiEditMode',
|
|
973
|
+
type: 'options',
|
|
974
|
+
options: [
|
|
975
|
+
{ name: 'Legacy (Default)', value: 'legacy' },
|
|
976
|
+
{ name: 'Strict', value: 'strict' },
|
|
977
|
+
],
|
|
978
|
+
default: 'legacy',
|
|
979
|
+
description: 'Strict can also change title, address, categories, service area and open status (some need Confirm) and supports Dry Run',
|
|
980
|
+
displayOptions: showFor('googleBusiness', ['updateGbpLocationInfo']),
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
displayName: 'Description',
|
|
984
|
+
name: 'gbpApiDescription',
|
|
985
|
+
type: 'string',
|
|
986
|
+
default: '',
|
|
987
|
+
description: 'Business description (max 750 characters)',
|
|
988
|
+
displayOptions: showFor('googleBusiness', ['updateGbpLocationInfo']),
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
displayName: 'Website',
|
|
992
|
+
name: 'gbpApiWebsite',
|
|
993
|
+
type: 'string',
|
|
994
|
+
default: '',
|
|
995
|
+
displayOptions: showFor('googleBusiness', ['updateGbpLocationInfo']),
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
displayName: 'Phone',
|
|
999
|
+
name: 'gbpApiPhone',
|
|
1000
|
+
type: 'string',
|
|
1001
|
+
default: '',
|
|
1002
|
+
description: 'Primary phone, e.g. +34 912 345 678',
|
|
1003
|
+
displayOptions: showFor('googleBusiness', ['updateGbpLocationInfo']),
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
displayName: 'Validate Only',
|
|
1007
|
+
name: 'gbpApiValidateOnly',
|
|
1008
|
+
type: 'boolean',
|
|
1009
|
+
default: false,
|
|
1010
|
+
description: 'Whether Google only validates the change without applying it',
|
|
1011
|
+
displayOptions: showFor('googleBusiness', ['updateGbpLocationInfo']),
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
displayName: 'Dry Run',
|
|
1015
|
+
name: 'gbpApiDryRun',
|
|
1016
|
+
type: 'boolean',
|
|
1017
|
+
default: false,
|
|
1018
|
+
description: 'Whether to only validate the change (strict mode)',
|
|
1019
|
+
displayOptions: { show: { resource: ['googleBusiness'], operation: ['updateGbpLocationInfo'], gbpApiEditMode: ['strict'] } },
|
|
1020
|
+
},
|
|
1021
|
+
confirmProperty('googleBusiness', ['updateGbpLocationInfo'], 'changing title, address, primary category, phone or closing the location (strict mode)'),
|
|
1022
|
+
extraJsonProperty('googleBusiness', ['updateGbpLocationInfo'], 'Other location fields merged into the body as is, e.g. {"regular_hours": [{"day": "MONDAY", "open": "09:00", "close": "18:00"}]}, special_hours, primary_category, additional_categories or (strict mode) title, address, open_status'),
|
|
1023
|
+
];
|
|
1024
|
+
const buildQueueRequest = (ctx, profile) => {
|
|
1025
|
+
switch (ctx.operation) {
|
|
1026
|
+
case 'getBestTimes': {
|
|
1027
|
+
const qs = { profile_username: profile, platform: requireStr(ctx, 'bestTimesPlatform', 'Platform') };
|
|
1028
|
+
putFilled(ctx, qs, [['queueTimezone', 'timezone'], ['bestTimesTop', 'top']]);
|
|
1029
|
+
if (bool(ctx, 'queueRefresh'))
|
|
1030
|
+
qs.refresh = 'true';
|
|
1031
|
+
if (qs.platform === 'linkedin')
|
|
1032
|
+
putFilled(ctx, qs, [['bestTimesPageUrn', 'page_urn']]);
|
|
1033
|
+
if (qs.platform === 'facebook')
|
|
1034
|
+
putFilled(ctx, qs, [['bestTimesFacebookPageId', 'facebook_page_id']]);
|
|
1035
|
+
return request('GET', '/uploadposts/best-times', qs);
|
|
1036
|
+
}
|
|
1037
|
+
case 'getQueueSettings':
|
|
1038
|
+
return request('GET', '/uploadposts/queue/settings', { profile_username: profile });
|
|
1039
|
+
case 'getQueuePreview': {
|
|
1040
|
+
const qs = { profile_username: profile };
|
|
1041
|
+
putFilled(ctx, qs, [['queuePreviewCount', 'count']]);
|
|
1042
|
+
return request('GET', '/uploadposts/queue/preview', qs);
|
|
1043
|
+
}
|
|
1044
|
+
case 'getNextQueueSlot':
|
|
1045
|
+
return request('GET', '/uploadposts/queue/next-slot', { profile_username: profile });
|
|
1046
|
+
case 'updateQueueSettings': {
|
|
1047
|
+
const body = { profile_username: profile };
|
|
1048
|
+
putFilled(ctx, body, [['queueTimezone', 'timezone'], ['queueMaxPostsPerSlot', 'max_posts_per_slot']]);
|
|
1049
|
+
const mode = str(ctx, 'queueSlotsMode');
|
|
1050
|
+
if (mode === 'auto') {
|
|
1051
|
+
body.slots_mode = 'auto';
|
|
1052
|
+
putFilled(ctx, body, [['queueAutoSlotsCount', 'auto_slots_count']]);
|
|
1053
|
+
const platforms = param(ctx, 'queueAutoPlatforms', []);
|
|
1054
|
+
if (Array.isArray(platforms) && platforms.length > 0)
|
|
1055
|
+
body.auto_platforms = platforms;
|
|
1056
|
+
if (bool(ctx, 'queueRefresh'))
|
|
1057
|
+
body.refresh = true;
|
|
1058
|
+
}
|
|
1059
|
+
else if (mode === 'fixed') {
|
|
1060
|
+
const slots = parseJson(ctx, param(ctx, 'queueSlots', ''), 'Fixed Slots');
|
|
1061
|
+
if (slots === undefined) {
|
|
1062
|
+
body.slots_mode = 'fixed';
|
|
1063
|
+
}
|
|
1064
|
+
else if (Array.isArray(slots)) {
|
|
1065
|
+
body.slots = slots;
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
fail(ctx, 'Fixed Slots must be a JSON array, e.g. [{"hour": 9, "minute": 0}]');
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
const days = str(ctx, 'queueDaysOfWeek');
|
|
1072
|
+
if (days) {
|
|
1073
|
+
const parsed = days.split(',').map(day => day.trim()).filter(Boolean).map(Number);
|
|
1074
|
+
if (parsed.some(day => !Number.isInteger(day) || day < 0 || day > 6)) {
|
|
1075
|
+
fail(ctx, 'Days of Week must be numbers from 0 (Monday) to 6 (Sunday)');
|
|
1076
|
+
}
|
|
1077
|
+
body.days_of_week = parsed;
|
|
1078
|
+
}
|
|
1079
|
+
if (Object.keys(body).length === 1)
|
|
1080
|
+
fail(ctx, 'Nothing to update: set Slots Mode, Time Zone, Days of Week or Max Posts per Slot');
|
|
1081
|
+
return request('POST', '/uploadposts/queue/settings', body);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return fail(ctx, `Unsupported queue operation: ${ctx.operation}`);
|
|
1085
|
+
};
|
|
1086
|
+
const TG = '/uploadposts/telegram';
|
|
1087
|
+
const buildTelegramRequest = (ctx, user) => {
|
|
1088
|
+
var _a;
|
|
1089
|
+
const extra = () => jsonObjectParam(ctx, 'telegramExtraFields', 'Extra Fields (JSON)');
|
|
1090
|
+
const confirm = (body) => {
|
|
1091
|
+
if (bool(ctx, 'telegramConfirm'))
|
|
1092
|
+
body.confirm = true;
|
|
1093
|
+
return body;
|
|
1094
|
+
};
|
|
1095
|
+
switch (ctx.operation) {
|
|
1096
|
+
case 'getTelegramChatInfo': {
|
|
1097
|
+
const qs = { user };
|
|
1098
|
+
if (param(ctx, 'telegramIncludeAdministrators', true) === false)
|
|
1099
|
+
qs.include_administrators = 'false';
|
|
1100
|
+
if (bool(ctx, 'telegramReturnBots'))
|
|
1101
|
+
qs.return_bots = 'true';
|
|
1102
|
+
return request('GET', `${TG}/chat-info`, qs);
|
|
1103
|
+
}
|
|
1104
|
+
case 'updateTelegramChatInfo': {
|
|
1105
|
+
const body = { user };
|
|
1106
|
+
putFilled(ctx, body, [['telegramChatTitle', 'title'], ['telegramChatDescription', 'description']]);
|
|
1107
|
+
Object.assign(body, extra());
|
|
1108
|
+
if (Object.keys(body).length === 1)
|
|
1109
|
+
fail(ctx, 'Nothing to update: set Title, Description or Extra Fields');
|
|
1110
|
+
return request('PATCH', `${TG}/chat-info`, body);
|
|
1111
|
+
}
|
|
1112
|
+
case 'getTelegramBoosts': {
|
|
1113
|
+
const qs = { user };
|
|
1114
|
+
putFilled(ctx, qs, [['telegramUserId', 'user_id']]);
|
|
1115
|
+
return request('GET', `${TG}/boosts`, qs);
|
|
1116
|
+
}
|
|
1117
|
+
case 'getTelegramMember': {
|
|
1118
|
+
const qs = { user };
|
|
1119
|
+
putFilled(ctx, qs, [['telegramUserId', 'user_id']]);
|
|
1120
|
+
if (bool(ctx, 'telegramReturnBots'))
|
|
1121
|
+
qs.return_bots = 'true';
|
|
1122
|
+
return request('GET', `${TG}/members`, qs);
|
|
1123
|
+
}
|
|
1124
|
+
case 'moderateTelegramMember': {
|
|
1125
|
+
const body = {
|
|
1126
|
+
user,
|
|
1127
|
+
action: requireStr(ctx, 'telegramMemberAction', 'Member Action'),
|
|
1128
|
+
user_id: requireStr(ctx, 'telegramUserId', 'Telegram User ID'),
|
|
1129
|
+
...extra(),
|
|
1130
|
+
};
|
|
1131
|
+
return request('POST', `${TG}/members`, confirm(body));
|
|
1132
|
+
}
|
|
1133
|
+
case 'createTelegramInviteLink': {
|
|
1134
|
+
const body = { user };
|
|
1135
|
+
putFilled(ctx, body, [
|
|
1136
|
+
['telegramInviteName', 'name'],
|
|
1137
|
+
['telegramInviteExpireDate', 'expire_date'],
|
|
1138
|
+
['telegramInviteMemberLimit', 'member_limit'],
|
|
1139
|
+
]);
|
|
1140
|
+
if (bool(ctx, 'telegramInviteCreatesJoinRequest'))
|
|
1141
|
+
body.creates_join_request = true;
|
|
1142
|
+
return request('POST', `${TG}/invite-links`, body);
|
|
1143
|
+
}
|
|
1144
|
+
case 'revokeTelegramInviteLink':
|
|
1145
|
+
return request('DELETE', `${TG}/invite-links`, confirm({ user, invite_link: requireStr(ctx, 'telegramInviteLink', 'Invite Link') }));
|
|
1146
|
+
case 'getTelegramBotProfile':
|
|
1147
|
+
return request('GET', `${TG}/bot-profile`, { user });
|
|
1148
|
+
case 'updateTelegramBotProfile': {
|
|
1149
|
+
const body = { user };
|
|
1150
|
+
putFilled(ctx, body, [
|
|
1151
|
+
['telegramBotName', 'name'],
|
|
1152
|
+
['telegramBotDescription', 'description'],
|
|
1153
|
+
['telegramBotShortDescription', 'short_description'],
|
|
1154
|
+
['telegramLanguageCode', 'language_code'],
|
|
1155
|
+
]);
|
|
1156
|
+
Object.assign(body, extra());
|
|
1157
|
+
return request('PATCH', `${TG}/bot-profile`, body);
|
|
1158
|
+
}
|
|
1159
|
+
case 'getTelegramBotCommands': {
|
|
1160
|
+
const qs = { user };
|
|
1161
|
+
putFilled(ctx, qs, [['telegramLanguageCode', 'language_code']]);
|
|
1162
|
+
return request('GET', `${TG}/bot-commands`, qs);
|
|
1163
|
+
}
|
|
1164
|
+
case 'setTelegramBotCommands': {
|
|
1165
|
+
const raw = param(ctx, 'telegramCommands', {});
|
|
1166
|
+
const commands = ((_a = raw.command) !== null && _a !== void 0 ? _a : [])
|
|
1167
|
+
.map(entry => {
|
|
1168
|
+
var _a, _b;
|
|
1169
|
+
return ({
|
|
1170
|
+
command: String((_a = entry.command) !== null && _a !== void 0 ? _a : '').trim().replace(/^\//, ''),
|
|
1171
|
+
description: String((_b = entry.description) !== null && _b !== void 0 ? _b : '').trim(),
|
|
1172
|
+
});
|
|
1173
|
+
})
|
|
1174
|
+
.filter(entry => entry.command && entry.description);
|
|
1175
|
+
const body = { user, ...extra() };
|
|
1176
|
+
if (commands.length > 0)
|
|
1177
|
+
body.commands = commands;
|
|
1178
|
+
if (!body.commands)
|
|
1179
|
+
fail(ctx, 'Add at least one command with a description');
|
|
1180
|
+
putFilled(ctx, body, [['telegramLanguageCode', 'language_code']]);
|
|
1181
|
+
return request('POST', `${TG}/bot-commands`, body);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return fail(ctx, `Unsupported Telegram operation: ${ctx.operation}`);
|
|
1185
|
+
};
|
|
1186
|
+
const BS = '/uploadposts/bluesky';
|
|
1187
|
+
const BLUESKY_PAGING = [['blueskyPageSize', 'limit'], ['blueskyCursor', 'cursor']];
|
|
1188
|
+
const buildBlueskyRequest = (ctx, user) => {
|
|
1189
|
+
switch (ctx.operation) {
|
|
1190
|
+
case 'getBlueskyProfile': {
|
|
1191
|
+
const qs = { user };
|
|
1192
|
+
putFilled(ctx, qs, [['blueskyActor', 'actor']]);
|
|
1193
|
+
return request('GET', `${BS}/profile`, qs);
|
|
1194
|
+
}
|
|
1195
|
+
case 'getBlueskyNotifications': {
|
|
1196
|
+
const qs = { user };
|
|
1197
|
+
const reasons = param(ctx, 'blueskyReasons', []);
|
|
1198
|
+
if (Array.isArray(reasons) && reasons.length > 0)
|
|
1199
|
+
qs.reasons = reasons.join(',');
|
|
1200
|
+
putFilled(ctx, qs, BLUESKY_PAGING);
|
|
1201
|
+
return request('GET', `${BS}/notifications`, qs);
|
|
1202
|
+
}
|
|
1203
|
+
case 'getBlueskyUnreadCount':
|
|
1204
|
+
return request('GET', `${BS}/notifications/unread-count`, { user });
|
|
1205
|
+
case 'searchBlueskyPosts': {
|
|
1206
|
+
const qs = { user, q: requireStr(ctx, 'blueskyQuery', 'Search Query') };
|
|
1207
|
+
putFilled(ctx, qs, [
|
|
1208
|
+
['blueskySort', 'sort'],
|
|
1209
|
+
['blueskyAuthor', 'author'],
|
|
1210
|
+
['blueskyLang', 'lang'],
|
|
1211
|
+
['blueskySince', 'since'],
|
|
1212
|
+
['blueskyUntil', 'until'],
|
|
1213
|
+
...BLUESKY_PAGING,
|
|
1214
|
+
]);
|
|
1215
|
+
return request('GET', `${BS}/search/posts`, qs);
|
|
1216
|
+
}
|
|
1217
|
+
case 'searchBlueskyActors': {
|
|
1218
|
+
const qs = { user, q: requireStr(ctx, 'blueskyQuery', 'Search Query') };
|
|
1219
|
+
putFilled(ctx, qs, BLUESKY_PAGING);
|
|
1220
|
+
return request('GET', `${BS}/search/actors`, qs);
|
|
1221
|
+
}
|
|
1222
|
+
case 'listBlueskyDrafts': {
|
|
1223
|
+
const qs = { user };
|
|
1224
|
+
putFilled(ctx, qs, BLUESKY_PAGING);
|
|
1225
|
+
return request('GET', `${BS}/drafts`, qs);
|
|
1226
|
+
}
|
|
1227
|
+
case 'createBlueskyDraft': {
|
|
1228
|
+
const body = { user };
|
|
1229
|
+
const posts = parseJson(ctx, param(ctx, 'blueskyDraftPosts', ''), 'Draft Posts');
|
|
1230
|
+
if (posts !== undefined) {
|
|
1231
|
+
if (!Array.isArray(posts))
|
|
1232
|
+
fail(ctx, 'Draft Posts must be a JSON array of posts');
|
|
1233
|
+
body.posts = posts;
|
|
1234
|
+
}
|
|
1235
|
+
else {
|
|
1236
|
+
putFilled(ctx, body, [['blueskyDraftText', 'text']]);
|
|
1237
|
+
}
|
|
1238
|
+
if (!body.posts && !body.text)
|
|
1239
|
+
fail(ctx, 'Set Draft Text or Draft Posts');
|
|
1240
|
+
putFilled(ctx, body, [['blueskyDraftLangs', 'langs'], ['blueskyDraftReplySettings', 'reply_settings']]);
|
|
1241
|
+
return request('POST', `${BS}/drafts`, body);
|
|
1242
|
+
}
|
|
1243
|
+
case 'deleteBlueskyDraft': {
|
|
1244
|
+
const draftId = encodeURIComponent(requireStr(ctx, 'blueskyDraftId', 'Draft ID'));
|
|
1245
|
+
const body = { user };
|
|
1246
|
+
if (bool(ctx, 'blueskyConfirm'))
|
|
1247
|
+
body.confirm = true;
|
|
1248
|
+
return request('DELETE', `${BS}/drafts/${draftId}`, body);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
return fail(ctx, `Unsupported Bluesky operation: ${ctx.operation}`);
|
|
1252
|
+
};
|
|
1253
|
+
const GB = '/uploadposts/google-business';
|
|
1254
|
+
const GBP_PAGING = [['gbpApiPageSize', 'page_size'], ['gbpApiPageCursor', 'page_token']];
|
|
1255
|
+
const buildGoogleBusinessRequest = (ctx, user) => {
|
|
1256
|
+
const located = () => {
|
|
1257
|
+
const payload = { user };
|
|
1258
|
+
putFilled(ctx, payload, [['gbpApiLocationId', 'location_id']]);
|
|
1259
|
+
return payload;
|
|
1260
|
+
};
|
|
1261
|
+
switch (ctx.operation) {
|
|
1262
|
+
case 'listGbpPosts': {
|
|
1263
|
+
const qs = located();
|
|
1264
|
+
putFilled(ctx, qs, GBP_PAGING);
|
|
1265
|
+
return request('GET', `${GB}/posts`, qs);
|
|
1266
|
+
}
|
|
1267
|
+
case 'getGbpPost':
|
|
1268
|
+
return request('GET', `${GB}/posts/get`, { user, post_id: requireStr(ctx, 'gbpApiPostId', 'Post ID') });
|
|
1269
|
+
case 'listGbpReviews': {
|
|
1270
|
+
const qs = located();
|
|
1271
|
+
putFilled(ctx, qs, [...GBP_PAGING, ['gbpApiOrderBy', 'order_by']]);
|
|
1272
|
+
return request('GET', `${GB}/reviews`, qs);
|
|
1273
|
+
}
|
|
1274
|
+
case 'getGbpReview':
|
|
1275
|
+
return request('GET', `${GB}/reviews/get`, { user, review_name: requireStr(ctx, 'gbpApiReviewName', 'Review Name') });
|
|
1276
|
+
case 'getGbpPerformance': {
|
|
1277
|
+
const qs = located();
|
|
1278
|
+
putFilled(ctx, qs, [['gbpApiMetrics', 'metrics'], ['gbpApiStartDate', 'start_date'], ['gbpApiEndDate', 'end_date']]);
|
|
1279
|
+
return request('GET', `${GB}/performance`, qs);
|
|
1280
|
+
}
|
|
1281
|
+
case 'getGbpSearchKeywords': {
|
|
1282
|
+
const qs = located();
|
|
1283
|
+
putFilled(ctx, qs, [['gbpApiStartMonth', 'start_month'], ['gbpApiEndMonth', 'end_month'], ...GBP_PAGING]);
|
|
1284
|
+
return request('GET', `${GB}/performance/keywords`, qs);
|
|
1285
|
+
}
|
|
1286
|
+
case 'getGbpLocationInfo': {
|
|
1287
|
+
const qs = located();
|
|
1288
|
+
putFilled(ctx, qs, [['gbpApiReadMask', 'read_mask']]);
|
|
1289
|
+
return request('GET', `${GB}/location-info`, qs);
|
|
1290
|
+
}
|
|
1291
|
+
case 'updateGbpLocationInfo': {
|
|
1292
|
+
const body = located();
|
|
1293
|
+
const mode = str(ctx, 'gbpApiEditMode') || 'legacy';
|
|
1294
|
+
body.edit_mode = mode;
|
|
1295
|
+
putFilled(ctx, body, [['gbpApiDescription', 'description'], ['gbpApiWebsite', 'website'], ['gbpApiPhone', 'phone']]);
|
|
1296
|
+
if (bool(ctx, 'gbpApiValidateOnly'))
|
|
1297
|
+
body.validate_only = true;
|
|
1298
|
+
if (mode === 'strict') {
|
|
1299
|
+
if (bool(ctx, 'gbpApiDryRun'))
|
|
1300
|
+
body.dry_run = true;
|
|
1301
|
+
if (bool(ctx, 'googleBusinessConfirm'))
|
|
1302
|
+
body.confirm = true;
|
|
1303
|
+
}
|
|
1304
|
+
Object.assign(body, jsonObjectParam(ctx, 'googleBusinessExtraFields', 'Extra Fields (JSON)'));
|
|
1305
|
+
return request('PATCH', `${GB}/location-info`, body);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
return fail(ctx, `Unsupported Google Business operation: ${ctx.operation}`);
|
|
1309
|
+
};
|
|
1310
|
+
const buildNetworkRequest = (node, itemIndex, resource, operation) => {
|
|
1311
|
+
const ctx = { node, itemIndex, operation };
|
|
1312
|
+
const profile = requireStr(ctx, 'networkProfile', 'Profile');
|
|
1313
|
+
if (resource === 'queue')
|
|
1314
|
+
return buildQueueRequest(ctx, profile);
|
|
1315
|
+
if (resource === 'telegram')
|
|
1316
|
+
return buildTelegramRequest(ctx, profile);
|
|
1317
|
+
if (resource === 'bluesky')
|
|
1318
|
+
return buildBlueskyRequest(ctx, profile);
|
|
1319
|
+
return buildGoogleBusinessRequest(ctx, profile);
|
|
1320
|
+
};
|
|
1321
|
+
exports.buildNetworkRequest = buildNetworkRequest;
|
|
1322
|
+
//# sourceMappingURL=NetworkOperations.js.map
|