Message Search System
Discord channel history search with keyword filtering and image detection for /pin command.
Search Functions
Utility module: src/utils/messageSearch.js
Core functions:
findLastPinCommand(channel, maxMessages)– Locates last/pincommand executionsearchMessagesAfter(channel, afterMessageId, maxMessages)– Fetches messages after reference pointgenerateKeywordVariants(keyword)– Creates singular/plural variationsmessageMatchesKeywords(message, keywordVariants)– Tests message content against keywordsmessageHasImages(message)– Detects Midjourney upscaled imagesextractImageMessageIds(channel, keyword, afterMessage, maxResults)– Combines all functions for/pincommand
Last Pin Command Search
Purpose:
Finds most recent /pin command execution in channel.
Algorithm:
- Fetch messages in batches of 100 (Discord limit)
- Iterate through messages chronologically
- Check for interaction command name = "pin"
- Return first matching message
- Continue pagination if not found
Pagination:
- Uses
beforeparameter for backward pagination - Maximum 500 messages searched by default
- 100ms delay between batches to prevent rate limiting
Return value:
- Message object if found
nullif no/pincommand found in range
Use case:
Establishes search starting point for /pin command.
Message Pagination
Backward pagination:
Uses before parameter to fetch older messages.
Forward pagination:
Uses after parameter to fetch newer messages.
Batch size:
100 messages per fetch (Discord maximum).
Rate limiting:
100ms delay between fetches to prevent API throttling.
Continuation:
Stops when:
- Batch returns zero messages
- Maximum message limit reached
- All available messages fetched
Keyword Variant Generation
Purpose:
Automatically handles singular/plural forms.
Algorithm:
- Start with lowercase keyword
- If doesn’t end with ‘s’: Add plural form (keyword + ‘s’)
- If ends with ‘s’ and length > 1: Add singular form (keyword – ‘s’)
Examples:
- "cat" → ["cat", "cats"]
- "dogs" → ["dogs", "dog"]
- "mouse" → ["mouse", "mouses"] (Note: Not linguistically perfect)
Limitations:
- Simple suffix-based logic
- No irregular plural handling (mouse/mice, child/children)
- No stemming or lemmatization
Keyword Matching
Search locations:
- Message content (
message.content) - Embed descriptions (
embed.description) - Embed titles (
embed.title) - Attachment names (
attachment.name)
Match algorithm:
- Collect all text from search locations
- Join into single lowercase string
- Test each keyword variant with
includes() - Return true if any variant matches
Match type:
Substring match (case-insensitive).
Examples:
- Keyword "cat" matches "I love cats"
- Keyword "dog" matches "doghouse"
- Keyword "art" matches "artificial"
Image Detection
Detection criteria:
Messages must contain:
- Text "- Image #" in message content (Midjourney format)
- Actual image attachment or embed
Midjourney format:
- Upscaled images contain "- Image #1", "- Image #2", etc.
- 4-image grid previews do not contain "- Image #"
Image sources:
- Attachments with
image/*content type - Embed image property
- Embed thumbnail property
Exclusion:
4-image grids excluded automatically by "- Image #" requirement.
Purpose:
Ensures found messages contain single upscaled images suitable for pinning.
Message ID Extraction
Purpose:
Main function for /pin command – combines all search capabilities.
Parameters:
channel– Discord channel to searchkeyword– Search termafterMessage– Optional reference message (last/pincommand)maxResults– Maximum message IDs to return (default 10)
Algorithm:
- Generate keyword variants (singular/plural)
- Determine search scope:
- With afterMessage: Search messages after that point
- Without afterMessage: Search 100 most recent messages
- Iterate through messages
- For each message:
- Check if has images (Midjourney upscaled format)
- Check if matches keywords
- Add message ID to results if both true
- Stop when maxResults reached or messages exhausted
Return value:
Array of message IDs (strings) matching criteria.
Search limits:
- Maximum 10 results by default (customizable)
- Searches up to 1000 messages when afterMessage provided
- Searches 100 messages when no afterMessage
Search Scope Determination
With previous /pin command:
/pinfinds last/pinexecution- Searches messages posted after that point
- Useful for finding new images since last pinning session
Without previous /pin command:
- Searches 100 most recent messages
- Useful for first-time usage in channel
Message ordering:
Messages processed chronologically from reference point forward.
Error Handling
Search failures:
- Logged to console
- Returns empty array
- Does not throw errors
Pagination failures:
- Returns messages collected so far
- Logged to console
Rate limiting:
Built-in delays prevent Discord API rate limits.
Performance
Fetch operations:
- Minimum 1 fetch (100 messages)
- Maximum 10 fetches (1000 messages)
- 100ms delay between fetches = 1 second maximum delay
Processing:
- Linear iteration through messages
- No indexing or caching
- Real-time search on command execution
Memory:
Messages stored in array during search, released after completion.