@aikeytake/social-automation 2.0.5 → 2.0.7

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/index.js +101 -70
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikeytake/social-automation",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "Content research and aggregation tool for AI agents",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  "author": "aikeytake",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
- "@aikeytake/social-automation": "2.0.4",
27
+ "@aikeytake/social-automation": "2.0.5",
28
28
  "@supabase/supabase-js": "^2.47.0",
29
29
  "axios": "^1.7.9",
30
30
  "cheerio": "^1.0.0",
package/src/index.js CHANGED
@@ -7,7 +7,15 @@ import apiFetch from './fetchers/api.js';
7
7
  import fs from 'fs';
8
8
  import path from 'path';
9
9
  import { fileURLToPath } from 'url';
10
- import defaultConfig from '../config/sources.json';
10
+ import { createRequire } from 'module';
11
+
12
+ dotenv.config();
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const defaultConfig = require('../config/sources.json');
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+ const logger = createLogger('Main');
11
19
 
12
20
  dotenv.config();
13
21
 
@@ -133,20 +141,26 @@ function getDateString() {
133
141
  }
134
142
 
135
143
  async function saveSourceData(source, items, today) {
136
- const todayFolder = path.join(__dirname, '../data', today);
137
- if (!fs.existsSync(todayFolder)) {
138
- fs.mkdirSync(todayFolder, { recursive: true });
144
+ try {
145
+ const todayFolder = path.join(__dirname, '../data', today);
146
+ if (!fs.existsSync(todayFolder)) {
147
+ fs.mkdirSync(todayFolder, { recursive: true });
148
+ }
149
+ const filePath = path.join(todayFolder, `${source}.json`);
150
+ const data = {
151
+ date: today,
152
+ source: source,
153
+ total_items: items.length,
154
+ scraped_at: new Date().toISOString(),
155
+ items: items
156
+ };
157
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
158
+ } catch (err) {
159
+ // Vercel ephemeral filesystem - ignore write errors when saving to filesystem
160
+ if (err.code !== 'ENOENT' && err.code !== 'EACCES') {
161
+ logger.warn(`saveSourceData skipped: ${err.message}`);
162
+ }
139
163
  }
140
-
141
- const filePath = path.join(todayFolder, `${source}.json`);
142
- const data = {
143
- date: today,
144
- source: source,
145
- total_items: items.length,
146
- scraped_at: new Date().toISOString(),
147
- items: items
148
- };
149
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
150
164
  }
151
165
 
152
166
  async function saveToSupabase(supabase, items, date) {
@@ -177,66 +191,83 @@ async function saveToSupabase(supabase, items, date) {
177
191
  }
178
192
 
179
193
  async function generateCombinedFiles(results, today) {
180
- const todayFolder = path.join(__dirname, '../data', today);
181
-
182
- // Load all source files
183
- const allItems = [];
184
- const sourceFiles = fs.readdirSync(todayFolder)
185
- .filter(f => f.endsWith('.json') && f !== 'all.json' && f !== 'trending.json');
186
- for (const file of sourceFiles) {
187
- const filePath = path.join(todayFolder, file);
188
- const content = fs.readFileSync(filePath, 'utf-8');
189
- const data = JSON.parse(content);
190
- allItems.push(...(data.items || []));
191
- }
194
+ try {
195
+ const todayFolder = path.join(__dirname, '../data', today);
192
196
 
193
- // Save all.json
194
- const allData = {
195
- date: today,
196
- generated_at: new Date().toISOString(),
197
- total_items: allItems.length,
198
- sources: results.sources,
199
- items: allItems
200
- };
201
- fs.writeFileSync(path.join(todayFolder, 'all.json'), JSON.stringify(allData, null, 2));
202
-
203
- // Generate trending.json (top 20 by score with source diversity)
204
- const scoredItems = allItems
205
- .filter(item => item.metadata?.score || item.engagement?.upvotes || item.engagement?.points || 0)
206
- .map(item => ({ ...item, combined_score: calculateScore(item) }))
207
- .sort((a, b) => b.combined_score - a.combined_score);
208
-
209
- // Apply source diversity: max 5 items per source
210
- const trendingBySource = {};
211
- const finalTrending = [];
212
- for (const item of scoredItems) {
213
- const source = item.source || 'unknown';
214
- if (!trendingBySource[source]) trendingBySource[source] = 0;
215
- if (trendingBySource[source] < 5) {
216
- trendingBySource[source]++;
217
- finalTrending.push(item);
197
+ // Load all source files
198
+ const allItems = [];
199
+ let sourceFiles = [];
200
+ try {
201
+ sourceFiles = fs.readdirSync(todayFolder)
202
+ .filter(f => f.endsWith('.json') && f !== 'all.json' && f !== 'trending.json');
203
+ } catch {
204
+ // Folder may not exist - skip loading
205
+ sourceFiles = [];
206
+ }
207
+ for (const file of sourceFiles) {
208
+ try {
209
+ const filePath = path.join(todayFolder, file);
210
+ const content = fs.readFileSync(filePath, 'utf-8');
211
+ const data = JSON.parse(content);
212
+ allItems.push(...(data.items || []));
213
+ } catch {
214
+ // Skip unreadable files
215
+ }
218
216
  }
219
- if (finalTrending.length >= 20) break;
220
- }
221
217
 
222
- const trendingData = {
223
- date: today,
224
- generated_at: new Date().toISOString(),
225
- total_items: finalTrending.length,
226
- items: finalTrending.map((item, index) => ({
227
- rank: index + 1,
228
- score: item.combined_score,
229
- sources: getItemSources(item),
230
- title: item.title,
231
- url: item.url || item.link,
232
- summary: extractSummary(item),
233
- keywords: extractKeywords(item),
234
- engagement: item.engagement || item.metadata || {}
235
- }))
236
- };
218
+ // Save all.json
219
+ const allData = {
220
+ date: today,
221
+ generated_at: new Date().toISOString(),
222
+ total_items: allItems.length,
223
+ sources: results.sources,
224
+ items: allItems
225
+ };
226
+ fs.writeFileSync(path.join(todayFolder, 'all.json'), JSON.stringify(allData, null, 2));
227
+
228
+ // Generate trending.json (top 20 by score with source diversity)
229
+ const scoredItems = allItems
230
+ .filter(item => item.metadata?.score || item.engagement?.upvotes || item.engagement?.points || 0)
231
+ .map(item => ({ ...item, combined_score: calculateScore(item) }))
232
+ .sort((a, b) => b.combined_score - a.combined_score);
233
+
234
+ // Apply source diversity: max 5 items per source
235
+ const trendingBySource = {};
236
+ const finalTrending = [];
237
+ for (const item of scoredItems) {
238
+ const source = item.source || 'unknown';
239
+ if (!trendingBySource[source]) trendingBySource[source] = 0;
240
+ if (trendingBySource[source] < 5) {
241
+ trendingBySource[source]++;
242
+ finalTrending.push(item);
243
+ }
244
+ if (finalTrending.length >= 20) break;
245
+ }
237
246
 
238
- fs.writeFileSync(path.join(todayFolder, 'trending.json'), JSON.stringify(trendingData, null, 2));
239
- logger.success(`✅ Generated: trending.json (${finalTrending.length} items)`);
247
+ const trendingData = {
248
+ date: today,
249
+ generated_at: new Date().toISOString(),
250
+ total_items: finalTrending.length,
251
+ items: finalTrending.map((item, index) => ({
252
+ rank: index + 1,
253
+ score: item.combined_score,
254
+ sources: getItemSources(item),
255
+ title: item.title,
256
+ url: item.url || item.link,
257
+ summary: extractSummary(item),
258
+ keywords: extractKeywords(item),
259
+ engagement: item.engagement || item.metadata || {}
260
+ }))
261
+ };
262
+
263
+ fs.writeFileSync(path.join(todayFolder, 'trending.json'), JSON.stringify(trendingData, null, 2));
264
+ logger.success(`✅ Generated: trending.json (${finalTrending.length} items)`);
265
+ } catch (err) {
266
+ // Vercel ephemeral filesystem - ignore write errors
267
+ if (err.code !== 'ENOENT' && err.code !== 'EACCES') {
268
+ logger.warn(`generateCombinedFiles skipped: ${err.message}`);
269
+ }
270
+ }
240
271
  }
241
272
 
242
273
  function calculateScore(item) {