@ferchy/n8n-nodes-aimc-toolkit 0.1.18 → 0.1.21

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 CHANGED
@@ -4,7 +4,7 @@ AIMC Toolkit is a community node package for n8n with focused nodes:
4
4
 
5
5
  - **AIMC Code**: run JavaScript with a practical toolbox of libraries.
6
6
  - **AIMC Media**: FFmpeg-powered media operations without extra glue nodes.
7
- - **AIMC Social Scraper**: scrape content from social media platforms (TikTok, Instagram, etc.). Note: YouTube is available via AIMC Code node.
7
+ - **AIMC Social Scraper**: scrape content from social media platforms (coming soon).
8
8
 
9
9
  ## Why I Built This
10
10
 
@@ -23,7 +23,7 @@ n8n is powerful, but real workflows often need basic utilities (validation, pars
23
23
 
24
24
  - **Fewer nodes, cleaner flows**: consolidate multiple steps into one code node.
25
25
  - **Media ready**: convert, compress, merge, and inspect media in one place.
26
- - **Social scraping**: scrape TikTok, Instagram, and more with a simple UI.
26
+ - **Social scraping**: scrape social media platforms with a simple UI (coming soon).
27
27
  - **Practical libraries**: parsing, validation, dates, and web utilities built in.
28
28
 
29
29
  ## Installation
@@ -113,7 +113,7 @@ Inputs: items are available as `items` (all) or `item` (single)
113
113
  Return: return a plain object or array of objects (JSON-safe)
114
114
  Libraries (globals): axios, lodash (_), zod (z), joi (Joi), yup, Ajv, validator, dayjs, dateFns, dateFnsTz, moment,
115
115
  cheerio, papaparse (Papa), yaml (YAML), xml2js, XMLParser, qs, FormData, uuid, nanoid, bytes, cronParser, ms,
116
- fuzzy, stringSimilarity, slug, pluralize, jsonDiff, htmlToText, marked, qrcode/QRCode, ytdl, tiktokScraper/TikTokScraper, ffmpeg, ffmpegStatic, ffprobeStatic.
116
+ fuzzy, stringSimilarity, slug, pluralize, jsonDiff, htmlToText, marked, qrcode/QRCode, ytdl, ffmpeg, ffmpegStatic, ffprobeStatic.
117
117
  Helpers: utils.now(), utils.safeJson(), utils.toArray()
118
118
  Please return only the JavaScript code for the AIMC Code node.
119
119
  ```
@@ -193,85 +193,12 @@ Use **Input Mode = File Path** to avoid loading big files into memory.
193
193
 
194
194
  ### AIMC Social Scraper
195
195
 
196
- > **💡 Tip**: You can also use TikTok scraper programmatically in the **AIMC Code** node using `tiktokScraper` or `TikTokScraper` global variables. This UI node provides a simpler interface for common scraping tasks.
196
+ **Coming Soon!**
197
197
 
198
- > **⚠️ Important Legal Notice**: This node uses web scraping techniques, not official APIs. It is provided for educational and personal use only. Users are responsible for complying with:
199
- > - TikTok's Terms of Service
200
- > - Applicable laws and regulations in their jurisdiction
201
- > - Rate limiting and respectful usage practices
202
- > - Copyright and intellectual property rights
203
- >
204
- > **This is not an official API support.** This scraper uses TikTok's web interface to extract media and metadata. Use at your own risk. The authors and maintainers are not responsible for any misuse or violations of terms of service.
205
-
206
- **Platforms**
207
- - **TikTok** (fully supported)
208
- - Instagram, Twitter/X (coming soon)
198
+ Social media scraping functionality is currently under development. This node will support scraping content from various platforms including TikTok, Instagram, Twitter/X, and more.
209
199
 
210
200
  **Note**: YouTube support is already available via the **AIMC Code** node using the `ytdl` library. See the Media Helpers section for details.
211
201
 
212
- **TikTok Scrape Types**
213
- - **User Posts**: Scrape posts from a specific user
214
- - **Hashtag**: Scrape posts from a hashtag
215
- - **Trending**: Get trending posts
216
- - **Single Video**: Get metadata for a specific video
217
-
218
- **Key Options**
219
- - **Number of Posts**: How many posts to scrape (1-1000)
220
- - **Options** (collapsible section):
221
- - **No Watermark**: Download videos without TikTok watermark
222
- - **HD Video**: Download in HD quality
223
- - **By User ID**: Treat username as user ID (for large IDs)
224
- - **Session Cookie** (Advanced): Only needed if you encounter rate limits - see instructions below
225
- - **No Watermark**: Download videos without TikTok watermark
226
- - **HD Video**: Download in HD quality
227
- - **By User ID**: Treat username as user ID (for large IDs)
228
-
229
- **Example: Scrape User Posts**
230
- ```
231
- Platform: TikTok
232
- Scrape Type: User Posts
233
- Username: username
234
- Number of Posts: 50
235
- Options (expand if needed):
236
- - No Watermark: true
237
- - Session Cookie: (only if you hit rate limits)
238
- ```
239
-
240
- **Example: Scrape Hashtag**
241
- ```
242
- Platform: TikTok
243
- Scrape Type: Hashtag
244
- Hashtag: fyp
245
- Number of Posts: 100
246
- ```
247
-
248
- **Example: Get Trending**
249
- ```
250
- Platform: TikTok
251
- Scrape Type: Trending
252
- Number of Posts: 30
253
- ```
254
-
255
- **Session Cookie (Advanced - Optional)**
256
- The scraper works **without cookies by default**. Session cookies are only needed if you encounter rate limits. They're hidden in the **Options** section - you don't need to worry about them unless you have issues.
257
-
258
- **When you might need a session cookie:**
259
- - You're scraping many posts and getting rate limited
260
- - You're seeing captcha challenges
261
- - You need to scrape large amounts of data regularly
262
-
263
- **To get a session cookie (only if needed):**
264
- 1. Open TikTok in your browser and log in
265
- 2. Open DevTools (F12 or Right-click > Inspect)
266
- 3. Go to **Application** tab > **Cookies** > `https://www.tiktok.com`
267
- 4. Find the `sid_tt` cookie
268
- 5. Copy the entire value (e.g., `sid_tt=abc123def456...`)
269
- 6. Expand **Options** in the node and paste into the Session Cookie field
270
-
271
- **Tip**: Start without a cookie. Most users won't need it. Only add one if you hit rate limits.
272
-
273
- **Note**: Session cookies help avoid rate limits and captchas. They're optional but recommended for production use.
274
-
275
202
  ## Library Reference (AIMC Code)
276
203
 
277
204
  Libraries are available as globals or via `libs.<name>`.
@@ -344,7 +271,6 @@ Provide Python code and set a variable named `result` to return output.
344
271
  ### Media Helpers
345
272
  - `qrcode` (global `QRCode` or `qrcode`): generate QR codes as data URLs or images.
346
273
  - `@distube/ytdl-core` (global `ytdl`): download media from supported sources. Use for media ingestion flows.
347
- - `tiktok-scraper` (global `tiktokScraper` or `TikTokScraper`): scrape TikTok content including users, hashtags, trending topics, videos, and metadata. Supports downloading videos (with/without watermarks), session cookies, and proxies.
348
274
  - `fluent-ffmpeg` (global `ffmpeg`): build FFmpeg pipelines in JS when you need custom media logic.
349
275
  - `ffmpeg-static` (global `ffmpegStatic`): path to a bundled FFmpeg binary (if available).
350
276
  - `ffprobe-static` (global `ffprobeStatic`): path to a bundled ffprobe binary (if available).
@@ -382,7 +308,7 @@ Environment variables:
382
308
  The AIMC Social Scraper node uses web scraping techniques to extract data from social media platforms. This is **not** an official API integration and is provided for educational and personal use only.
383
309
 
384
310
  **Important Points:**
385
- - This scraper uses the web interface of platforms (TikTok, etc.), not official APIs
311
+ - This scraper uses the web interface of platforms, not official APIs
386
312
  - Users must comply with each platform's Terms of Service
387
313
  - Users must comply with applicable laws and regulations (GDPR, CCPA, etc.)
388
314
  - Users are responsible for respecting rate limits and avoiding abusive behavior
@@ -1,55 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AimcSocial = void 0;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- let tiktokScraper = null;
6
- function getTikTokScraper() {
7
- if (!tiktokScraper) {
8
- try {
9
- tiktokScraper = require('tiktok-scraper');
10
- }
11
- catch (error) {
12
- throw new Error('TikTok scraper not available. Please ensure tiktok-scraper is installed.');
13
- }
14
- }
15
- return tiktokScraper;
16
- }
17
- async function scrapeTikTokUser(username, options) {
18
- const scraper = getTikTokScraper();
19
- return await scraper.user(username, {
20
- number: options.number || 20,
21
- sessionList: options.sessionList || [],
22
- by_user_id: options.byUserId || false,
23
- noWaterMark: options.noWaterMark || false,
24
- hdVideo: options.hdVideo || false,
25
- });
26
- }
27
- async function scrapeTikTokHashtag(hashtag, options) {
28
- const scraper = getTikTokScraper();
29
- return await scraper.hashtag(hashtag, {
30
- number: options.number || 20,
31
- sessionList: options.sessionList || [],
32
- noWaterMark: options.noWaterMark || false,
33
- hdVideo: options.hdVideo || false,
34
- });
35
- }
36
- async function scrapeTikTokTrend(options) {
37
- const scraper = getTikTokScraper();
38
- return await scraper.trend('', {
39
- number: options.number || 20,
40
- sessionList: options.sessionList || [],
41
- noWaterMark: options.noWaterMark || false,
42
- hdVideo: options.hdVideo || false,
43
- });
44
- }
45
- async function scrapeTikTokVideo(videoUrl, options) {
46
- const scraper = getTikTokScraper();
47
- return await scraper.video(videoUrl, {
48
- sessionList: options.sessionList || [],
49
- noWaterMark: options.noWaterMark || false,
50
- hdVideo: options.hdVideo || false,
51
- });
52
- }
53
4
  class AimcSocial {
54
5
  constructor() {
55
6
  this.description = {
@@ -58,7 +9,7 @@ class AimcSocial {
58
9
  icon: 'file:aimc-social.svg',
59
10
  group: ['transform'],
60
11
  version: 1,
61
- description: 'Scrape content from social media platforms (TikTok, Instagram, etc.). Note: YouTube is available via AIMC Code node using ytdl.',
12
+ description: 'Scrape content from social media platforms. Coming soon!',
62
13
  defaults: {
63
14
  name: 'AIMC Social Scraper',
64
15
  },
@@ -75,133 +26,7 @@ class AimcSocial {
75
26
  { name: 'Twitter/X', value: 'twitter' },
76
27
  ],
77
28
  default: 'tiktok',
78
- description: 'Select the social media platform to scrape. Note: YouTube is available via AIMC Code node using the ytdl library.',
79
- },
80
- {
81
- displayName: 'Scrape Type',
82
- name: 'scrapeType',
83
- type: 'options',
84
- options: [
85
- { name: 'User Posts', value: 'user' },
86
- { name: 'Hashtag', value: 'hashtag' },
87
- { name: 'Trending', value: 'trending' },
88
- { name: 'Single Video', value: 'video' },
89
- ],
90
- default: 'user',
91
- displayOptions: {
92
- show: {
93
- platform: ['tiktok'],
94
- },
95
- },
96
- description: 'What type of content to scrape',
97
- },
98
- {
99
- displayName: 'Username',
100
- name: 'username',
101
- type: 'string',
102
- default: '',
103
- required: true,
104
- displayOptions: {
105
- show: {
106
- platform: ['tiktok'],
107
- scrapeType: ['user'],
108
- },
109
- },
110
- placeholder: 'username or @username',
111
- description: 'TikTok username (with or without @ symbol - will be automatically removed)',
112
- },
113
- {
114
- displayName: 'Hashtag',
115
- name: 'hashtag',
116
- type: 'string',
117
- default: '',
118
- required: true,
119
- displayOptions: {
120
- show: {
121
- platform: ['tiktok'],
122
- scrapeType: ['hashtag'],
123
- },
124
- },
125
- placeholder: 'fyp or #fyp',
126
- description: 'Hashtag to scrape (with or without # symbol - will be automatically removed)',
127
- },
128
- {
129
- displayName: 'Video URL',
130
- name: 'videoUrl',
131
- type: 'string',
132
- default: '',
133
- required: true,
134
- displayOptions: {
135
- show: {
136
- platform: ['tiktok'],
137
- scrapeType: ['video'],
138
- },
139
- },
140
- placeholder: 'https://www.tiktok.com/@username/video/1234567890',
141
- description: 'Full URL of the TikTok video',
142
- },
143
- {
144
- displayName: 'Number of Posts',
145
- name: 'number',
146
- type: 'number',
147
- default: 20,
148
- typeOptions: {
149
- minValue: 1,
150
- maxValue: 1000,
151
- },
152
- displayOptions: {
153
- show: {
154
- platform: ['tiktok'],
155
- scrapeType: ['user', 'hashtag', 'trending'],
156
- },
157
- },
158
- description: 'Number of posts to scrape',
159
- },
160
- {
161
- displayName: 'Options',
162
- name: 'options',
163
- type: 'collection',
164
- placeholder: 'Add Option',
165
- default: {},
166
- displayOptions: {
167
- show: {
168
- platform: ['tiktok'],
169
- },
170
- },
171
- options: [
172
- {
173
- displayName: 'No Watermark',
174
- name: 'noWaterMark',
175
- type: 'boolean',
176
- default: false,
177
- description: 'Whether to download videos without watermark',
178
- },
179
- {
180
- displayName: 'HD Video',
181
- name: 'hdVideo',
182
- type: 'boolean',
183
- default: false,
184
- description: 'Whether to download HD quality videos',
185
- },
186
- {
187
- displayName: 'By User ID',
188
- name: 'byUserId',
189
- type: 'boolean',
190
- default: false,
191
- description: 'If true, interpret the username as a user ID (only applies to User Posts scrape type)',
192
- },
193
- {
194
- displayName: 'Session Cookie',
195
- name: 'sessionCookie',
196
- type: 'string',
197
- typeOptions: {
198
- password: true,
199
- },
200
- default: '',
201
- placeholder: 'sid_tt=abc123...',
202
- description: '[Advanced] TikTok session cookie to reduce rate limits. Only needed if you encounter rate limits. Leave empty to use without. Format: "sid_tt=abc123def456..."',
203
- },
204
- ],
29
+ description: 'Select the social media platform to scrape',
205
30
  },
206
31
  ],
207
32
  };
@@ -210,84 +35,15 @@ class AimcSocial {
210
35
  const items = this.getInputData();
211
36
  const returnData = [];
212
37
  for (let i = 0; i < items.length; i++) {
213
- try {
214
- const platform = this.getNodeParameter('platform', i);
215
- const scrapeType = this.getNodeParameter('scrapeType', i);
216
- const options = this.getNodeParameter('options', i, {});
217
- let result;
218
- if (platform === 'tiktok') {
219
- // Get session cookie from options if provided
220
- const sessionCookie = options.sessionCookie || '';
221
- const sessionList = sessionCookie ? [sessionCookie] : [];
222
- if (scrapeType === 'user') {
223
- const usernameRaw = this.getNodeParameter('username', i);
224
- if (!usernameRaw || !usernameRaw.trim()) {
225
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Username is required. Please enter a TikTok username (without @ symbol).');
226
- }
227
- // Remove @ symbol if present and trim whitespace
228
- const username = usernameRaw.trim().replace(/^@/, '');
229
- const number = this.getNodeParameter('number', i, 20);
230
- result = await scrapeTikTokUser.call(this, username, {
231
- number,
232
- sessionList,
233
- byUserId: options.byUserId,
234
- noWaterMark: options.noWaterMark,
235
- hdVideo: options.hdVideo,
236
- });
237
- }
238
- else if (scrapeType === 'hashtag') {
239
- const hashtagRaw = this.getNodeParameter('hashtag', i);
240
- if (!hashtagRaw || !hashtagRaw.trim()) {
241
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Hashtag is required. Please enter a TikTok hashtag (without # symbol).');
242
- }
243
- // Remove # symbol if present and trim whitespace
244
- const hashtag = hashtagRaw.trim().replace(/^#/, '');
245
- const number = this.getNodeParameter('number', i, 20);
246
- result = await scrapeTikTokHashtag.call(this, hashtag, {
247
- number,
248
- sessionList,
249
- noWaterMark: options.noWaterMark,
250
- hdVideo: options.hdVideo,
251
- });
252
- }
253
- else if (scrapeType === 'trending') {
254
- const number = this.getNodeParameter('number', i, 20);
255
- result = await scrapeTikTokTrend.call(this, {
256
- number,
257
- sessionList,
258
- noWaterMark: options.noWaterMark,
259
- hdVideo: options.hdVideo,
260
- });
261
- }
262
- else if (scrapeType === 'video') {
263
- const videoUrl = this.getNodeParameter('videoUrl', i);
264
- result = await scrapeTikTokVideo.call(this, videoUrl, {
265
- sessionList,
266
- noWaterMark: options.noWaterMark,
267
- hdVideo: options.hdVideo,
268
- });
269
- }
270
- }
271
- else {
272
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Platform "${platform}" is not yet implemented. Currently only TikTok is supported.`);
273
- }
274
- returnData.push({
275
- json: result,
276
- pairedItem: { item: i },
277
- });
278
- }
279
- catch (error) {
280
- if (this.continueOnFail()) {
281
- returnData.push({
282
- json: {
283
- error: error instanceof Error ? error.message : String(error),
284
- },
285
- pairedItem: { item: i },
286
- });
287
- continue;
288
- }
289
- throw error;
290
- }
38
+ const platform = this.getNodeParameter('platform', i);
39
+ returnData.push({
40
+ json: {
41
+ message: 'AIMC Social Scraper is coming soon!',
42
+ platform: platform,
43
+ note: 'This feature is currently under development. Stay tuned for updates!',
44
+ },
45
+ pairedItem: { item: i },
46
+ });
291
47
  }
292
48
  return [returnData];
293
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ferchy/n8n-nodes-aimc-toolkit",
3
- "version": "0.1.18",
3
+ "version": "0.1.21",
4
4
  "description": "AIMC Toolkit nodes for n8n: code execution and media operations.",
5
5
  "license": "MIT",
6
6
  "author": "Ferchy",
@@ -88,7 +88,6 @@
88
88
  "uuid": "^11.1.0",
89
89
  "validator": "^13.11.0",
90
90
  "xml2js": "^0.6.2",
91
- "tiktok-scraper": "git+https://github.com/drawrowfly/tiktok-scraper.git",
92
91
  "yaml": "^2.8.1",
93
92
  "yup": "^1.7.0",
94
93
  "zod": "^3.25.76"