feat: add base64 command to encode/decode base64 strings#31
Conversation
Summary by BeetleThis PR introduces a new 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 3 files changed, +93 additions, -0 deletions 🗺️ Walkthrough:sequenceDiagram
participant User
participant Discord
participant Base64Command
participant Buffer
User->>Discord: ;base64 encode "Hello World"
Discord->>Base64Command: Invoke encode callback
Base64Command->>Base64Command: Validate input exists
Base64Command->>Buffer: Convert UTF-8 to Base64
Buffer-->>Base64Command: "SGVsbG8gV29ybGQ="
Base64Command->>Base64Command: Format embed (green)
Base64Command-->>Discord: Reply with encoded result
Discord-->>User: Display embed
User->>Discord: ;base64 decode "SGVsbG8gV29ybGQ="
Discord->>Base64Command: Invoke decode callback
Base64Command->>Base64Command: Validate input exists
Base64Command->>Buffer: Convert Base64 to UTF-8
Buffer-->>Base64Command: "Hello World"
Base64Command->>Base64Command: Check for null bytes
Base64Command->>Base64Command: Format embed (blue)
Base64Command-->>Discord: Reply with decoded result
Discord-->>User: Display embed
User->>Discord: ;base64 decode "invalid!!!"
Discord->>Base64Command: Invoke decode callback
Base64Command->>Buffer: Attempt decode
Buffer-->>Base64Command: Error thrown
Base64Command->>Base64Command: Format error embed (red)
Base64Command-->>Discord: Reply with error
Discord-->>User: Display error message
🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
|
✅ You're good to merge this PR! No issues found. Great job! Settings⚙️ SettingsSeverity Threshold: 📖 User Guide
|
|
Note Linting checks passed successfully 🎉 All formatting and code quality checks are clean. You're good to merge 🚀 |
Summary by BeetleThis PR introduces two developer experience and feature enhancements to the Discord bot: a conflict detection utility for command name/alias validation and an enhanced GitHub profile command with visual contribution activity graphs. The first commit adds a static analysis script to prevent command naming conflicts across the bot's command registry, while the second commit enriches the 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 6 files changed, +376 additions, -51 deletions 🗺️ Walkthrough:graph TD
A["User runs ;profile command"] --> B["Parse GitHub username"]
B --> C["Fetch user data from GitHub API"]
C --> D["Generate contribution heatmap"]
D --> E{"Heatmap generation successful?"}
E -->|"Yes"| F["Attach heatmap image"]
E -->|"No"| G["Log error, continue without image"]
F --> H["Build embed with stats"]
G --> H
H --> I["Send reply with embed + attachment"]
J["Developer runs npm run check:conflicts"] --> K["Scan all command files in src/commands"]
K --> L["Parse name and aliases from each file"]
L --> M["Register identifiers in global map"]
M --> N{"Conflicts detected?"}
N -->|"Yes"| O["Print conflict report with file locations"]
N -->|"No"| P["Print success message"]
style D fill:#26a641
style K fill:#0e4429
style E fill:#ffd700
style N fill:#ffd700
🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
|
Note Linting checks passed successfully 🎉 All formatting and code quality checks are clean. You're good to merge 🚀 |
|
Important Review skipped Bot user detected. To trigger a single review, invoke the ⚙️ SettingsSeverity Threshold: 📖 User Guide
|
|
Tip Make sure to check the following before pushing:
Then fix the issues, commit, and push again. Note This is just a friendly reminder and will not block the PR from being merged. |
Summary by BeetleThis PR introduces several developer utility features and improvements to the Discord bot, focusing on GitHub integration enhancements, encoding utilities, and internal tooling. The main additions include a Base64 encoder/decoder command, a conflict detection script for command validation, and a visual GitHub contribution activity graph integrated into the profile command. 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 7 files changed, +471 additions, -52 deletions 🗺️ Walkthrough:graph TD
A["User invokes ;profile username"] --> B["profile.ts: Fetch GitHub API"]
B --> C["Generate contribution heatmap"]
C --> D["githubActivityGraph.ts: Fetch from jogruber API"]
D --> E["Parse contribution data into columns"]
E --> F["Render heatmap using canvas"]
F --> G["Create PNG buffer"]
G --> H["Attach to Discord embed"]
H --> I["Reply with profile + heatmap"]
J["User invokes ;base64 encode text"] --> K["base64.ts: Validate input"]
K --> L["Buffer.from utf8 to base64"]
L --> M["Return encoded result in embed"]
N["User invokes ;base64 decode string"] --> O["base64.ts: Validate input"]
O --> P["Buffer.from base64 to utf8"]
P --> Q{"Valid Base64?"}
Q -->|Yes| R["Return decoded text"]
Q -->|No| S["Return error embed"]
T["Developer runs npm run check:conflicts"] --> U["conflicts.ts: Scan commands dir"]
U --> V["Parse all .ts files for name/aliases"]
V --> W["Build identifier registry"]
W --> X{"Conflicts found?"}
X -->|Yes| Y["Print conflict report"]
X -->|No| Z["Print success message"]
🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
Summary by BeetleThis PR introduces three new features to enhance the Discord bot's utility toolkit: a Base64 encoder/decoder command, a conflict detection script for command validation, and a GitHub contribution activity heatmap visualization. The changes focus on expanding developer tools, improving code quality assurance, and enriching the GitHub profile command with visual contribution data. 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 7 files changed, +492 additions, -57 deletions 🗺️ Walkthrough:graph TD
A["User invokes ;base64 encode/decode"] --> B["base64.ts command handler"]
B --> C{"Validate input"}
C -->|"Missing input"| D["Return error embed"]
C -->|"Valid input"| E{"Encode or Decode?"}
E -->|"Encode"| F["Buffer.from text to base64"]
E -->|"Decode"| G["Buffer.from base64 to utf8"]
G --> H{"Valid Base64?"}
H -->|"Invalid"| I["Return error embed"]
H -->|"Valid"| J["Return success embed"]
F --> J
K["User invokes ;profile username"] --> L["profile.ts command handler"]
L --> M["Fetch GitHub API user data"]
M --> N["generateGitHubHeatMap username"]
N --> O["fetchContributionData with 10s timeout"]
O --> P["github-contributions-api.jogruber.de"]
P --> Q["Parse contribution levels by week"]
Q --> R["Render heatmap canvas with rounded cells"]
R --> S["Return PNG buffer"]
S --> T["Attach heatmap.png to embed"]
T --> U["Reply with profile embed + graph"]
V["Developer runs npm run check:conflicts"] --> W["conflicts.ts script"]
W --> X["Scan all .ts files in commands/"]
X --> Y["Parse name and aliases via regex"]
Y --> Z["Build global identifier registry"]
Z --> AA{"Conflicts detected?"}
AA -->|"Yes"| AB["Print conflict report"]
AA -->|"No"| AC["Print success message"]
🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
| try { | ||
| const decoded = Buffer.from(input, "base64").toString("utf8"); | ||
|
|
||
| if (!decoded || decoded.includes("\u0000")) { | ||
| throw new Error("Invalid Base64"); | ||
| } |
There was a problem hiding this comment.
Missing input length validation before Base64 decoding creates a potential Denial of Service (DoS) vulnerability. An attacker could provide an extremely long Base64 string that decodes to a massive UTF-8 output, causing memory exhaustion. Additionally, the validation logic at line 57 is insufficient - it only checks for null bytes but doesn't validate maximum decoded length or other problematic content.
Confidence: 5/5
Suggested Fix
| try { | |
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
| if (!decoded || decoded.includes("\u0000")) { | |
| throw new Error("Invalid Base64"); | |
| } | |
| try { | |
| // Validate input length before decoding to prevent DoS | |
| if (input.length > 10000) { | |
| throw new Error("Input too long"); | |
| } | |
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
| // Validate decoded output | |
| if (!decoded) { | |
| throw new Error("Empty decode result"); | |
| } | |
| if (decoded.includes("\u0000")) { | |
| throw new Error("Invalid Base64"); | |
| } | |
| // Validate decoded length to prevent memory issues | |
| if (decoded.length > 50000) { | |
| throw new Error("Decoded output too large"); | |
| } | |
Add input validation before decoding to prevent DoS attacks. Validate both the input Base64 string length (before decoding) and the decoded output length (after decoding). The limits should be adjusted based on your application's requirements, but should prevent processing of maliciously large inputs.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/tools/base64.ts around line 54-59, add input validation before
Base64 decoding to prevent DoS attacks. Validate the input Base64 string length
before decoding (e.g., max 10000 characters) and validate the decoded output
length after decoding (e.g., max 50000 characters) to prevent memory exhaustion
from maliciously large inputs. Also improve the validation logic to distinguish
between empty results, null bytes, and oversized outputs with appropriate error
messages.
📍 This suggestion applies to lines 54-59
| } | ||
|
|
||
| try { | ||
| const decoded = Buffer.from(input, "base64").toString("utf8"); |
There was a problem hiding this comment.
The decode operation lacks input size validation, which could cause memory exhaustion if an attacker provides an extremely large Base64 string. This could lead to service disruption or denial of service.
Confidence: 5/5
Suggested Fix
Add input size validation before attempting to decode. Limit the input to a reasonable size (e.g., 10MB when decoded):
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
| const MAX_INPUT_SIZE = 10 * 1024 * 1024; // 10MB decoded size limit | |
| const estimatedSize = (input.length * 3) / 4; // Base64 decoding size estimate | |
| if (estimatedSize > MAX_INPUT_SIZE) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Input Too Large") | |
| .setDescription("The Base64 string is too large to decode. Maximum size is 10MB.") | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
Add size validation before the decode operation to prevent memory exhaustion attacks. The estimated decoded size is calculated as (input.length * 3) / 4 since Base64 encoding increases size by approximately 33%.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/tools/base64.ts at line 55, add input size validation before
decoding Base64 to prevent memory exhaustion attacks. Add a check that estimates
the decoded size using (input.length * 3) / 4 and rejects inputs that would
decode to more than 10MB, returning an appropriate error embed to the user.
| return message.reply({ embeds: [embed] }); | ||
| } | ||
|
|
||
| const encoded = Buffer.from(text, "utf8").toString("base64"); |
There was a problem hiding this comment.
The encode operation lacks input size validation, which could cause memory exhaustion if an attacker provides an extremely large text string. This could lead to service disruption or denial of service.
Confidence: 5/5
Suggested Fix
Add input size validation before attempting to encode:
| const encoded = Buffer.from(text, "utf8").toString("base64"); | |
| const MAX_INPUT_SIZE = 10 * 1024 * 1024; // 10MB limit | |
| const inputSize = Buffer.byteLength(text, "utf8"); | |
| if (inputSize > MAX_INPUT_SIZE) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Input Too Large") | |
| .setDescription("The text is too large to encode. Maximum size is 10MB.") | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| const encoded = Buffer.from(text, "utf8").toString("base64"); | |
Add size validation before the encode operation to prevent memory exhaustion. Use Buffer.byteLength() to get the actual byte size of the UTF-8 string, as some characters may be multi-byte.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/tools/base64.ts at line 21, add input size validation before
encoding to prevent memory exhaustion attacks. Check if the input text exceeds
10MB using Buffer.byteLength(text, "utf8") and return an appropriate error
embed if it does, before attempting the Base64 encoding operation.
|
Note Linting checks passed successfully 🎉 All formatting and code quality checks are clean. You're good to merge 🚀 |
| const res = await fetch( | ||
| `https://github-contributions-api.jogruber.de/v4/${encodeURIComponent(username)}?y=last`, | ||
| { headers: { "User-Agent": "github-heatmap-generator" } }, | ||
| ); |
There was a problem hiding this comment.
Missing timeout configuration for external API fetch call creates a potential Denial of Service vulnerability. If the third-party API (jogruber.de) becomes unresponsive or experiences network issues, this fetch call could hang indefinitely, blocking the Discord bot's event loop and preventing it from processing other commands.
Confidence: 5/5
Suggested Fix
| const res = await fetch( | |
| `https://github-contributions-api.jogruber.de/v4/${encodeURIComponent(username)}?y=last`, | |
| { headers: { "User-Agent": "github-heatmap-generator" } }, | |
| ); | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout | |
| try { | |
| const res = await fetch( | |
| `https://github-contributions-api.jogruber.de/v4/${encodeURIComponent(username)}?y=last`, | |
| { | |
| headers: { "User-Agent": "github-heatmap-generator" }, | |
| signal: controller.signal | |
| }, | |
| ); | |
| clearTimeout(timeoutId); | |
Add an AbortController with a timeout to prevent hanging requests. Wrap the fetch in a try-catch block and clear the timeout on success. This ensures the bot remains responsive even if the external API is slow or unresponsive.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/utils/githubActivityGraph.ts around line 64-67, add timeout protection
to the fetch call to prevent hanging requests. Create an AbortController with
a 10-second timeout, pass its signal to the fetch options, and clear the timeout
after successful fetch. This prevents the Discord bot from hanging if the
third-party API becomes unresponsive.
📍 This suggestion applies to lines 64-67
|
|
||
| async function parseCommandFile(filePath: string): Promise<CommandMeta | null> { | ||
| try { | ||
| const content = await fs.readFile(filePath, "utf8"); |
There was a problem hiding this comment.
The script reads command files without size validation, which could cause memory exhaustion if an attacker places an extremely large file in the commands directory. This could lead to denial of service during the conflict scanning process.
Confidence: 5/5
Suggested Fix
Add file size validation before reading:
| const content = await fs.readFile(filePath, "utf8"); | |
| const stats = await fs.stat(filePath); | |
| const MAX_FILE_SIZE = 1 * 1024 * 1024; // 1MB limit for command files | |
| if (stats.size > MAX_FILE_SIZE) { | |
| console.warn( | |
| `⚠️ Skipped (file too large): ${path.relative(COMMANDS_DIR, filePath)}` | |
| ); | |
| return null; | |
| } | |
| const content = await fs.readFile(filePath, "utf8"); | |
Check the file size using fs.stat() before reading it. Command files should typically be small (a few KB), so a 1MB limit is reasonable and prevents memory exhaustion attacks.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/scripts/conflicts.ts at line 36, add file size validation before reading
command files to prevent memory exhaustion. Use fs.stat() to check the file size
and skip files larger than 1MB with an appropriate warning message, as command
files should be small and this prevents potential denial of service attacks.
| const controller = new AbortController(); | ||
| const timeoutId = setTimeout(() => controller.abort(), 10_000); | ||
|
|
||
| let res: Response; |
There was a problem hiding this comment.
The fetch request to the external API lacks a timeout configuration, which could cause the Discord bot to hang indefinitely if the third-party service becomes unresponsive. This could lead to resource exhaustion and denial of service.
Confidence: 5/5
Suggested Fix
Add a timeout using AbortController to prevent indefinite hanging:
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10_000); | |
| let res: Response; | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout | |
| try { | |
| const res = await fetch( | |
| `https://github-contributions-api.jogruber.de/v4/${encodeURIComponent(username)}?y=last`, | |
| { | |
| headers: { "User-Agent": "github-heatmap-generator" }, | |
| signal: controller.signal | |
| }, | |
| ); | |
| clearTimeout(timeoutId); | |
Wrap the fetch in a try-catch to handle AbortError and provide a meaningful error message. Add clearTimeout(timeoutId) after successful fetch to prevent memory leaks.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/utils/githubActivityGraph.ts at lines 64-67, add timeout protection to the
fetch request using AbortController with a 10-second timeout. This prevents the
bot from hanging indefinitely if the third-party API becomes unresponsive. Include
proper cleanup with clearTimeout and handle AbortError in the catch block.
📍 This suggestion applies to lines 64-67
Co-authored-by: beetle-ai[bot] <221859081+beetle-ai[bot]@users.noreply.github.com>
Summary by BeetleThis PR introduces three new developer utility features to the Discord bot: a Base64 encoding/decoding command, a command conflict detection script for maintaining command uniqueness, and an enhanced GitHub profile command with visual contribution activity graphs. The changes focus on improving developer experience through better tooling and richer GitHub integration. 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 7 files changed, +492 additions, -60 deletions 🗺️ Walkthrough:graph TD
A["User invokes ;base64 encode/decode"] --> B["base64.ts command handler"]
B --> C{"Validate input"}
C -->|"Valid"| D["Buffer encode/decode"]
C -->|"Invalid"| E["Return error embed"]
D --> F["Return success embed with result"]
G["User invokes ;profile username"] --> H["profile.ts command handler"]
H --> I["Fetch GitHub API user data"]
I --> J["generateGitHubHeatMap()"]
J --> K["Fetch contribution data from jogruber API"]
K -->|"Timeout after 10s"| L["AbortController cancels request"]
K -->|"Success"| M["Parse contribution levels by week"]
M --> N["Render heatmap with canvas"]
N --> O["Create rounded rectangle cells"]
O --> P["Apply color based on contribution level"]
P --> Q["Return PNG buffer"]
Q --> R["Attach heatmap to Discord embed"]
R --> S["Send profile embed with activity graph"]
T["Developer runs npm run check:conflicts"] --> U["conflicts.ts script"]
U --> V["Scan all command files recursively"]
V --> W["Parse name and aliases from each file"]
W --> X["Register identifiers in global map"]
X --> Y{"Detect conflicts?"}
Y -->|"Yes"| Z["Print conflict report with file paths"]
Y -->|"No"| AA["Print success message"]
🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
| return message.reply({ embeds: [embed] }); | ||
| } | ||
|
|
||
| const encoded = Buffer.from(text, "utf8").toString("base64"); |
There was a problem hiding this comment.
The encoding operation lacks input size validation before creating a Buffer. A malicious user could provide extremely large text input (e.g., millions of characters), causing excessive memory allocation and potentially crashing the bot or causing service disruption.
Confidence: 5/5
Suggested Fix
Add input size validation before encoding to prevent memory exhaustion attacks:
| const encoded = Buffer.from(text, "utf8").toString("base64"); | |
| const MAX_INPUT_SIZE = 100000; // 100KB limit | |
| const text = args.join(" "); | |
| if (!text) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Missing Input") | |
| .setDescription("Please provide some text to encode.") | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| if (text.length > MAX_INPUT_SIZE) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Input Too Large") | |
| .setDescription(`Text is too large to encode. Maximum size: ${MAX_INPUT_SIZE} characters.`) | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| const encoded = Buffer.from(text, "utf8").toString("base64"); | |
Add size validation immediately after checking if text exists to prevent memory exhaustion from oversized inputs.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/tools/base64.ts around line 11-21, the encode function lacks input size validation before creating a Buffer, which could allow malicious users to cause memory exhaustion by providing extremely large text inputs; add a MAX_INPUT_SIZE constant (e.g., 100000 characters) and validate text.length against it after the empty check but before the Buffer.from() operation, returning an appropriate error embed if the limit is exceeded.
| } | ||
|
|
||
| try { | ||
| const decoded = Buffer.from(input, "base64").toString("utf8"); |
There was a problem hiding this comment.
The decode operation lacks input size validation before creating a Buffer. A malicious user could provide an extremely large Base64 string, causing excessive memory allocation during decoding and potentially crashing the bot or causing service disruption.
Confidence: 5/5
Suggested Fix
Add input size validation before decoding to prevent memory exhaustion attacks:
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
| const MAX_INPUT_SIZE = 100000; // 100KB limit | |
| const input = args.join(" "); | |
| if (!input) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Missing Input") | |
| .setDescription("Please provide a Base64 string to decode.") | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| if (input.length > MAX_INPUT_SIZE) { | |
| const embed = new EmbedBuilder() | |
| .setTitle("❌ Input Too Large") | |
| .setDescription(`Base64 input is too large to decode. Maximum size: ${MAX_INPUT_SIZE} characters.`) | |
| .setColor(0xe74c3c); | |
| return message.reply({ embeds: [embed] }); | |
| } | |
| try { | |
| const decoded = Buffer.from(input, "base64").toString("utf8"); | |
Add size validation immediately after checking if input exists to prevent memory exhaustion from oversized Base64 strings.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/tools/base64.ts around line 44-55, the decode function lacks input size validation before creating a Buffer, which could allow malicious users to cause memory exhaustion by providing extremely large Base64 strings; add a MAX_INPUT_SIZE constant (e.g., 100000 characters) and validate input.length against it after the empty check but before the try block, returning an appropriate error embed if the limit is exceeded.
|
Note Linting checks passed successfully 🎉 All formatting and code quality checks are clean. You're good to merge 🚀 |
| const row = new ActionRowBuilder().addComponents(button); | ||
| let heatmapAttachment: AttachmentBuilder | null = null; | ||
| try { | ||
| const heatmapBuffer = await generateGitHubHeatMap(user || ""); |
There was a problem hiding this comment.
The user variable is used with a fallback to empty string (user || ""), but user is extracted from regex match at line 50 and should always be defined at this point. However, if user is somehow undefined, passing an empty string to generateGitHubHeatMap("") will cause the function to make an API call with an invalid username, potentially causing errors or unexpected behavior. This indicates a logic error in the flow.
Confidence: 5/5
Suggested Fix
| const heatmapBuffer = await generateGitHubHeatMap(user || ""); | |
| const heatmapBuffer = await generateGitHubHeatMap(user); | |
Remove the || "" fallback since user is guaranteed to be defined at this point (extracted from regex match at line 50). If there's concern about undefined values, the proper fix is to add validation earlier in the flow, not to pass empty strings to API functions.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/commands/github/profile.ts around line 78, the generateGitHubHeatMap call uses `user || ""` as a fallback, but the user variable is extracted from a regex match at line 50 and should always be defined at this point; remove the `|| ""` fallback and pass `user` directly since it's guaranteed to exist, or if there's genuine concern about undefined values, add proper validation earlier in the flow rather than passing empty strings to API functions which could cause unexpected behavior.
| const controller = new AbortController(); | ||
| const timeoutId = setTimeout(() => controller.abort(), 10_000); | ||
|
|
||
| let res: Response; |
There was a problem hiding this comment.
The fetch request to the third-party API lacks timeout configuration. If the external service (github-contributions-api.jogruber.de) becomes unresponsive or experiences network issues, this will cause the Discord bot to hang indefinitely, blocking the command execution and potentially causing service disruption for users.
Confidence: 5/5
Suggested Fix
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10_000); | |
| let res: Response; | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout | |
| try { | |
| const res = await fetch( | |
| `https://github-contributions-api.jogruber.de/v4/${encodeURIComponent(username)}?y=last`, | |
| { | |
| headers: { "User-Agent": "github-heatmap-generator" }, | |
| signal: controller.signal | |
| }, | |
| ); | |
| clearTimeout(timeoutId); | |
Add an AbortController with a 10-second timeout to prevent indefinite hanging when the external API is unresponsive. Clear the timeout after successful fetch to avoid memory leaks.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/utils/githubActivityGraph.ts around line 64-67, the fetch request to the third-party github-contributions-api lacks timeout configuration which could cause the bot to hang indefinitely if the service is unresponsive; create an AbortController before the fetch call, set a timeout of 10000ms that calls controller.abort(), pass the controller.signal to the fetch options, and clear the timeout after the fetch completes successfully to prevent memory leaks and ensure the request fails gracefully after 10 seconds.
📍 This suggestion applies to lines 64-67
| signal: controller.signal, | ||
| }, | ||
| ); | ||
| } catch (err) { |
There was a problem hiding this comment.
The res.json() call lacks error handling for malformed JSON responses. If the third-party API returns invalid JSON (due to service errors, network corruption, or unexpected responses), this will throw an unhandled error that bypasses the user-friendly error messages and could expose raw error details or crash the command execution.
Confidence: 5/5
Suggested Fix
| } catch (err) { | |
| let json: JogruberResponse; | |
| try { | |
| json = await res.json(); | |
| } catch (err) { | |
| throw new Error("Failed to parse contribution data from github-contributions-api"); | |
| } | |
Wrap the JSON parsing in a try-catch block to handle malformed responses gracefully and throw a user-friendly error message instead of exposing raw parsing errors.
Prompt for AI
Copy this prompt to your AI IDE to fix this issue locally:
In src/utils/githubActivityGraph.ts around line 76, the res.json() call lacks error handling for malformed JSON responses from the third-party API; wrap the await res.json() call in a try-catch block, declare json as a let variable with type JogruberResponse before the try block, assign it inside the try block, and in the catch block throw a new Error with message "Failed to parse contribution data from github-contributions-api" to provide a clear error message instead of exposing raw JSON parsing errors.
Summary by BeetleThis PR fixes a Discord UI rendering issue in the changelog command by removing backticks from select menu labels. Backticks in Discord select menu labels can cause rendering problems or unexpected behavior, so this change sanitizes the version titles by stripping out backtick characters before displaying them in dropdown menus. 📁 File Changes Summary (Consolidated across all commits):
Total Changes: 2 files changed, +9 additions, -8 deletions 🎯 Key Changes:
📊 Impact Assessment:
⚙️ SettingsSeverity Threshold: 📖 User Guide
|
|
✅ You're good to merge this PR! No issues found. Great job! Settings⚙️ SettingsSeverity Threshold: 📖 User Guide
|
No description provided.