Readme

Daily Twitter "Important Updates" Digest

You like getting important updates from Twitter—new projects or writing or companies to learn about.

But you don't like being addicted to the feed constantly.

This val lets you get daily updates from specific people you want to follow closely. It uses AI to filter out random shitposts and only get the important updates.

1. Authentication

You'll need a Twitter Bearer Token. Follow these instructions to get one.

Unfortunately it costs $100 / month to have a Basic Twitter Developer account. If you subscribe to Val Town Pro, you can ask Steve Krouse to borrow his token.

Also rate limits seem really severe which limits how useful this is :( Need to figure out workarounds...

2. Query

Update the list of usernames to people you care about; change the AI prompt if you want different filtering.

3. Notification

Sends a daily email.

Todos:

  • this should filter the twitter API call to only tweets since the last run.
  • some kind of caching to avoid rate limiting
  • would be nice to use the user's feed instead of a username list... but not sure how easy that is
Runs every 1 days
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { getTweets } from "https://esm.town/v/geoffreylitt/getTweets";
import { email } from "https://esm.town/v/std/email?v=12";
import { OpenAI } from "https://esm.town/v/std/openai?v=4";
import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
import { twitterSearch } from "https://esm.town/v/stevekrouse/twitterSearch";
const usernames = [
"stevekrouse",
"worrydream",
"wattenberger",
"mappletons",
"maryrosecook",
// Rate limits seem to be an issue...
// "thesephist",
// "tylerangert",
// "szymon_k",
// "schickling",
// "pvh",
// "todepond",
// "rsnous",
// "rsms",
// "andy_matuschak",
// "sliminality",
];
const openai = new OpenAI();
export async function twitterAlert({ lastRunAt }: Interval) {
let results = [];
for (const username of usernames) {
const tweets = await getTweets(username);
results = results.concat(tweets.data.map(tweet => ({ ...tweet, username })));
// wait 1 seconds between requests to try to avoid rate limits
await new Promise((resolve) => setTimeout(resolve, 1000));
}
async function filterTweets(tweets) {
const completion = await openai.chat.completions.create({
messages: [
{
role: "system",
content:
`You'll be given a list of tweets as JSON. I want you to filter the list and return a JSON array of IDs, plus a headline for the filtered list: { headline: string; ids: string[] } The filter criteria are:
I want to hear about important tweets sharing major updates, new projects, new papers or essays, website updates, etc. I don't want to see shitposts or jokes.
The headline should be short for an email subject, like 10 words, tease who said what with specifics of what they said.`,
},
{ role: "user", content: JSON.stringify(results) },
],
model: "gpt-4o",
response_format: { type: "json_object" },
});
const parsed = JSON.parse(completion.choices[0].message.content);
return { tweets: tweets.filter(tweet => parsed.ids.includes(tweet.id)), headline: parsed.headline };
}
const { tweets, headline } = await filterTweets(results);
// Format email HTML
const emailHtml = tweets.map((tweet) => {
const url = `https://fxtwitter.com/${tweet.username}/status/${tweet.id}`;
return `
<div style="border: 1px solid #e1e8ed; padding: 10px; margin-bottom: 10px; border-radius: 10px;">
<p style="margin: 0; font-size: 14px;"><strong>${tweet.username}:</strong> ${tweet.text}</p>
<a href="${url}" style="font-size: 12px; color: #1da1f2;">Read more</a>
</div>
`;
}).join("");
const htmlContent = `
<div style="font-family: Arial, sans-serif; color: #333;">
${emailHtml}
</div>
`;
email({ subject: headline, html: htmlContent });
console.log("Sent!", headline);
console.log(htmlContent);
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
June 12, 2024