n8n-nodes-postwire 0.2.1 → 0.2.3

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.
@@ -51,7 +51,7 @@ class PostWire {
51
51
  name: 'Get Account',
52
52
  value: 'me',
53
53
  description: 'Plan, usage this month and connected accounts',
54
- action: 'Get the PostWire account',
54
+ action: 'Get account',
55
55
  },
56
56
  {
57
57
  name: 'Publish',
@@ -142,6 +142,18 @@ class PostWire {
142
142
  show: { operation: ['generate', 'publish', 'generateAndPublish', 'schedule'] },
143
143
  },
144
144
  options: [
145
+ {
146
+ displayName: 'Media Type',
147
+ name: 'mediaType',
148
+ type: 'options',
149
+ default: 'auto',
150
+ options: [
151
+ { name: 'Detect From the URL', value: 'auto' },
152
+ { name: 'Video', value: 'video' },
153
+ { name: 'Image', value: 'image' },
154
+ ],
155
+ description: 'Only needed when the link has no file extension — a signed CDN URL or a share link. Detection reads the extension and, when there is none, follows what the chosen networks require.',
156
+ },
145
157
  {
146
158
  displayName: 'Brand',
147
159
  name: 'brandId',
@@ -204,21 +216,40 @@ class PostWire {
204
216
  });
205
217
  }
206
218
  // Media rules, checked before the request so the message names the fix rather than the symptom.
207
- const isVideo = /\.(mp4|mov|webm|m3u8|avi|mkv|m4v)(\?|$)/i.test(mediaUrl);
219
+ //
220
+ // The classifier used to answer only video-or-photo, and called everything without a
221
+ // known video extension a photo. A signed CDN link, one ending in #t=30, or a share URL
222
+ // with no extension at all was therefore "a photo", and the check below then threw and
223
+ // stopped the whole workflow — for a video that would have published perfectly well.
224
+ // Three answers now, and an unknown one is never grounds for refusing to try: the
225
+ // network is the thing that gets to decide, not a regular expression over a filename.
226
+ const declared = opts.mediaType || 'auto';
227
+ const kind = !mediaUrl
228
+ ? 'none'
229
+ : declared === 'video' || declared === 'image'
230
+ ? declared
231
+ : /\.(mp4|mov|webm|m3u8|avi|mkv|m4v)(\?|#|$)/i.test(mediaUrl)
232
+ ? 'video'
233
+ : /\.(jpe?g|png|gif|webp|heic|heif|avif|bmp|tiff?)(\?|#|$)/i.test(mediaUrl)
234
+ ? 'image'
235
+ : 'unknown';
208
236
  const blocked = platforms.filter((p) => {
209
237
  const need = needOf(p);
210
238
  if (!need)
211
239
  return false;
212
240
  if (need === 'video')
213
- return !isVideo;
214
- return !mediaUrl;
241
+ return kind === 'image' || kind === 'none';
242
+ return kind === 'none';
215
243
  });
216
244
  if (blocked.length) {
217
245
  const wantsVideo = blocked.some((p) => needOf(p) === 'video');
218
246
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `${blocked.join(' and ')} will not accept a post without ${wantsVideo ? 'a video' : 'an image or video'}. Set Media URL to a direct file link, or remove ${blocked.length > 1 ? 'those networks' : 'that network'} from the list.`, { itemIndex: i });
219
247
  }
220
- const photoUrl = mediaUrl && !isVideo ? mediaUrl : undefined;
221
- const videoUrl = isVideo ? mediaUrl : undefined;
248
+ // An unrecognised link still has to go in one of the two fields the API has. Send it as the
249
+ // one the chosen networks need — that is the only reading of it that can succeed.
250
+ const treatAsVideo = kind === 'video' || (kind === 'unknown' && platforms.some((p) => needOf(p) === 'video'));
251
+ const videoUrl = mediaUrl && treatAsVideo ? mediaUrl : undefined;
252
+ const photoUrl = mediaUrl && !treatAsVideo ? mediaUrl : undefined;
222
253
  let perPlatform;
223
254
  if (operation === 'generate' || operation === 'generateAndPublish') {
224
255
  const prompt = this.getNodeParameter('prompt', i);
@@ -293,8 +324,9 @@ class PostWire {
293
324
  // Our own checks already throw NodeOperationError with a message that names the fix;
294
325
  // re-wrapping those would bury it. Anything else is an HTTP failure, and n8n renders
295
326
  // a NodeApiError with the node's context instead of a bare fetch stack.
296
- if (error instanceof n8n_workflow_1.NodeOperationError)
297
- throw error;
327
+ if (error instanceof n8n_workflow_1.NodeOperationError) {
328
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i });
329
+ }
298
330
  throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
299
331
  }
300
332
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-postwire",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Publish one idea natively to TikTok, Instagram, YouTube, LinkedIn, X, Bluesky, Mastodon, Telegram, Discord and Reddit from n8n — a different post written for each network, via PostWire.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",