Skip to content

Instantly share code, notes, and snippets.

@Qubus0
Last active October 7, 2025 16:14
Show Gist options
  • Save Qubus0/90f6841aa40284a4626bfce6c1226393 to your computer and use it in GitHub Desktop.
Save Qubus0/90f6841aa40284a4626bfce6c1226393 to your computer and use it in GitHub Desktop.
yagbdb discord bot custom command to block image spambots
{{/* === CONFIGURATION === */}}
{{/* where to log the action and deleted message */}}
{{$logChannel := 000000000000 }}
{{/* how often the same message needs to be sent in the timespan to trigger the command */}}
{{$triggerThreshold := 5 }}
{{/* the timespan between messages until they are no longer considered duplicates */}}
{{$duplicateTrackExpirationSeconds := 120 }}
{{/* how long to time out the offending user, blocks bots from spamming further */}}
{{$timeoutDurationMinutes := 300 }}
{{/* === SCRIPT START === */}}
{{/* DB keys for this user */}}
{{$userID := .User.ID}}
{{$counterKey := print "spamCounter:" $userID}}
{{$msgsKey := print "spamMsgs:" $userID}}
{{/* Fetch existing data */}}
{{$currentCounter := 0}}
{{with (dbGet $userID $counterKey)}}{{$currentCounter = .Value}}{{end}}
{{/* Add message to the stored list */}}
{{$existingMsgs := cslice}}
{{with (dbGet $userID $msgsKey)}}{{$existingMsgs = .Value}}{{end}}
{{$newMsg := dict "ID" .Message.ID "Content" .Message.Content "ChannelID" .Channel.ID}}
{{$updatedMsgs := $existingMsgs.Append $newMsg}}
{{/* Increase counter and reset DB expiration */}}
{{$newCounter := add $currentCounter 1}}
{{dbSetExpire $userID $counterKey $newCounter $duplicateTrackExpirationSeconds}}
{{dbSetExpire $userID $msgsKey $updatedMsgs $duplicateTrackExpirationSeconds}}
{{if ge (toInt $newCounter) $triggerThreshold}}
{{try}}
{{$noOutput := execAdmin "timeout" .User.Mention $timeoutDurationMinutes "Image Spam (Suspected Scambot)"}}
{{catch}}
{{sendMessage $logChannel (.Error) }}
{{end}}
{{/* Log the action */}}
{{$logMsg := (printf "**Anti-Imagescam Triggered**\n\nUser: %s \nDeleting %d messages:\n\n" .User.Mention (len $updatedMsgs))}}
{{/* Get the first message */}}
{{$firstMsg := index $updatedMsgs 0}}
{{$cleanContent := $firstMsg.Content}}
{{$embed := cembed
"description" (print $cleanContent)
"color" 16711680
"footer" (dict "text" (print "Triggered at: " currentTime))
"author" (sdict
"name" .User.Username
"icon_url" (.Member.AvatarURL "256")
)
}}
{{sendMessage $logChannel (complexMessage "content" $logMsg "embed" $embed)}}
{{/* Delete all stored messages */}}
{{range $msg := $updatedMsgs}}
{{deleteMessage (toInt64 $msg.ChannelID) (toInt64 $msg.ID) 0}}
{{end}}
{{/* Clear user data after action */}}
{{dbDel $userID $counterKey}}
{{dbDel $userID $msgsKey}}
{{end}}
@Qubus0
Copy link
Author

Qubus0 commented Sep 30, 2025

Setup

The custom command trigger is a Regex matching images hosted on discord: .*?(?:media|cdn)\.discord(app)?\.(?:net|com).*? but this can be adjusted on the fly if they ever swap to other hosting or generalised to get any image

Make sure to also set the $logChannel and ignore that channel in the command settings

Why?

This command specifically targets Discord spambots posting images to circumvent text automoderation

like this one image

This can be complemented with this other automoderation rule in case they switch to directly uploading images to discord instead of sending links - those will actually be caught by the "with attachments" filter.

image

Notes

  • The custom command matches image links because linked files are not considered attachments by discord
  • The automod rule bans for one minute because message mass deletion is restricted to a single channel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment