2025-05-29 09:50:07 -04:00
/ *
* Vencord , a modification for Discord ' s desktop app
* Copyright ( c ) 2022 Vendicated , Samu and contributors
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
* /
2025-09-28 11:12:36 -04:00
import { ApplicationCommandInputType , ApplicationCommandOptionType , findOption , OptionalMessageOption , RequiredMessageOption , sendBotMessage } from "@api/Commands" ;
2025-09-10 06:04:17 -04:00
import { addMessagePreEditListener , addMessagePreSendListener , MessageObject , removeMessagePreEditListener , removeMessagePreSendListener } from "@api/MessageEvents" ;
2026-03-07 00:00:51 -05:00
import { migratePluginSettings } from "@api/Settings" ;
2026-06-04 11:58:56 -04:00
import { Devs , EquicordDevs , GUILD_IDS } from "@utils/constants" ;
2025-09-28 11:12:36 -04:00
import { sendMessage } from "@utils/discord" ;
2025-05-29 09:50:07 -04:00
import definePlugin from "@utils/types" ;
2026-03-07 00:00:51 -05:00
import { DraftType , UploadHandler , UploadManager , UserAffinitiesStore , UserStore } from "@webpack/common" ;
import { applyPalette , GIFEncoder , quantize } from "gifenc" ;
2025-05-29 09:50:07 -04:00
2026-03-07 00:00:51 -05:00
import {
calculateAffinityScore ,
calculateCanvasSize ,
FRAMES ,
fromMorse ,
generatePoissonDiskPosition ,
getCuteAnimeBoys ,
getCuteNeko ,
2026-06-04 11:58:56 -04:00
getFavoriteGif ,
2026-03-07 00:00:51 -05:00
isMorse ,
loadFriendImage ,
loadImage ,
makeFreaky ,
mock ,
resolveImage ,
settings ,
toMorse ,
uwuify ,
uwuifyArray
} from "./utils" ;
migratePluginSettings ( "MoreCommands" , "FriendCloud" , "GifRoulette" , "ImgToGif" , "MoreKaomoji" ) ;
2025-05-29 09:50:07 -04:00
export default definePlugin ( {
name : "MoreCommands" ,
2025-09-01 16:16:46 -04:00
description : "Adds various fun and useful commands" ,
2026-04-16 13:45:58 -04:00
dependencies : [ "CommandsAPI" ] ,
tags : [ "Commands" , "Fun" , "Shortcuts" ] ,
2026-03-07 00:00:51 -05:00
authors : [
Devs . Arjix ,
Devs . amy ,
Devs . Samu ,
EquicordDevs . zyqunix ,
EquicordDevs . ShadyGoat ,
Devs . thororen ,
Devs . Korbo ,
Devs . nyx ,
Devs . amy ,
Devs . Samwich ,
EquicordDevs . Fafa ,
Devs . JacobTm ,
EquicordDevs . voidbbg
] ,
2025-09-10 05:14:27 -04:00
settings ,
2025-05-29 09:50:07 -04:00
commands : [
2025-09-28 11:12:36 -04:00
{
name : "systeminfo" ,
description : "Shows system information" ,
options : [ ] ,
execute : async ( opts , ctx ) = > {
try {
const { userAgent , hardwareConcurrency , onLine , languages } = navigator ;
const { width , height , colorDepth } = window . screen ;
const { deviceMemory , connection } : { deviceMemory : any , connection : any ; } = navigator as any ;
const platform = userAgent . includes ( "Windows" ) ? "Windows" :
userAgent . includes ( "Mac" ) ? "MacOS" :
userAgent . includes ( "Linux" ) ? "Linux" : "Unknown" ;
const isMobile = /Mobile|Android|iPhone/i . test ( userAgent ) ;
const deviceType = isMobile ? "Mobile" : "Desktop" ;
const browserInfo = userAgent . match ( /(?:chrome|firefox|safari|edge|opr)\/?\s*(\d+)/i ) ? . [ 0 ] || "Unknown" ;
const networkInfo = connection ? ` ${ connection . effectiveType || "Unknown" } ` : "Unknown" ;
const info = [
` > **Platform**: ${ platform } ` ,
` > **Device Type**: ${ deviceType } ` ,
` > **Browser**: ${ browserInfo } ` ,
` > **CPU Cores**: ${ hardwareConcurrency || "N/A" } ` ,
` > **Memory**: ${ deviceMemory ? ` ${ deviceMemory } GB ` : "N/A" } ` ,
` > **Screen**: ${ width } x ${ height } ( ${ colorDepth } bit) ` ,
` > **Languages**: ${ languages ? . join ( ", " ) } ` ,
` > **Network**: ${ networkInfo } ( ${ onLine ? "Online" : "Offline" } ) `
] . join ( "\n" ) ;
return { content : info } ;
} catch ( err ) {
sendBotMessage ( ctx . channel . id , { content : "Failed to fetch system information" } ) ;
}
} ,
} ,
{
2025-09-28 11:52:06 -04:00
name : "getuptime" ,
2025-09-28 11:12:36 -04:00
description : "Returns the system uptime" ,
execute : async ( ) = > {
const uptime = performance . now ( ) / 1000 ;
const uptimeInfo = ` > **System Uptime**: ${ Math . floor ( uptime / 60 ) } minutes ` ;
return { content : uptimeInfo } ;
} ,
} ,
{
2025-09-28 11:52:06 -04:00
name : "gettime" ,
2025-09-28 11:12:36 -04:00
description : "Returns the current server time" ,
execute : async ( ) = > {
const currentTime = new Date ( ) . toLocaleString ( ) ;
return { content : ` > **Current Time**: ${ currentTime } ` } ;
} ,
} ,
{
name : "choose" ,
description : "Randomly chooses from provided options" ,
options : [
{
name : "choices" ,
description : "Comma-separated list of choices" ,
type : ApplicationCommandOptionType . STRING ,
required : true
}
] ,
execute : opts = > {
const choices = findOption ( opts , "choices" , "" ) . split ( "," ) . map ( c = > c . trim ( ) ) ;
const choice = choices [ Math . floor ( Math . random ( ) * choices . length ) ] ;
return {
content : ` I choose: ${ choice } `
} ;
}
} ,
{
name : "rolldice" ,
description : "Roll a die with the specified number of sides" ,
options : [ RequiredMessageOption ] ,
execute : opts = > {
const sides = parseInt ( findOption ( opts , "message" , "6" ) ) ;
const roll = Math . floor ( Math . random ( ) * sides ) + 1 ;
return {
content : ` You rolled a ${ roll } ! `
} ;
} ,
} ,
{
name : "flipcoin" ,
description : "Flips a coin and returns heads or tails" ,
options : [ ] ,
execute : ( opts , ctx ) = > {
const flip = Math . random ( ) < 0.5 ? "Heads" : "Tails" ;
return {
content : ` The coin landed on: ${ flip } `
} ;
} ,
} ,
{
name : "ask" ,
description : "Ask a yes/no question and get an answer" ,
options : [ RequiredMessageOption ] ,
execute : opts = > {
const question = findOption ( opts , "message" , "" ) ;
const responses = [ "Yes" , "No" , "Maybe" , "Ask again later" , "Definitely not" , "It is certain" ] ;
const response = responses [ Math . floor ( Math . random ( ) * responses . length ) ] ;
return {
content : ` ${ question } - ${ response } `
} ;
} ,
} ,
{
name : "randomanimal" ,
description : "Get a random cat picture" ,
options : [
{
name : "animal" ,
description : "pick your animal" ,
type : ApplicationCommandOptionType . STRING ,
required : true ,
choices : [
{ name : "cat" , value : "cat" , label : "cat" } ,
{ name : "dog" , value : "dog" , label : "dog" } ,
]
}
] ,
execute : ( opts , ctx ) = > {
return ( async ( ) = > {
const animal = findOption ( opts , "animal" ) as string ;
let url ;
if ( animal === "cat" ) {
url = "https://api.thecatapi.com/v1/images/search" ;
} else if ( animal === "dog" ) {
url = "https://api.thedogapi.com/v1/images/search" ;
}
try {
const response = await fetch ( url ) ;
if ( ! response . ok ) throw new Error ( ` Failed to fetch ${ animal } image ` ) ;
const data = await response . json ( ) ;
return {
content : data [ 0 ] . url
} ;
} catch ( err ) {
sendBotMessage ( ctx . channel . id , {
content : "Sorry, couldn't fetch a cat picture right now 😿"
} ) ;
}
} ) ( ) ;
} ,
} ,
{
name : "randomnumber" ,
description : "Generates a random number between two values" ,
options : [
{
name : "min" ,
description : "Minimum value" ,
type : ApplicationCommandOptionType . INTEGER ,
required : true
} ,
{
name : "max" ,
description : "Maximum value" ,
type : ApplicationCommandOptionType . INTEGER ,
required : true
}
] ,
execute : opts = > {
const min = parseInt ( findOption ( opts , "min" , "0" ) ) ;
const max = parseInt ( findOption ( opts , "max" , "100" ) ) ;
const number = Math . floor ( Math . random ( ) * ( max - min + 1 ) ) + min ;
return {
content : ` Random number between ${ min } and ${ max } : ${ number } `
} ;
}
} ,
{
name : "transform" ,
description : "Transform your text with the specified option" ,
options : [
{
name : "text" ,
description : "TEXT TO UPPERCASE" ,
type : ApplicationCommandOptionType . STRING ,
required : true
} ,
{
name : "transformation" ,
description : "transformation to apply to your text" ,
type : ApplicationCommandOptionType . STRING ,
required : true ,
choices : [
{ name : "toLowerCase" , value : "toLowerCase" , label : "toLowerCase" } ,
{ name : "toUpperCase" , value : "toUpperCase" , label : "toUpperCase" } ,
{ name : "toLocaleLowerCase" , value : "toLocaleLowerCase" , label : "toLocaleLowerCase" } ,
{ name : "toLocaleUpperCase" , value : "toLocaleUpperCase" , label : "toLocaleUpperCase" } ,
{ name : "stay the same" , value : "same" , label : "stay the same" }
]
} ,
{
name : "repeat" ,
description : "how many times to repeat" ,
type : ApplicationCommandOptionType . INTEGER ,
required : false
} ,
{
name : "reverse" ,
description : "reverse your text" ,
type : ApplicationCommandOptionType . BOOLEAN ,
required : false
} ,
{
name : "normalize" ,
description : "which normailze option to use" ,
type : ApplicationCommandOptionType . STRING ,
required : false ,
choices : [
{ name : "NFC" , value : "NFC" , label : "NFC" } ,
{ name : "NFD" , value : "NFD" , label : "NFD" } ,
{ name : "NFKC" , value : "NFKC" , label : "NFKC" } ,
{ name : "NFKD" , value : "NFKD" , label : "NFKD" }
]
} ,
] ,
execute : opts = > {
let text = findOption ( opts , "text" ) as string ;
const transform = findOption ( opts , "transformation" ) as string ;
const repeat = findOption ( opts , "repeat" ) as number | undefined ? ? 1 ;
const normalize = findOption ( opts , "normalize" ) as string | undefined ;
const reverse = findOption ( opts , "reverse" ) as boolean | undefined ;
if ( transform !== "same" ) {
text = ( text as any ) [ transform ] ? . call ( text ) ? ? text ;
}
if ( normalize ) text = text . normalize ( normalize ) ;
if ( reverse ) text = text . split ( "" ) . reverse ( ) . join ( "" ) ;
return { content : text.repeat ( repeat ) } ;
} ,
} ,
{
name : "wordcount" ,
description : "Counts the number of words in a message" ,
options : [ RequiredMessageOption ] ,
inputType : ApplicationCommandInputType.BOT ,
execute : ( opts , ctx ) = > {
const message = findOption ( opts , "message" , "" ) ;
const wordCount = message . trim ( ) . split ( /\s+/ ) . length ;
sendBotMessage ( ctx . channel . id , {
content : ` The message contains ${ wordCount } words. `
} ) ;
} ,
} ,
{
name : "countdown" ,
description : "Starts a countdown from a specified number" ,
options : [
{
name : "number" ,
description : "Number to countdown from (max 10)" ,
type : ApplicationCommandOptionType . INTEGER ,
required : true
}
] ,
inputType : ApplicationCommandInputType.BOT ,
execute : async ( opts , ctx ) = > {
const number = Math . min ( parseInt ( findOption ( opts , "number" , "5" ) ) , 10 ) ;
if ( isNaN ( number ) || number < 1 ) {
sendBotMessage ( ctx . channel . id , {
content : "Please provide a valid number between 1 and 10!"
} ) ;
return ;
}
sendBotMessage ( ctx . channel . id , {
content : ` Starting countdown from ${ number } ... `
} ) ;
for ( let i = number ; i >= 0 ; i -- ) {
await new Promise ( resolve = > setTimeout ( resolve , 1000 ) ) ;
sendBotMessage ( ctx . channel . id , {
content : i === 0 ? "🎉 Go! 🎉" : ` ${ i } ... `
} ) ;
}
} ,
} ,
{
name : "nekos" ,
description : "Send Neko" ,
execute : async ( ) = > ( {
content : await getCuteNeko ( )
} )
} ,
{
name : "anime-boys" ,
description : "Send cute anime boys" ,
options : [
{
name : "cat" ,
description : "If set, this will send exclusively cute anime cat boys" ,
type : ApplicationCommandOptionType . BOOLEAN ,
required : false ,
} ,
] ,
execute : async opts = > {
let sub = "cuteanimeboys" ;
const cat = findOption ( opts , "cat" ) as boolean | undefined ;
if ( cat ) sub = "animecatboys" ;
return { content : await getCuteAnimeBoys ( sub ) } ;
} ,
} ,
{
name : "ping" ,
description : "Pings the bot to check if it's responding" ,
options : [ ] ,
inputType : ApplicationCommandInputType.BOT ,
execute : ( opts , ctx ) = > {
sendBotMessage ( ctx . channel . id , {
content : "Pong!"
} ) ;
} ,
} ,
{
name : "echo" ,
description : "Sends a message as Clyde (locally)" ,
options : [ OptionalMessageOption ] ,
inputType : ApplicationCommandInputType.BOT ,
execute : ( opts , ctx ) = > {
const content = findOption ( opts , "message" , "" ) ;
sendBotMessage ( ctx . channel . id , { content } ) ;
} ,
} ,
{
name : "lenny" ,
description : "Sends a lenny face" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " ( ͡° ͜ʖ ͡°)"
} ) ,
} ,
{
name : "mock" ,
description : "mOcK PeOpLe" ,
options : [ RequiredMessageOption ] ,
execute : opts = > ( {
content : mock ( findOption ( opts , "message" , "" ) )
} ) ,
} ,
{
inputType : ApplicationCommandInputType.BUILT_IN_TEXT ,
name : "slap" ,
description : "Slap someone/something." ,
options : [ {
name : "victim" ,
description : "Thing to slap" ,
required : true ,
type : ApplicationCommandOptionType . STRING ,
} ] ,
execute : opts = > {
const victim = findOption ( opts , "victim" ) as string ;
return { content : ` <@ ${ UserStore . getCurrentUser ( ) . id } > slaps ${ victim } around a bit with a large trout ` } ;
}
} ,
{
name : "freaky" ,
description : "it's freaky." ,
inputType : ApplicationCommandInputType.BUILT_IN ,
options : [ {
name : "message" ,
description : "yoooo freaky" ,
type : ApplicationCommandOptionType . STRING ,
required : true
} ] ,
execute : ( opts , ctx ) = > {
sendMessage ( ctx . channel . id , { content : makeFreaky ( findOption ( opts , "message" , "" ) ) } ) ;
}
} ,
{
inputType : ApplicationCommandInputType.BUILT_IN_TEXT ,
name : "morse" ,
description : "Translate to or from Morse code" ,
options : [
{
name : "text" ,
description : "Text to convert" ,
type : ApplicationCommandOptionType . STRING ,
required : true
}
] ,
execute : opts = > {
const input = opts . find ( o = > o . name === "text" ) ? . value as string ;
const output = isMorse ( input ) ? fromMorse ( input ) : toMorse ( input ) ;
return {
content : ` ${ output } `
} ;
} ,
} ,
{
name : "uwuify" ,
description : "uwuifies your messages" ,
options : [ RequiredMessageOption ] ,
execute : opts = > ( {
content : uwuify ( findOption ( opts , "message" , "" ) ) ,
} ) ,
} ,
2026-03-07 00:00:51 -05:00
{
name : "gifroulette" ,
description : "Tempt fate and send a gif" ,
2026-06-04 11:58:56 -04:00
execute : ( opts , other ) = > {
if ( GUILD_IDS . includes ( other ? . guild ? . id ? ? "" ) ) return sendBotMessage ( other . channel . id , {
content : "This command is restricted in this server."
} ) ;
return {
content : getFavoriteGif ( opts , other )
} ;
}
2026-03-07 00:00:51 -05:00
} ,
{
inputType : ApplicationCommandInputType.BUILT_IN ,
name : "friendcloud" ,
description : "Display user you most interact with in a cloud" ,
options : [
{
name : "count" ,
description : "Number of users to display" ,
type : ApplicationCommandOptionType . NUMBER ,
required : false
}
] ,
execute : async ( opts , cmdCtx ) = > {
const count = findOption ( opts , "count" , 25 ) ;
if ( ! count ) return sendBotMessage ( cmdCtx . channel . id , { content : "The count must be 1 or higher!" } ) ;
try {
const affinities = UserAffinitiesStore . getUserAffinities ( ) ;
if ( ! affinities ? . length ) {
return sendBotMessage ( cmdCtx . channel . id , {
content : "No affinities found. Check your [privacy settings](<https://support.discord.com/hc/en-us/articles/21864805694999-Data-Used-to-Improve-Discord>)."
} ) ;
}
const users = affinities
. map ( e = > ( {
member : UserStore.getUser ( e . otherUserId ) ,
affinity : calculateAffinityScore ( e )
} ) )
. filter ( x = > x . member ? . id )
. sort ( ( a , b ) = > b . affinity - a . affinity )
. slice ( 0 , count ) ;
if ( ! users . length ) {
return sendBotMessage ( cmdCtx . channel . id , {
content : "No valid users found in affinities. Check your [privacy settings](<https://support.discord.com/hc/en-us/articles/21864805694999-Data-Used-to-Improve-Discord>)."
} ) ;
}
const minAffinity = Math . min ( . . . users . map ( u = > u . affinity ) ) ;
const maxAffinity = Math . max ( . . . users . map ( u = > u . affinity ) ) ;
const minSize = 120 ;
const maxSize = 240 ;
const getSize = ( affinity : number ) : number = > {
if ( maxAffinity === minAffinity ) return ( minSize + maxSize ) / 2 ;
return minSize + ( ( affinity - minAffinity ) / ( maxAffinity - minAffinity ) ) * ( maxSize - minSize ) ;
} ;
const avgSize = ( minSize + maxSize ) / 2 ;
const { width : canvasWidth , height : canvasHeight } = calculateCanvasSize ( users . length , avgSize ) ;
const canvas = document . createElement ( "canvas" ) ;
canvas . width = canvasWidth ;
canvas . height = canvasHeight ;
const ctx = canvas . getContext ( "2d" ) ! ;
const positions : Array < { x : number , y : number , size : number ; } > = [ ] ;
const userPositions = users . map ( user = > {
const size = getSize ( user . affinity ) ;
const pos = generatePoissonDiskPosition ( positions , canvasWidth , canvasHeight , size ) ;
positions . push ( { x : pos.x , y : pos.y , size } ) ;
return { . . . user , x : pos.x , y : pos.y , size } ;
} ) ;
let loadedImages = 0 ;
const totalImages = userPositions . length ;
const drawImage = async user = > {
try {
const avatarUrl = user . member ? . avatar
? ` https://cdn.discordapp.com/avatars/ ${ user . member . id } / ${ user . member ? . avatar } .webp?size=256 `
: ` https://cdn.discordapp.com/embed/avatars/ ${ user . member . id as any as number % 5 } .png ` ;
const img = await loadFriendImage ( avatarUrl ) ;
const centerX = user . x + user . size / 2 ;
const centerY = user . y + user . size / 2 ;
ctx . save ( ) ;
ctx . beginPath ( ) ;
ctx . arc ( centerX , centerY , user . size / 2 , 0 , Math . PI * 2 ) ;
ctx . clip ( ) ;
ctx . drawImage ( img , user . x , user . y , user . size , user . size ) ;
ctx . restore ( ) ;
ctx . strokeStyle = "#808080" ;
ctx . lineWidth = 3 ;
ctx . beginPath ( ) ;
ctx . arc ( centerX , centerY , user . size / 2 + 1 , 0 , Math . PI * 2 ) ;
ctx . stroke ( ) ;
} catch {
// we ignore
} finally {
loadedImages ++ ;
if ( loadedImages === totalImages ) {
canvas . toBlob ( blob = > {
if ( ! blob ) {
sendBotMessage ( cmdCtx . channel . id , { content : "Couldn't generate the image :c" } ) ;
return ;
}
const file = new File ( [ blob ] , "affinities-cloud.png" , { type : "image/png" } ) ;
UploadHandler . promptToUpload ( [ file ] , cmdCtx . channel , DraftType . ChannelMessage ) ;
} , "image/png" ) ;
}
}
} ;
userPositions . forEach ( drawImage ) ;
} catch ( e : unknown ) {
if ( e instanceof Error ) sendBotMessage ( cmdCtx . channel . id , { content : e.message } ) ;
}
} ,
} ,
{
inputType : ApplicationCommandInputType.BUILT_IN ,
name : "imgtogif" ,
description : "Allows you to turn an image to a gif" ,
options : [
{
name : "image" ,
description : "Image attachment to use" ,
type : ApplicationCommandOptionType . ATTACHMENT
} ,
{
name : "width" ,
description : "Width of the gif" ,
type : ApplicationCommandOptionType . INTEGER
} ,
{
name : "height" ,
description : "Height of the gif" ,
type : ApplicationCommandOptionType . INTEGER
}
] ,
execute : async ( opts , cmdCtx ) = > {
try {
const { image , width , height } = await resolveImage ( opts , cmdCtx ) ;
if ( ! image ) throw "No Image specified!" ;
const avatar = await loadImage ( image ) ;
let gifWidth : number ;
let gifHeight : number ;
if ( width && height ) {
gifWidth = width ;
gifHeight = height ;
} else if ( width ) {
gifWidth = width ;
gifHeight = Math . round ( ( avatar . height / avatar . width ) * width ) ;
} else if ( height ) {
gifHeight = height ;
gifWidth = Math . round ( ( avatar . width / avatar . height ) * height ) ;
} else {
gifWidth = avatar . width ;
gifHeight = avatar . height ;
}
const gif = GIFEncoder ( ) ;
const canvas = document . createElement ( "canvas" ) ;
canvas . width = gifWidth ;
canvas . height = gifHeight ;
const ctx = canvas . getContext ( "2d" ) ! ;
UploadManager . clearAll ( cmdCtx . channel . id , DraftType . SlashCommand ) ;
for ( let i = 0 ; i < FRAMES ; i ++ ) {
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
ctx . drawImage ( avatar , 0 , 0 , avatar . width , avatar . height , 0 , 0 , canvas . width , canvas . height ) ;
const { data } = ctx . getImageData ( 0 , 0 , canvas . width , canvas . height ) ;
const palette = quantize ( data , 256 ) ;
const index = applyPalette ( data , palette ) ;
gif . writeFrame ( index , canvas . width , canvas . height , {
transparent : true ,
palette ,
} ) ;
}
gif . finish ( ) ;
const originalName = image . name ? image . name . replace ( /\.[^/.]+$/ , "" ) : "converted" ;
const file = new File ( [ new Uint8Array ( gif . bytesView ( ) ) ] , ` ${ originalName } .gif ` , { type : "image/gif" } ) ;
setTimeout ( ( ) = > UploadHandler . promptToUpload ( [ file ] , cmdCtx . channel , DraftType . ChannelMessage ) , 10 ) ;
} catch ( err ) {
UploadManager . clearAll ( cmdCtx . channel . id , DraftType . SlashCommand ) ;
sendBotMessage ( cmdCtx . channel . id , { content : String ( err ) } ) ;
}
} ,
} ,
{
name : "dissatisfaction" ,
description : " > ﹏ < " ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + " > ﹏ < " ,
} ) ,
} ,
{
name : "smug" ,
description : "ಠ_ಠ" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ಠ_ಠ" ,
} ) ,
} ,
{
name : "happy" ,
description : "ヽ(´▽`)/" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ヽ(´▽`)/" ,
} ) ,
} ,
{
name : "crying" ,
description : "ಥ_ಥ" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ಥ_ಥ" ,
} ) ,
} ,
{
name : "angry" ,
description : "ヽ(`Д´)ノ" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ヽ(`Д´)ノ" ,
} ) ,
} ,
{
name : "anger" ,
description : "ヽ(o `皿′o)ノ" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ヽ(o `皿′o)ノ" ,
} ) ,
} ,
{
name : "joy" ,
description : "<( ̄︶ ̄)>" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "<( ̄︶ ̄)>" ,
} ) ,
} ,
{
name : "blush" ,
description : "૮ ˶ᵔ ᵕ ᵔ˶ ა" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "૮ ˶ᵔ ᵕ ᵔ˶ ა" ,
} ) ,
} ,
{
name : "confused" ,
description : "(•ิ_•ิ)?" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(•ิ_•ิ)?" ,
} ) ,
} ,
{
name : "sleeping" ,
description : "(ᴗ_ᴗ)" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(ᴗ_ᴗ)" ,
} ) ,
} ,
{
name : "laughing" ,
description : "o(≧▽≦)o" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "o(≧▽≦)o" ,
} ) ,
} ,
/ *
even more kaomoji
* /
{
name : "giving" ,
description : "(ノ◕ヮ◕)ノ*:・゚✧" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(ノ◕ヮ◕)ノ*:・゚✧" ,
} ) ,
} ,
{
name : "peace" ,
description : "✌(◕‿-)✌" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "✌(◕‿-)✌" ,
} ) ,
} ,
{
name : "ending1" ,
description : "Ꮺ ָ࣪ ۰ ͙⊹" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "Ꮺ ָ࣪ ۰ ͙⊹" ,
} ) ,
} ,
{
name : "uwu" ,
description : "(>⩊<)" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(>⩊<)" ,
} ) ,
} ,
{
name : "comfy" ,
description : "(─‿‿─)♡" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(─‿‿─)♡" ,
} ) ,
} ,
{
name : "lovehappy" ,
description : "(*≧ω≦*)" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(*≧ω≦*)" ,
} ) ,
} ,
{
name : "loveee" ,
description : "(⁄ ⁄ >⁄ ▽ ⁄ <⁄ ⁄ )" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(⁄ ⁄ >⁄ ▽ ⁄ <⁄ ⁄ )" ,
} ) ,
} ,
{
name : "give" ,
description : "(ノ = ⩊ = )ノ " ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "(ノ = ⩊ = )ノ " ,
} ) ,
} ,
{
name : "lovegive" ,
description : "ღゝ◡╹)ノ♡" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "ღゝ◡╹)ノ♡" ,
} ) ,
} ,
{
name : "music" ,
description : "( ̄▽ ̄)/♫•¨•.¸¸♪" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "( ̄▽ ̄)/♫•¨•.¸¸♪" ,
} ) ,
} ,
{
name : "stars" ,
description : ".𖥔 ݁ ˖๋ ࣭ ⭑" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + ".𖥔 ݁ ˖๋ ࣭ ⭑" ,
} ) ,
} ,
{
name : "lovegiving" ,
description : "⸜(。˃ ᵕ ˂ )⸝♡" ,
options : [ OptionalMessageOption ] ,
execute : opts = > ( {
content : findOption ( opts , "message" , "" ) + " " + "⸜(。˃ ᵕ ˂ )⸝♡" ,
} ) ,
}
2025-09-10 06:04:17 -04:00
] ,
2026-03-07 00:00:51 -05:00
2025-09-10 06:04:17 -04:00
patches : [
{
find : ".isPureReactComponent=!0;" ,
2025-09-10 06:10:18 -04:00
predicate : ( ) = > settings . store . uwuEverything ,
2025-09-10 06:04:17 -04:00
replacement : {
2026-02-13 23:32:29 +01:00
match : /(\.defaultProps\).{0,80}return \i\(\i,\i,void 0,void 0,null,)(\i)\)/ ,
replace : "$1$self.uwuifyProps($2))"
2025-09-10 06:04:17 -04:00
}
}
] ,
uwuifyProps ( props : any ) {
if ( ! props . children ) return props ;
if ( typeof props . children === "string" ) props . children = uwuify ( props . children ) ;
else if ( Array . isArray ( props . children ) ) props . children = uwuifyArray ( props . children ) ;
return props ;
} ,
onSend ( msg : MessageObject ) {
// Only run when it's enabled
2025-09-10 06:10:18 -04:00
if ( settings . store . uwuEveryMessage ) {
2025-09-10 06:04:17 -04:00
msg . content = uwuify ( msg . content ) ;
}
} ,
start() {
this . preSend = addMessagePreSendListener ( ( _ , msg ) = > this . onSend ( msg ) ) ;
this . preEdit = addMessagePreEditListener ( ( _cid , _mid , msg ) = >
this . onSend ( msg )
) ;
} ,
stop() {
removeMessagePreSendListener ( this . preSend ) ;
removeMessagePreEditListener ( this . preEdit ) ;
} ,
2025-05-29 09:50:07 -04:00
} ) ;