1// Map Vote Tallying Function with Rate Limit Service Integration
2// This function counts emoji reactions and announces winners in a Hell Let Loose map vote
3import seedrandom from "https://esm.sh/seedrandom";
4import { DiscordRateLimitService } from "https://esm.town/v/ktodaz/Discord_Bot_Services/discord-rate-limit-service.tsx";
103}
104105// Get emoji mapping to decode emoji reactions
106function getEmojiMapping() {
107return {
219}
220221// Get reactions for a specific message with rate limiting
222async function getMessageReactions(channelId: string, messageId: string, emoji: string) {
223try {
224const encodedEmoji = encodeURIComponent(emoji);
225const routeKey = `/channels/${channelId}/messages/${messageId}/reactions`;
226227return rateLimitService.executeWithRateLimit(routeKey, async () => {
228const endpoint = `/channels/${channelId}/messages/${messageId}/reactions/${encodedEmoji}?limit=100`;
229const reactions = await discordRequest(endpoint);
230return reactions;
231});
232} catch (error) {
233console.error(`Error getting reactions for message ${messageId}:`, error);
234return []; // Return empty array on error to continue processing
235}
578}
579580// Get all reactions on this message
581const reactions = msg.reactions || [];
582583// Process each reaction type
584for (const reaction of Object.values(reactions)) {
585const emoji = reaction.emoji.name;
586587// Skip if this emoji is not in our mapping
592593const variant = emojiMapping[emoji];
594console.log(`Processing: Embed: ${mapName} (${variant}), Reactions: ${reaction.count}`);
595596// Get users who reacted with this emoji - using rate limited function
597const reactedUsers = await getMessageReactions(channelId, msg.id, emoji);
598console.log(`Emote key ${variant}: ${reactedUsers.length} users`);
599600// Process each user's reaction
601for (const user of reactedUsers) {
602// Skip bot reactions
603if (user.bot) continue;
604623const random = seedrandom(Date.now().toString());
624const userVotes: UserVote[] = [];
625const embedVariantReactionCounts: Record<string, number> = {};
626627// Process users in smaller batches to manage rate limits better
673for (const vote of votes) {
674const key = `${vote.embed.title} ${vote.variant}`;
675embedVariantReactionCounts[key] = (embedVariantReactionCounts[key] || 0) + 1;
676}
677}
682683// Convert to array of MapVote objects
684for (const [key, count] of Object.entries(embedVariantReactionCounts)) {
685const [mapName, variant] = key.split(/\s(?=[^\s]+$)/); // Split at the last space
686mapVotes.push({
695// Handle ties with random shuffle (match C# implementation)
696const randomVariants = seedrandom(Date.now().toString());
697const sortedVotes = Object.entries(embedVariantReactionCounts)
698.map(([key, count]) => {
699const [mapName, variant] = key.split(/\s(?=[^\s]+$)/);
radiohead_circle_jerkmain.tsx2 matches
1/** @jsxImportSource https://esm.sh/react */
2import { renderToString } from "npm:react-dom/server";
34const notesStyle = {
101}
102103// Add emoji reaction to message - RATE LIMITED VERSION
104async function addReaction(channelId: string, messageId: string, emoji: string) {
105const routeKey = `/channels/${channelId}/messages/${messageId}/reactions`;
106107return rateLimitService.executeWithRateLimit(routeKey, async () => {
108const url = `${API_BASE}/channels/${channelId}/messages/${messageId}/reactions/${emoji}/@me`;
109const token = Deno.env.get("DISCORD_BOT_TOKEN");
110123if (!response.ok) {
124let errorText = await response.text();
125console.error(`Error adding reaction: Status ${response.status}, Body: ${errorText}`);
126throw new Error(`Failed to add reaction: ${response.status}`);
127}
128129// Successful reaction add
130return true;
131});
195type: 0, // Role type
196allow: "1024", // VIEW_CHANNEL, READ_MESSAGE_HISTORY
197deny: "64", // ADD_REACTIONS
198},
199{
201type: 0, // Role type
202allow: "1024", // VIEW_CHANNEL, READ_MESSAGE_HISTORY
203deny: "64", // ADD_REACTIONS
204},
205{
271}
272273// Process variants for a map and add emoji reactions
274async function processMapVariants(messageId: string, channelId: string, map: MapInfo, variantOptions: any) {
275const mapMetaVariants: string[] = [];
279if (variantOptions.EnableDawn && map.MapDetails.Dawn) {
280if (map.MapDetails.Dawn === "meta") {
281console.log(`${map.MapName} Dawn variant is meta, not adding reaction`);
282mapMetaVariants.push(`${map.MapName} Dawn`);
283mapEnabledVariants.push("Dawn");
284} else if (map.MapDetails.Dawn === "enabled") {
285await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.DAWN));
286mapEnabledVariants.push("Dawn");
287}
291if (variantOptions.EnableDay && map.MapDetails.Day) {
292if (map.MapDetails.Day === "meta") {
293console.log(`${map.MapName} Day variant is meta, not adding reaction`);
294mapMetaVariants.push(`${map.MapName} Day`);
295mapEnabledVariants.push("Day");
296} else if (map.MapDetails.Day === "enabled") {
297await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.DAY));
298mapEnabledVariants.push("Day");
299}
303if (variantOptions.EnableDusk && map.MapDetails.Dusk) {
304if (map.MapDetails.Dusk === "meta") {
305console.log(`${map.MapName} Dusk variant is meta, not adding reaction`);
306mapMetaVariants.push(`${map.MapName} Dusk`);
307mapEnabledVariants.push("Dusk");
308} else if (map.MapDetails.Dusk === "enabled") {
309await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.DUSK));
310mapEnabledVariants.push("Dusk");
311}
315if (variantOptions.EnableNight && map.MapDetails.Night) {
316if (map.MapDetails.Night === "meta") {
317console.log(`${map.MapName} Night variant is meta, not adding reaction`);
318mapMetaVariants.push(`${map.MapName} Night`);
319mapEnabledVariants.push("Night");
320} else if (map.MapDetails.Night === "enabled") {
321await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.NIGHT));
322mapEnabledVariants.push("Night");
323}
327if (variantOptions.EnableFog && map.MapDetails.Fog) {
328if (map.MapDetails.Fog === "meta") {
329console.log(`${map.MapName} Fog variant is meta, not adding reaction`);
330mapMetaVariants.push(`${map.MapName} Fog`);
331mapEnabledVariants.push("Fog");
332} else if (map.MapDetails.Fog === "enabled") {
333await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.FOG));
334mapEnabledVariants.push("Fog");
335}
339if (variantOptions.EnableOvercast && map.MapDetails.Overcast) {
340if (map.MapDetails.Overcast === "meta") {
341console.log(`${map.MapName} Overcast variant is meta, not adding reaction`);
342mapMetaVariants.push(`${map.MapName} Overcast`);
343mapEnabledVariants.push("Overcast");
344} else if (map.MapDetails.Overcast === "enabled") {
345await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.OVERCAST));
346mapEnabledVariants.push("Overcast");
347}
351if (variantOptions.EnableRain && map.MapDetails.Rain) {
352if (map.MapDetails.Rain === "meta") {
353console.log(`${map.MapName} Rain variant is meta, not adding reaction`);
354mapMetaVariants.push(`${map.MapName} Rain`);
355mapEnabledVariants.push("Rain");
356} else if (map.MapDetails.Rain === "enabled") {
357await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.RAIN));
358mapEnabledVariants.push("Rain");
359}
363if (variantOptions.EnableSandstorm && map.MapDetails.Sandstorm) {
364if (map.MapDetails.Sandstorm === "meta") {
365console.log(`${map.MapName} Sandstorm variant is meta, not adding reaction`);
366mapMetaVariants.push(`${map.MapName} Sandstorm`);
367mapEnabledVariants.push("Sandstorm");
368} else if (map.MapDetails.Sandstorm === "enabled") {
369await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.SAND));
370mapEnabledVariants.push("Sandstorm");
371}
375if (variantOptions.EnableSnowstorm && map.MapDetails.Snowstorm) {
376if (map.MapDetails.Snowstorm === "meta") {
377console.log(`${map.MapName} Snowstorm variant is meta, not adding reaction`);
378mapMetaVariants.push(`${map.MapName} Snowstorm`);
379mapEnabledVariants.push("Snowstorm");
380} else if (map.MapDetails.Snowstorm === "enabled") {
381await addReaction(channelId, messageId, encodeURIComponent(EMOJIS.SNOW));
382mapEnabledVariants.push("Snowstorm");
383}
387}
388389// Populate channel with map options and add reactions
390async function populateChannelWithMaps(
391channel: any,
662const initialMessage = await sendInitialEmbed(channel, initialEmbedData);
663664// Populate channel with map options and reactions
665const { metaVariants, enabledVariants } = await populateChannelWithMaps(
666channel,
luciaMagicLinkStarterApp.tsx3 matches
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { useState } from "https://esm.sh/react@18.2.0";
34export function App() {
6return (
7<div>
8<h1>Val Town React + Hono Starter</h1>
9I've been clicked <button onClick={() => setClicked((c) => c + 1)}>{clicked}</button> times
10</div>
helloWorldmain.tsx2 matches
1/** @jsxImportSource https://esm.sh/react */
2import { blob } from "https://esm.town/v/std/blob?v=11";
3import { renderToString } from "npm:react-dom/server";
45export default async (request: Request) => {
34InstallSlashInteractionsTextCommandTrigger: "installslashinteractions",
35CreateMapRotationVoteTextChannelTextCommandTrigger: "mapvote",
36TallyReactionVotesTextCommandTrigger: "tally",
37},
38DiscordTargets: {
53fieldHowToTitle: "How to Vote",
54fieldHowToText:
55"Use the Emoji Reaction(s) under each option corresponding to your choice of time or weather variant.",
56fieldEmojiKeyTitle: "Emoji Reaction Key",
57fieldEmojiKeyText: "",
58fieldCurrentMetaMapsTitle: "Current Meta Maps:",
69title: "Garrisons & Whiskey Map Rotation Vote",
70description:
71"Rules, \"How to Vote\", and Emoji Reaction Key can be found at the top. The Map Rotation Guide can be found in the discussion thread below.",
72fieldJumpTitle: "You have reached the bottom.",
73fieldJumpValue: "",
81threadHeader: {
82title: "Welcome to the Discussion Thread!",
83description: "Rules, \"How to Vote\", and Emoji Reaction Key can be found at the top of the main channel.",
84fieldMapRotationGuideTitle: "Map Rotation Guide",
85fieldMapRotationGuideText:
141// Common tech skills to look for
142const skillKeywords = [
143"typescript", "javascript", "python", "react", "node.js", "nodejs", "vue",
144"angular", "next.js", "nextjs", "go", "golang", "rust", "aws", "azure",
145"gcp", "docker", "kubernetes", "k8s", "terraform", "ci/cd", "ml", "ai",
my-first-val04_design_partners.tsx4 matches
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import ReactDOMServer from "https://esm.sh/react-dom@18.2.0/server";
3import React from "https://esm.sh/react@18.2.0";
45function DesignPartnersSlide() {
105// HTTP handler function for Val Town
106export default async function(req: Request): Promise<Response> {
107const html = ReactDOMServer.renderToString(<DesignPartnersSlide />);
108109return new Response(
markdownBlogStarterLayout.tsx3 matches
1/** @jsxImportSource npm:react@18.2.0 */
2import type { ReactNode } from "npm:react@18.2.0";
34export function Layout({ children }: { children: ReactNode }) {
5return (
6<html lang="en">