1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { BlueskyIcon, DiscordIcon, GitHubIcon, RSSIcon, TwitterIcon } from "./icons.tsx";
3
4export default function SocialLinks() {
44 </a>
45 <a
46 href="https://discord.val.town"
47 target="_blank"
48 rel="noopener noreferrer"
49 className="social-link"
50 >
51 <DiscordIcon />
52 </a>
53 </div>
75}
76
77export function DiscordIcon (props: React.SVGProps<SVGSVGElement>) {
78 return (
79 <svg
894. Migration completes on **May 1, 2025**.
90
91We're committed to making this transition smooth for you — reach out anytime via [email](mailto:help@val.town) or [Discord](http://discord.val.town/) if you need assistance. We appreciate your help and patience through this migration.
9 let redirectUrl = DEFAULT_REDIRECT_TARGET; // Assume default redirect initially
10
11 // Check if User-Agent exists and contains 'twitter' or 'discord' (case-insensitive)
12 if (userAgent) {
13 const lowerCaseUserAgent = userAgent.toLowerCase();
14 if (
15 lowerCaseUserAgent.includes("twitter")
16 || lowerCaseUserAgent.includes("discord")
17 ) {
18 // If it matches, set the special redirect target
1This script takes a Steam ID, Game Name, and array of discord webhook url destinations. It scans the main Steam community discussion page,
2and looks for new threads and threads with new comments, and then constructs a webhook with a configurable amount threads per hook, sending it to
3all configured destinations.
15 embedColor: 9043685, // optional decimal color to change the embed highlight
16 steamId: "570",
17 discordWebhook: [
18 Deno.env.get("DISCHOOK_URL_1"), // set up your webhook urls as environment variables
19 Deno.env.get("DISCHOOK_URL_2"), // you can pass in a single url or an array
8const MAX_THREADS_PER_BATCH = 5; // Maximum threads to include in a single batch
9const MAX_DEBUG_HTML_RUNS = 3; // Maximum number of debug HTML runs to keep
10const DEFAULT_EMBED_COLOR = 3447003; // Default Discord embed color (blue)
11const MAX_STORED_THREADS = 100; // Maximum number of threads to store
12
24 gameName: string;
25 steamId: string; // Changed from steamUrl to steamId
26 discordWebhook?: string | string[]; // Now accepts a single string or an array of strings
27 maxThreads?: number;
28 embedColor?: number; // Decimal color value
48 gameName,
49 steamId,
50 discordWebhook,
51 maxThreads = MAX_THREADS_PER_BATCH,
52 embedColor,
80 );
81
82 if (discordWebhook && threadsToNotify.length > 0) {
83 await sendDiscordNotifications(gameName, threadsToNotify, discordWebhook, maxThreads, embedColor, steamId);
84 }
85
150}
151
152async function sendDiscordNotifications(
153 gameName: string,
154 threads: SteamThread[],
164 for (const webhookUrl of webhookList) {
165 try {
166 await sendDiscordWebhook(gameName, threadBatch, webhookUrl, embedColor, steamId);
167 await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY_MS));
168 } catch (webhookError) {
169 console.error(`Failed to send webhook for ${gameName} to ${webhookUrl} for thread batch starting at index ${i}:`, webhookError);
170 await sendErrorEmail(gameName, webhookError, `sending Discord webhook to ${webhookUrl} for thread batch starting at index ${i}`);
171 }
172 }
295}
296
297async function sendDiscordWebhook(
298 gameName: string,
299 threads: SteamThread[],
331 };
332
333 console.log("Discord Webhook Payload:", JSON.stringify(payload, null, 2));
334
335 const response = await fetch(webhookUrl, {
5This template will help you:
61. Search for specific mentions on Twitter/X using customizable keywords.
72. Deliver notifications wherever you'd like (email, Discord, Slack, Telegram, etc).
8
9## Example
10This val tracks mentions of "Val Town" and related terms, excluding noise like retweets and irrelevant accounts. Notifications are sent to a Discord webhook but can be easily reconfigured for other platforms.
11<img src="https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/85912106-f625-443e-5321-6e2699453200/public" width="500"/>
12To see exactly how we use this template at Val Town: https://www.val.town/x/stevekrouse/twitterAlert
37### 5. Choose Notification Method
38
39This template uses a Discord webhook for notifications, but
40you can update this to your preferred platform by replacing the `discordWebhook` call
41with a call to [Slack](https://docs.val.town/integrations/slack/send-messages-to-slack/), [`@std/email`](https://docs.val.town/std/email/), etc.
42
43**Create a Discord webhook following [this guide](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks).**
44
45Save your Discord Webhook URL in your Environment Variables (you can find this on the left sidebar):
46- Key: `mentionsDiscord`
47- Value: Your Discord webhook URL.
48Notifications will be sent using this function:
49
50```ts
51await discordWebhook({
52 url: Deno.env.get("mentionsDiscord"),
53 content,
54});
1import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
2import { socialDataSearch, Tweet } from "https://esm.town/v/stevekrouse/socialDataSearch";
3
25
26 // Format notification content as a list of Tweet URLs
27 // Using fxtwitter, which fixes Twitter Embed Unfurls for Discord
28 const content = response.tweets?.map(({ user: { screen_name }, id_str }) =>
29 `https://fxtwitter.com/${screen_name}/status/${id_str}`
39 // Send notifications (only if isProd is set to true)
40 if (isProd && content?.length) {
41 await discordWebhook({
42 url: Deno.env.get("mentionsDiscord"), // Replace with your Discord webhook URL or other notification method
43 content,
44 });
10 let redirectUrl = DEFAULT_REDIRECT_TARGET; // Assume default redirect initially
11
12 // Check if User-Agent exists and contains 'twitter' or 'discord' (case-insensitive)
13 if (userAgent) {
14 const lowerCaseUserAgent = userAgent.toLowerCase();
15 if (
16 lowerCaseUserAgent.includes("twitter")
17 || lowerCaseUserAgent.includes("discord")
18 ) {
19 // If it matches, set the special redirect target
11
12 try {
13 const DISCORD_PUBLIC_KEY = process.env.discordPublicKey;
14
15 if (!DISCORD_PUBLIC_KEY) {
16 throw new Error("Discord webhook public key is not set");
17 }
18
30
31 // Convert public key and signature to Uint8Array
32 const publicKeyBytes = sodium.from_hex(DISCORD_PUBLIC_KEY);
33 const signatureBytes = sodium.from_hex(signature);
34
44 }
45
46 // Parse the incoming JSON payload from the Discord webhook
47 const payload = await JSON.parse(body);
48
53
54 // Log the entire payload to the console
55 console.log("Discord Webhook Received:", JSON.stringify(payload, null, 2));
56
57 // Respond with a 200 OK to acknowledge receipt