diff --git a/.env b/.env index 8877cae..442824b 100644 --- a/.env +++ b/.env @@ -4,4 +4,7 @@ CROWDIN_API_URL="op://Environment Variables - Development/Scripts/Crowdin API Ur CROWDIN_TOKEN="op://Environment Variables - Development/Scripts/Crowdin Token" # Github -GITHUB_TOKEN="op://Environment Variables - Development/Scripts/GitHub Token" \ No newline at end of file +GITHUB_TOKEN="op://Environment Variables - Development/Scripts/GitHub Token" + +# Discord +DISCORD_TOKEN="op://Environment Variables - Development/Scripts/Discord Token" \ No newline at end of file diff --git a/src/discord/cycThreads.ts b/src/discord/cycThreads.ts new file mode 100644 index 0000000..6a752b7 --- /dev/null +++ b/src/discord/cycThreads.ts @@ -0,0 +1,525 @@ +/** + * @copyright NHCarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ + +/* eslint-disable stylistic/max-len -- Too big strings */ +/* eslint-disable @typescript-eslint/naming-convention -- Discord API */ +/* eslint-disable max-lines -- Justification above */ + +import { backoffAndRetry } from "../utils/backoffAndRetry.js"; + +const data: Array<{ title: string; speaker: string }> = [ + { + speaker: "Abbey Perini", + title: "Slots, Slots, Slots, Everybody!", + }, + { + speaker: "Vishnu Ramineni", + title: "Building Inclusive Web Experiences: Web Accessibility in ReactJS", + }, + { + speaker: "Francisco Zenteno", + title: "Effective Testing Strategies for Optimization Models in Java", + }, + { + speaker: "Manisha Ponugoti", + title: "Legacy to Cloud: Transforming Insurance Systems with .NET Microservices & Azure", + }, + { + speaker: "Arjan Dedgjonaj", + title: "Mutation Testing", + }, + { + speaker: "Kierra Dotson", + title: "Beyond The Hype: Leading the Charge in Responsible AgentOps for Business Transformation", + }, + { + speaker: "Chris DeMars", + title: "Know Your JS", + }, + { + speaker: "Kaleb Garner", + title: "Need for Speed: How Modern JavaScript Frameworks Are Solving Web Performance", + }, + { + speaker: "Faye X", + title: "Break into full stack from Java", + }, + { + speaker: "Tim Corey", + title: "Modernize Your .NET Skills", + }, + { + speaker: "Ramasankar Molleti", + title: "Convergence of AI, Cybersecurity, and Cloud Technologies: Shaping the Future of Enterprise IT", + }, + { + speaker: "Sireesha Chilakamarri", + title: "TBA", + }, + {}, + { + speaker: "Lawrence Lockhart", + title: "You Don't Know JSON: How to Grow From Syntax to Superpowers", + }, + { + speaker: "Hermes Frangoudis", + title: "TBA", + }, + { + speaker: "Josh Long", + title: "TBA", + }, + { + speaker: "Caleb Jenkins", + title: "10 Reasons your Software Sucks! (and what to do about it)", + }, + { + speaker: "Leah Thompson", + title: "Using React with InertiaJS - Making front end development FAST🚀", + }, + { + speaker: "Katarinya Hughes", + title: "TBA", + }, + { + speaker: "Nnenna Ndukwe", + title: "Building with Confidence: Mastering Feature Flags in React Applications", + }, + { + speaker: "Dennis Ivy", + title: "TBA", + }, + { + speaker: "Aly Ibrahim", + title: "FinOps and Cloud Cost Optimization", + }, + { + speaker: "Ken Versaw", + title: "C# Past, Present, and Future", + }, + { + speaker: "Jonathan Perry", + title: "Strategies for Mitigating Performance Interference in Cloud-Native Systems", + }, + { + speaker: "Alexander Crettenand", + title: "TBA", + }, + { + speaker: "David Parry", + title: "AI Assisted Coding: Navigating the Strengths, Challenges, and Future of Coding Assistants", + }, + { + speaker: "Andrew MacLean", + title: "Goodbye, World; Hello, Battlesnake!", + }, + { + speaker: "Sergey Kryvets", + title: "Making You a Better Speaker with Spring AI", + }, + { + speaker: "Nick Cosentino", + title: "plugin architectures in C#", + }, + { + speaker: "Mike Arsenault", + title: "Stop Hitting Yourself: How to Prevent Common Attacks to your Application", + }, + { + speaker: "Tracy Lee", + title: "TBA", + }, + { + speaker: "Shaurya Agrawal", + title: "Integrating Microsoft Fabric and Databricks for Modern Data Analytics", + }, + { + speaker: "Swizec Teller", + title: "Abusing React Server Components as a tool for incremental rewrites", + }, + { + speaker: "Prathap Raghavan", + title: "Spring Boot Microservices Architecture: A Deep Dive", + }, + { + speaker: "Matthew Hess", + title: "Wait, What? C# Async-Await Explained", + }, + { + speaker: "Cedric Clyburn", + title: "Structuring the Unstructured: Advanced Document Parsing for AI Workflows", + }, + { + speaker: "Michael Leitz", + title: "The First Principles, Ep 1: Computers Run Code, Humans Read Code", + }, + { + speaker: "Nick Taylor", + title: "OAuth Gets You In, Zero Trust Keeps You Safe", + }, + { + speaker: "Allen Helton", + title: "Designing APIs Both Humans and AI Love", + }, + { + speaker: "Nate Custer", + title: "Leveraging Quality Intelligence and AI to Improve the Quality of Java Applications", + }, + { + speaker: "Boston Cartwright", + title: "Beyond Frontend and Backend: Defining the AI Layer", + }, + { + speaker: "Rob Ocel", + title: "The Superpower of Intentional Architecture", + }, + { + speaker: "Jeremy Barger", + title: "Split-Second Leadership: Mastering Emotions Before They Master You", + }, + { + speaker: "Rishab Kumar", + title: "Breaking Bad: Cooking APIs with AWS Serverless Chemistry", + }, + { + speaker: "Michael Brown", + title: "Hypervelocity Engineering: The End of Slow Dev", + }, + { + speaker: "Ted M. Young", + title: "Testable Architecture: Keep 'em Separated", + }, + { + speaker: "Elder Yzunia", + title: "Doing the Right Thing: Web Accessibility Tools for the Modern Dev", + }, + { + speaker: "David Strickland", + title: "On Prem to Cloud Native", + }, + { + speaker: "John Crighton", + title: "Cloud Enabled Event-Driven Architecture for Healthcare SaaS Solutions", + }, + { + speaker: "Pradeepkumar Palanisamy", + title: "Killing Hardcoded Secrets: Secure Test Automation with Vault and Cloud-Native Secrets Management", + }, + { + speaker: "Dona Maria Jose", + title: "From Vision to Impact: Leading Zero to One Projects in the Workplace", + }, + { + speaker: "Tanasin Vivitvorn", + title: "Boost Java Application Efficiency on the Cloud and Slash Costs with GraalVM and Spring AOT", + }, + { + speaker: "JJ Asghar", + title: "Open Source AI and Granite", + }, + { + speaker: "Jerry Reghunadh", + title: "The Modern Full-Stack: Owning Your Deployment Pipeline", + }, + { + speaker: "James Q. Quick", + title: "TBA", + }, + { + speaker: "Amanda Martin", + title: "Powering AI with your APIs: A Enterprise Architecture for MCP", + }, + { + speaker: "Diana Pham", + title: "TBA", + }, + { + speaker: "Trey Clark", + title: "Local to Live: Deploying your App to the Cloud", + }, + { + speaker: "Borko Djurkovic", + title: "Automating Secure OIDC-Based Cross-Cloud Authentication", + }, + { + speaker: "Alex Merced", + title: "Unifying Data for Data Applications with the Data Lakehouse", + }, + { + speaker: "Reece Iriye", + title: "Cloud vs. Control: Saving (or Sinking) a Business by Deploying Global Applications w/ Local Hardware", + }, + {}, + {}, + {}, + { + speaker: "Jasmine Vo", + title: "Blueprint for Architecting a Scalable Component Library", + }, + { + speaker: "Sachin Gupta", + title: "From Concept to Code: Domain-Driven Design for .NET Business Applications", + }, + { + speaker: "Dan Vega", + title: "Building AI-Enabled Spring Applications with Model Context Protocol (MCP)", + }, + { + speaker: "Akshay Mittal", + title: "AI-Powered DevOps in Cloud App Modernization: Automating Deployments, Monitoring, and Resilience", + }, + { + speaker: "Justin Biard", + title: "Manage Complexity with Terraform: Tips and Tricks from the Trenches", + }, + { + speaker: "Stacy Haven", + title: "TBA", + }, + { + speaker: "Rizel Scarlett", + title: "MCP-UI: Where Intent Becomes Interface", + }, + { + speaker: "Chris Griffing", + title: "Migrating 600k+ Lines of Code from Flow to TypeScript", + }, + { + speaker: "Srikanth Maru", + title: "Building Production-Ready Data Pipelines for AI/ML with Java and Apache Beam", + }, + { + speaker: "Israa Taha", + title: "ADRs: Because Context Isn't Just for LLMs", + }, + { + speaker: "Andrea Griffiths", + title: "The AI Teammate Is Here — Now What?", + }, + { + speaker: "Marshall Burns", + title: "Embedded Leadership: A Guid to Leading from Within", + }, + {}, + { + speaker: "Patrick Hulce", + title: "Video AI in Your Browser with WebGPU", + }, + { + speaker: "Anupama Pathirage", + title: "Ballerina in Action: Open-Source Innovation for Cloud-Native Integration", + }, + { + speaker: "Soujanya Vummannagari", + title: "AI-Enhanced Strangler Pattern: Cognitive Legacy System Transformation", + }, + { + speaker: "Sarah Shook", + title: "Bring Your Applications to Life with 3D CSS Animations", + }, + { + speaker: "Shafik Quoraishee", + title: "Building a Handwriting Recognition System for the New York Times Crossword", + }, + { + speaker: "Victor Lyuboslavsky", + title: "Radical Transparency: Leading Engineering with Openness Inside and Out", + }, + { + speaker: "Jacob Orshalick", + title: "Agentic Fundamentals: How language models and code can communicate", + }, + { + speaker: "Bas Steins", + title: "Beyond IaC: Bring your infrastructure to your app with sst", + }, + { + speaker: "Andrew Smit", + title: "unit testing your API", + }, + { + speaker: "Naveen Chatlapalli", + title: "TBA", + }, + { + speaker: "Vasanth Mudavatu", + title: "Commit Secure AI: Embedding Security in Code, Pipelines, and Production", + }, + { + speaker: "Samantha St-Louis", + title: "Dynamic AI Architectures: Building Scalable, Real-World Solutions in the Cloud", + }, + { + speaker: "Charles Wood", + title: "Your First JavaScript AI Agent", + }, + { + speaker: "Jacob Daddario", + title: "JavaScript for the Rest of Us", + }, + { + speaker: "Suren Konathala", + title: "Harness Java's Unmatched Power with JAQ Stack: Accelerate Web Development for Enterprise-Scale", + }, + { + speaker: "Ron Dagdag", + title: "Predicting the future (of equipment) using ML.NET", + }, + { + speaker: "Wayne Jones", + title: "Building Accessible Components: Best Practices and Business Buy-In", + }, + { + speaker: "Raja Krishna", + title: "AI-Powered Code Reviews with Node and Vercel AI SDK", + }, + { + speaker: "Bob Fornal", + title: "Writing Testable Code", + }, + { + speaker: "Jeremy Morgan", + title: "Leveling Up: Building Retro 2D Games with JavaScript and Phaser", + }, + { + speaker: "Joseph Evans", + title: "Write Once, Run Confidently: A Guide to Building Production-Ready Apps with Spring Boot", + }, + { + speaker: "Bobby Davis, Jr.", + title: "Enterprise-Ready Minimal APIs in .NET: Scaling Simplicity", + }, + { + speaker: "Kevin Griffin", + title: "Crazy Web Performance with Azure Static Web Apps", + }, + { + speaker: "Angela Cortes", + title: "The QA spectrum", + }, + { + speaker: "Alvaro Montoro", + title: "Playing with the Gamepad API: Using Game Controllers with JS", + }, + { + speaker: "Brian Morrison", + title: "Demystifying deployments as a service", + }, + { + speaker: "Vishal Reddy", + title: "Kotlin and Compose WASM for the UI challenged", + }, + { + speaker: "Alex Johnson", + title: "From React to Angular: Making the Transition a Breeze", + }, + { + speaker: "Nick Guzmán", + title: "Securing and Scaling AWS with Terraform, Vault, and Veeam: A Practical Guide", + }, + { + speaker: "Danielle Larregui", + title: "Mastering Large Language Models: Prompt Engineering for Precision and Performance", + }, + { + speaker: "Mark Thompson", + title: "TBA", + }, + { + speaker: "Eleazar Hernandez", + title: "WAI-ARIA in React components: guidance and considerations", + }, + { + speaker: "Satyanarayana Purella", + title: "Architecting Financial Systems for the Future: Microservices and Event-Driven Paradigms at Scale", + }, + { + speaker: "Bree Hall", + title: "Code, But Make It Cute", + }, + { + speaker: "Naveen Srikanth Pasupuleti", + title: "K8s-Native ML in Healthcare: Production Spark, AWS & Container Orchestration at Scale", + }, + { + speaker: "Avindra Fernando", + title: "The Hidden Struggles of React Server Components", + }, + { + speaker: "Mike Chen", + title: "TBA", + }, + { + speaker: "Adam Rackis", + title: "Serving content on the web: from PHP to RSC—and beyond", + }, + { + speaker: "Robert Groves", + title: "Creative Coding 101: Create Algorithmic Art with Processing", + }, + { + speaker: "Jeremy Miller", + title: "Simplifying Our Code with Vertical Slice Architecture", + }, + { + speaker: "Paul Chin Jr.", + title: "Data Gone in 60 Seconds: A Serverless ETL Heist", + }, + { + speaker: "Anitha Dakamarri", + title: "SBOM adopatability in open source software scanning", + }, + { + speaker: "Arfi Siddik Mollashaik", + title: "Designing Secure, Compliant, and Scalable Test Data Pipelines for Enterprise DevOps", + }, + { + speaker: "Julian Macagno", + title: "TBA", + }, + { + speaker: "Suresh A M", + title: "TBA", + }, + { + speaker: "David Edoh-Bedi", + title: "TBA", + }, + { + speaker: "Arun Prasad Jaganathan", + title: "How not to build a Startup", + }, + { + speaker: "Claire Bourdon", + title: "Little Bobby Tables: Understanding Data Validation and Sanitization", + }, +].filter((item): item is { title: string; speaker: string } => { + return Boolean(item.title) && Boolean(item.speaker); +}); + +const token = process.env.DISCORD_TOKEN; + +if (token === undefined) { + throw new Error("Missing DISCORD_TOKEN"); +} + +for (const talk of data) { + await backoffAndRetry("https://discord.com/api/v10/channels/1417221194536714393/threads", { + body: JSON.stringify({ + auto_archive_duration: 1440, + message: { + content: `Please use this thread to discuss anything related to this talk, ask questions, or share insights. Let's keep the conversation respectful and on-topic. Enjoy the session!`, + }, + name: `${talk.title} - ${talk.speaker}`, + type: 11, + }), + headers: { + "Authorization": `Bot ${token}`, + "Content-Type": "application/json", + }, + method: "POST", + }); +} diff --git a/src/github/auditNpmPackages.ts b/src/github/auditNpmPackages.ts index ecae1bd..5a65d06 100644 --- a/src/github/auditNpmPackages.ts +++ b/src/github/auditNpmPackages.ts @@ -22,9 +22,7 @@ const resultPath = join( ); const orgsToCheck = [ - "deepgram", - "deepgram-devs", - "deepgram-starters", + "freecodecamp", ]; const vulnerablePackages: Array<{ name: string; version: string }> = [ diff --git a/src/utils/backoffAndRetry.ts b/src/utils/backoffAndRetry.ts new file mode 100644 index 0000000..fbec676 --- /dev/null +++ b/src/utils/backoffAndRetry.ts @@ -0,0 +1,31 @@ +/** + * @copyright NHCarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ + +import { sleep } from "./sleep.js"; + +/** + * Wraps the native fetch method in logic to back off + * and retry on 429 errors. + * @param url - The URL to fetch. + * @param options - The fetch options. + */ +export const backoffAndRetry + = async(url: string, options: RequestInit = {}): Promise => { + try { + const response = await fetch(url, options); + + if (!response.ok) { + if (response.status === 429) { + await sleep(5000); + await backoffAndRetry(url, options); + return; + } + throw new Error(`Request failed with status ${response.status.toString()}`); + } + } catch (error) { + console.error(`Fetch error: ${JSON.stringify(error, null, 2)}`); + } + }; diff --git a/src/utils/serialiseJsonOrError.ts b/src/utils/serialiseJsonOrError.ts index eb805db..57a40d3 100644 --- a/src/utils/serialiseJsonOrError.ts +++ b/src/utils/serialiseJsonOrError.ts @@ -14,6 +14,7 @@ export const serialiseJsonOrError = (text: string): Record | null => { try { const object = JSON.parse(text); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- we know this is an object. return object; } catch { return null;