steamforumscannerREADME.md1 match
10import scanSteamForums from "https://esm.town/v/dreww/steamforumscanner";
1112export default async function(interval: Interval) {
13const dota2Threads = await scanSteamForums({
14gameName: "Dota 2",
steamforumscannermain.tsx15 matches
29}
3031async function sendErrorEmail(gameName: string, error: Error, context: string) {
32const subject = `Error in Steam Forum Scanner for ${gameName}`;
33const text = `An error occurred while ${context} for ${gameName}:\n\n${error.message}\n\n${error.stack}`;
41}
4243function constructSteamUrl(steamId: string): string {
44return `https://steamcommunity.com/app/${steamId}/discussions/`;
45}
4647export default async function scanSteamForums({
48gameName,
49steamId,
98}
99100async function cleanupDebugHtmlBlobs(gameName: string) {
101try {
102const debugBlobs = await blob.list(`steam_html_debug_${gameName}_`);
115}
116117async function fetchSteamDiscussionsPage(url: string): Promise<string> {
118const response = await fetch(url, {
119headers: {
132}
133134async function saveDebugHtml(gameName: string, html: string) {
135const key = `steam_html_debug_${gameName}_${Date.now()}`;
136await blob.set(key, html);
138}
139140async function getStoredThreads(gameName: string): Promise<SteamThread[]> {
141const storageKey = `steam_threads_${gameName}`;
142return await blob.getJSON(storageKey) ?? [];
143}
144145function identifyThreadsToNotify(currentThreads: SteamThread[], storedThreads: SteamThread[]): SteamThread[] {
146return currentThreads.filter(currentThread => {
147const storedThread = storedThreads.find(st => st.id === currentThread.id);
150}
151152async function sendDiscordNotifications(
153gameName: string,
154threads: SteamThread[],
174}
175176async function updateStoredThreads(gameName: string, storedThreads: SteamThread[], currentThreads: SteamThread[]) {
177const currentThreadMap = new Map(currentThreads.map(thread => [thread.id, thread]));
178200}
201202function parseThreads(html: string): SteamThread[] {
203const $ = cheerio.load(html);
204251}
252253function cleanTitle(title: string): string {
254return title.replace(/\t/g, '').trim();
255}
256257function parseForumTopic($: cheerio.Root, el: cheerio.Element): SteamThread {
258const threadNameEl = $(el).find(".forum_topic_name");
259const link = $(el).find(".forum_topic_overlay");
275}
276277function parseForumTopicName($: cheerio.Root, el: cheerio.Element): SteamThread {
278const link = $(el).find("a");
279const url = link.attr("href") ?? "";
295}
296297async function sendDiscordWebhook(
298gameName: string,
299threads: SteamThread[],
synced_reducermain.tsx1 match
1export default async function(req: Request): Promise<Response> {
2const url = new URL(req.url);
3if (url.pathname === "/v1") {
templateTwitterAlertREADME.md2 matches
46- Key: `mentionsDiscord`
47- Value: Your Discord webhook URL.
48Notifications will be sent using this function:
4950```ts
6364- **Proxies via Val Town's [SocialDataProxy](https://www.val.town/v/stevekrouse/socialDataProxy)**: Limited to 10 cents per day for [**Val Town Pro users**](https://www.val.town/pricing). This API is *only* for Pro users.
65- **Need more calls?** Sign up for your own [SocialData API token](https://socialdata.tools) and configure the [`socialDataSearch`](https://www.val.town/v/stevekrouse/socialDataSearch) function.
templateTwitterAlertmain.tsx1 match
12const isProd = false;
1314export async function twitterAlert({ lastRunAt }: Interval) {
15// If isProd, search for tweets since that last time this interval ran
16// if not, search for tweets since 48 hours ago for testing
testPondiversemain1 match
6import updateTable from "./updateTable";
78export default async function(req: Request): Promise<Response> {
9let url = new URL(req.url);
10const path = url.pathname.toLowerCase();
growingEmeraldGrasshoppermain.tsx3 matches
19- Respond in English, providing clear and direct answers`;
2021function ChatInterface() {
22const [messages, setMessages] = useState([]);
23const [inputValue, setInputValue] = useState("");
415}
416417function client() {
418createRoot(document.getElementById("root")).render(<ChatInterface />);
419}
420if (typeof document !== "undefined") { client(); }
421422export default async function server(request: Request): Promise<Response> {
423if (request.method === "POST" && new URL(request.url).pathname === "/chat") {
424try {
wonderfulBlushMagpiemain.tsx3 matches
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
45function App() {
6const [shorts, setShorts] = useState<{id: number, link: string}[]>([]);
7const [newShortLink, setNewShortLink] = useState('');
185}
186187function client() {
188createRoot(document.getElementById("root")).render(<App />);
189}
191if (typeof document !== "undefined") { client(); }
192193export default async function handler(request: Request): Promise<Response> {
194const { sqlite } = await import("https://esm.town/v/stevekrouse/sqlite");
195const KEY = "wonderfulBlushMagpie";
funAnimatedVocabularymain.tsx3 matches
119};
120121function App() {
122const [currentWord, setCurrentWord] = useState('');
123const [definition, setDefinition] = useState('');
354}
355356function client() {
357createRoot(document.getElementById("root")).render(<App />);
358}
360if (typeof document !== "undefined") { client(); }
361362export default async function handler(request: Request): Promise<Response> {
363if (request.method === 'GET') {
364return new Response(`
1export default async function(req: Request): Promise<Response> {
2const url = new URL(req.url);
3if (url.pathname === "/v1") {