tangled
alpha
login
or
join now
indexx.dev
/
tweets2bsky
forked from
j4ck.xyz/tweets2bsky
0
fork
atom
A simple tool which lets you scrape twitter accounts and crosspost them to bluesky accounts! Comes with a CLI and a webapp for managing profiles! Works with images/videos/link embeds/threads.
0
fork
atom
overview
issues
pulls
pipelines
feat: add support for custom backfill limits in web UI
jack
2 months ago
90b70a02
435cc19b
+21
-12
3 changed files
expand all
collapse all
unified
split
public
index.html
src
index.ts
server.ts
+5
-3
public/index.html
···
207
207
};
208
208
209
209
const runBackfill = async (id, twitterUsername) => {
210
210
-
if (!confirm(`Run full history backfill for @${twitterUsername}? This may take a while.`)) return;
210
210
+
const limit = prompt(`How many tweets to backfill for @${twitterUsername}?`, "100");
211
211
+
if (limit === null) return; // Cancelled
212
212
+
211
213
try {
212
212
-
await axios.post(`/api/backfill/${id}`, {}, {
214
214
+
await axios.post(`/api/backfill/${id}`, { limit: parseInt(limit) || 100 }, {
213
215
headers: { Authorization: `Bearer ${token}` }
214
216
});
215
217
alert(`Backfill queued for @${twitterUsername}`);
···
280
282
);
281
283
}
282
284
283
283
-
const isBackfillQueued = (id) => status.pendingBackfills?.includes(id);
285
285
+
const isBackfillQueued = (id) => status.pendingBackfills?.some(b => (b.id || b) === id);
284
286
285
287
return (
286
288
<div>
+5
-3
src/index.ts
···
582
582
const agent = await getAgent(mapping);
583
583
if (!agent) continue;
584
584
585
585
-
if (forceBackfill || pendingBackfills.includes(mapping.id)) {
586
586
-
console.log(`[${mapping.twitterUsername}] Running backfill (limit 100)...`);
587
587
-
await importHistory(mapping.twitterUsername, 100, dryRun);
585
585
+
const backfillReq = pendingBackfills.find(b => b.id === mapping.id);
586
586
+
if (forceBackfill || backfillReq) {
587
587
+
const limit = backfillReq?.limit || 100;
588
588
+
console.log(`[${mapping.twitterUsername}] Running backfill (limit ${limit})...`);
589
589
+
await importHistory(mapping.twitterUsername, limit, dryRun);
588
590
clearBackfill(mapping.id);
589
591
console.log(`[${mapping.twitterUsername}] Backfill complete.`);
590
592
} else {
+11
-6
src/server.ts
···
17
17
// In-memory state for triggers and scheduling
18
18
let lastCheckTime = Date.now();
19
19
let nextCheckTime = Date.now() + (getConfig().checkIntervalMinutes || 5) * 60 * 1000;
20
20
-
let pendingBackfills: string[] = [];
20
20
+
interface PendingBackfill {
21
21
+
id: string;
22
22
+
limit?: number;
23
23
+
}
24
24
+
let pendingBackfills: PendingBackfill[] = [];
21
25
22
26
app.use(cors());
23
27
app.use(express.json());
···
176
180
177
181
app.post('/api/backfill/:id', authenticateToken, requireAdmin, (req, res) => {
178
182
const { id } = req.params;
183
183
+
const { limit } = req.body;
179
184
const config = getConfig();
180
185
const mapping = config.mappings.find((m) => m.id === id);
181
186
···
184
189
return;
185
190
}
186
191
187
187
-
if (!pendingBackfills.includes(id)) {
188
188
-
pendingBackfills.push(id);
192
192
+
if (!pendingBackfills.find(b => b.id === id)) {
193
193
+
pendingBackfills.push({ id, limit: limit ? Number(limit) : undefined });
189
194
}
190
195
191
196
lastCheckTime = 0;
···
195
200
196
201
app.delete('/api/backfill/:id', authenticateToken, (req, res) => {
197
202
const { id } = req.params;
198
198
-
pendingBackfills = pendingBackfills.filter((bid) => bid !== id);
203
203
+
pendingBackfills = pendingBackfills.filter((bid) => bid.id !== id);
199
204
res.json({ success: true });
200
205
});
201
206
···
206
211
nextCheckTime = lastCheckTime + (config.checkIntervalMinutes || 5) * 60 * 1000;
207
212
}
208
213
209
209
-
export function getPendingBackfills(): string[] {
214
214
+
export function getPendingBackfills(): PendingBackfill[] {
210
215
return [...pendingBackfills];
211
216
}
212
217
···
215
220
}
216
221
217
222
export function clearBackfill(id: string) {
218
218
-
pendingBackfills = pendingBackfills.filter((bid) => bid !== id);
223
223
+
pendingBackfills = pendingBackfills.filter((bid) => bid.id !== id);
219
224
}
220
225
221
226
// Serve the frontend for any other route (middleware approach for Express 5)