Public
Back
Version 79
6d ago
import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
import { type Tweet } from "https://esm.town/v/stevekrouse/social_data@101-main/schemas.ts";
import { ValTownSocialData } from "https://esm.town/v/stevekrouse/social_data@101-main/sdk/index.ts";
const keywords = ["val.town", "val.run", "val town", "valdottown"];
const excludes = "-_ValTown_ -is:retweet -from:valenzuelacity -from:val__run -from:valdottown";
const query = keywords
.map((k) => "\"" + k + "\"")
.join(" OR ") + " " + excludes;
function relevant(t: Tweet) {
if (keywords.some(k => t.full_text?.includes(k))) return true;
return t.entities.urls?.some(u => keywords.some(k => u.expanded_url?.includes(k)));
}
// change to false when testing
// to run query for past 48 hours
const isProd = false;
const socialdata = new ValTownSocialData();
export async function twitterAlert({ lastRunAt }: Interval) {
// search
const since = isProd
? lastRunAt ? Math.floor(lastRunAt.getTime() / 1000) : 0
: Math.floor((Date.now() / 1000) - (2 * 24 * 60 * 60));
const response = await socialdata.search(query + " since_time:" + since);
if ("message" in response) throw new Error(response.message);
// to help us debug why we're getting and paying for irrelevant tweets
console.log(response);
// filter
const relevantTweets = response.tweets?.filter(relevant);
if (!relevantTweets?.length) return;
Updated: March 7, 2025