-
Notifications
You must be signed in to change notification settings - Fork 1
feat: handle send message with file and mediaId resolving #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
47f12ad
c4909ea
dd7a3da
4a6b1db
e13c254
e487775
1cb541b
e8e86cb
3d1490b
a05f296
2d04658
ce8e734
eb565f6
1a8cf31
c9378e5
ec7bf0e
9fc4d30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # This file ensures the media/temp directory is tracked by git | ||
| # Temporary media files will be processed in this directory |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # This file ensures the media/uploads directory is tracked by git | ||
| # Media files will be stored in this directory |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,21 @@ export interface WebhookConfig { | |||||||||||||||||||||||||||||||||||||||
| fallbackUrl: string | null | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export interface MediaConfig { | ||||||||||||||||||||||||||||||||||||||||
| /** Base directory for media storage */ | ||||||||||||||||||||||||||||||||||||||||
| baseDir: string | ||||||||||||||||||||||||||||||||||||||||
| /** Directory for uploaded files */ | ||||||||||||||||||||||||||||||||||||||||
| uploadsDir: string | ||||||||||||||||||||||||||||||||||||||||
| /** Directory for temporary files */ | ||||||||||||||||||||||||||||||||||||||||
| tempDir: string | ||||||||||||||||||||||||||||||||||||||||
| /** Maximum file size in bytes (default: 10MB) */ | ||||||||||||||||||||||||||||||||||||||||
| maxFileSize: number | ||||||||||||||||||||||||||||||||||||||||
| /** Allowed file extensions */ | ||||||||||||||||||||||||||||||||||||||||
| allowedExtensions: string[] | ||||||||||||||||||||||||||||||||||||||||
| /** Allowed MIME types */ | ||||||||||||||||||||||||||||||||||||||||
| allowedMimeTypes: string[] | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Parse CLI arguments for webhook URL mappings | ||||||||||||||||||||||||||||||||||||||||
| * Format: --webhook-url phone:url | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,8 +92,79 @@ function initializeWebhookConfig(): WebhookConfig { | |||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Global configuration instance | ||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Initialize media configuration with default values | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| function initializeMediaConfig(): MediaConfig { | ||||||||||||||||||||||||||||||||||||||||
| const baseDir = process.env.MEDIA_DIR || './media' | ||||||||||||||||||||||||||||||||||||||||
| const maxFileSizeMB = process.env.MAX_FILE_SIZE_MB | ||||||||||||||||||||||||||||||||||||||||
| ? Number.parseInt(process.env.MAX_FILE_SIZE_MB) | ||||||||||||||||||||||||||||||||||||||||
| : 10 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+100
to
+103
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Robustness: handle non-numeric
- const maxFileSizeMB = process.env.MAX_FILE_SIZE_MB
- ? Number.parseInt(process.env.MAX_FILE_SIZE_MB)
- : 10
+ const rawMb = process.env.MAX_FILE_SIZE_MB
+ const maxFileSizeMB =
+ rawMb && !Number.isNaN(Number.parseInt(rawMb))
+ ? Number.parseInt(rawMb)
+ : 10📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||
| baseDir, | ||||||||||||||||||||||||||||||||||||||||
| uploadsDir: `${baseDir}/uploads`, | ||||||||||||||||||||||||||||||||||||||||
| tempDir: `${baseDir}/temp`, | ||||||||||||||||||||||||||||||||||||||||
| maxFileSize: maxFileSizeMB * 1024 * 1024, // Convert MB to bytes | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+104
to
+108
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Cross-platform path handling. String interpolation with +import { join } from 'node:path';
...
- uploadsDir: `${baseDir}/uploads`,
- tempDir: `${baseDir}/temp`,
+ uploadsDir: join(baseDir, 'uploads'),
+ tempDir: join(baseDir, 'temp'),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| allowedExtensions: [ | ||||||||||||||||||||||||||||||||||||||||
| // Images | ||||||||||||||||||||||||||||||||||||||||
| '.jpg', | ||||||||||||||||||||||||||||||||||||||||
| '.jpeg', | ||||||||||||||||||||||||||||||||||||||||
| '.png', | ||||||||||||||||||||||||||||||||||||||||
| '.gif', | ||||||||||||||||||||||||||||||||||||||||
| '.webp', | ||||||||||||||||||||||||||||||||||||||||
| // Documents | ||||||||||||||||||||||||||||||||||||||||
| '.pdf', | ||||||||||||||||||||||||||||||||||||||||
| '.doc', | ||||||||||||||||||||||||||||||||||||||||
| '.docx', | ||||||||||||||||||||||||||||||||||||||||
| '.txt', | ||||||||||||||||||||||||||||||||||||||||
| '.csv', | ||||||||||||||||||||||||||||||||||||||||
| // Audio | ||||||||||||||||||||||||||||||||||||||||
| '.mp3', | ||||||||||||||||||||||||||||||||||||||||
| '.wav', | ||||||||||||||||||||||||||||||||||||||||
| '.ogg', | ||||||||||||||||||||||||||||||||||||||||
| '.m4a', | ||||||||||||||||||||||||||||||||||||||||
| // Video | ||||||||||||||||||||||||||||||||||||||||
| '.mp4', | ||||||||||||||||||||||||||||||||||||||||
| '.mov', | ||||||||||||||||||||||||||||||||||||||||
| '.avi', | ||||||||||||||||||||||||||||||||||||||||
| '.webm', | ||||||||||||||||||||||||||||||||||||||||
| // Other | ||||||||||||||||||||||||||||||||||||||||
| '.zip', | ||||||||||||||||||||||||||||||||||||||||
| '.rar', | ||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||
| allowedMimeTypes: [ | ||||||||||||||||||||||||||||||||||||||||
| // Images | ||||||||||||||||||||||||||||||||||||||||
| 'image/jpeg', | ||||||||||||||||||||||||||||||||||||||||
| 'image/png', | ||||||||||||||||||||||||||||||||||||||||
| 'image/gif', | ||||||||||||||||||||||||||||||||||||||||
| 'image/webp', | ||||||||||||||||||||||||||||||||||||||||
| // Documents | ||||||||||||||||||||||||||||||||||||||||
| 'application/pdf', | ||||||||||||||||||||||||||||||||||||||||
| 'application/msword', | ||||||||||||||||||||||||||||||||||||||||
| 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | ||||||||||||||||||||||||||||||||||||||||
| 'text/plain', | ||||||||||||||||||||||||||||||||||||||||
| 'text/csv', | ||||||||||||||||||||||||||||||||||||||||
| // Audio | ||||||||||||||||||||||||||||||||||||||||
| 'audio/mpeg', | ||||||||||||||||||||||||||||||||||||||||
| 'audio/wav', | ||||||||||||||||||||||||||||||||||||||||
| 'audio/ogg', | ||||||||||||||||||||||||||||||||||||||||
| 'audio/mp4', | ||||||||||||||||||||||||||||||||||||||||
| // Video | ||||||||||||||||||||||||||||||||||||||||
| 'video/mp4', | ||||||||||||||||||||||||||||||||||||||||
| 'video/quicktime', | ||||||||||||||||||||||||||||||||||||||||
| 'video/x-msvideo', | ||||||||||||||||||||||||||||||||||||||||
| 'video/webm', | ||||||||||||||||||||||||||||||||||||||||
| // Other | ||||||||||||||||||||||||||||||||||||||||
| 'application/zip', | ||||||||||||||||||||||||||||||||||||||||
| 'application/x-rar-compressed', | ||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Global configuration instances | ||||||||||||||||||||||||||||||||||||||||
| let webhookConfig: WebhookConfig | null = null | ||||||||||||||||||||||||||||||||||||||||
| const mediaConfig: MediaConfig = initializeMediaConfig() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Get the global webhook configuration (lazy initialization) | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -90,6 +176,13 @@ export function getWebhookConfig(): WebhookConfig { | |||||||||||||||||||||||||||||||||||||||
| return webhookConfig | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Get the global media configuration | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| export function getMediaConfig(): MediaConfig { | ||||||||||||||||||||||||||||||||||||||||
| return mediaConfig | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Get webhook URL for a specific phone number | ||||||||||||||||||||||||||||||||||||||||
| * @param phoneNumber - The phone number to get webhook URL for | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -133,3 +226,26 @@ export function setWebhookUrl(phoneNumber: string, url: string): void { | |||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| config.mappings.set(phoneNumber, url) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Retrieves the allowed API tokens from environment variables. | ||||||||||||||||||||||||||||||||||||||||
| * @returns {string[]} An array of allowed tokens. | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| export function getAllowedTokens(): string[] { | ||||||||||||||||||||||||||||||||||||||||
| const tokens = process.env.MOCK_API_TOKENS || '' | ||||||||||||||||||||||||||||||||||||||||
| return tokens.split(',').filter(Boolean) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * Retrieves the rate limit configuration from environment variables. | ||||||||||||||||||||||||||||||||||||||||
| * @returns {{windowMs: number, maxRequests: number}} The rate limit configuration. | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| export function getRateLimitConfig(): { | ||||||||||||||||||||||||||||||||||||||||
| windowMs: number | ||||||||||||||||||||||||||||||||||||||||
| maxRequests: number | ||||||||||||||||||||||||||||||||||||||||
| } { | ||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||
| windowMs: Number(process.env.RATE_LIMIT_WINDOW_MS) || 60000, // 1 minute | ||||||||||||||||||||||||||||||||||||||||
| maxRequests: Number(process.env.RATE_LIMIT_MAX_REQUESTS) || 100, // 100 requests per window | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+247
to
+250
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion
If someone sets -return {
- windowMs: Number(process.env.RATE_LIMIT_WINDOW_MS) || 60000,
- maxRequests: Number(process.env.RATE_LIMIT_MAX_REQUESTS) || 100,
-}
+return {
+ windowMs:
+ Number(process.env.RATE_LIMIT_WINDOW_MS) ?? 60000 /* 1 min default */,
+ maxRequests:
+ Number.isNaN(Number(process.env.RATE_LIMIT_MAX_REQUESTS))
+ ? 100
+ : Number(process.env.RATE_LIMIT_MAX_REQUESTS) ?? 100,
+}
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
webphandled twice – sticker branch is dead codeBecause
webpappears in the first condition, the finalelse if (['webp'].includes(extension))is never reached, meaning a sticker will be mis-classified as an image.Alternatively switch to a
switch/map for clarity.📝 Committable suggestion
🤖 Prompt for AI Agents