2020-10-20 23:25:34 +02:00
/ * *
* @ name ChatFilter
2021-03-05 13:26:41 +01:00
* @ author DevilBro
2020-10-20 23:25:34 +02:00
* @ authorId 278543574059057154
2021-03-05 13:26:41 +01:00
* @ version 3.5 . 1
* @ description Allows you to censor Words or block complete Messages / Statuses
2020-10-20 23:25:34 +02:00
* @ invite Jx3TjNS
2020-11-19 16:45:36 +01:00
* @ donate https : //www.paypal.me/MircoWittrien
* @ patreon https : //www.patreon.com/MircoWittrien
* @ website https : //github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ChatFilter
* @ source https : //raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatFilter/ChatFilter.plugin.js
* @ updateUrl https : //raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatFilter/ChatFilter.plugin.js
2020-10-20 23:25:34 +02:00
* /
2018-10-11 10:21:26 +02:00
2020-09-19 20:49:33 +02:00
module . exports = ( _ => {
2020-10-09 21:09:35 +02:00
const config = {
2020-09-19 20:49:33 +02:00
"info" : {
"name" : "ChatFilter" ,
"author" : "DevilBro" ,
2021-03-03 11:20:00 +01:00
"version" : "3.5.1" ,
2021-03-04 11:49:32 +01:00
"description" : "Allows you to censor Words or block complete Messages/Statuses"
2021-03-03 11:20:00 +01:00
} ,
"changeLog" : {
"added" : {
"Ignore own Messages/Status" : "Added option to ignore your own Messages/Status"
} ,
"improved" : {
"Zero Width Spaces" : "Ignores any zero width space, since some ppl like to troll with it"
} ,
"fixed" : {
"Settings Update" : "Fixed issue where the settings panel wouldn't show new words without having to close it first"
}
2020-02-09 14:38:05 +01:00
}
2020-09-19 20:49:33 +02:00
} ;
2020-11-13 19:47:44 +01:00
2020-10-09 21:09:35 +02:00
return ! window . BDFDB _Global || ( ! window . BDFDB _Global . loaded && ! window . BDFDB _Global . started ) ? class {
2021-01-06 12:38:36 +01:00
getName ( ) { return config . info . name ; }
getAuthor ( ) { return config . info . author ; }
getVersion ( ) { return config . info . version ; }
2021-02-01 17:13:13 +01:00
getDescription ( ) { return ` The Library Plugin needed for ${ config . info . name } is missing. Open the Plugin Settings to download it. \n \n ${ config . info . description } ` ; }
downloadLibrary ( ) {
require ( "request" ) . get ( "https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js" , ( e , r , b ) => {
2021-03-05 13:14:18 +01:00
if ( ! e && b && r . statusCode == 200 ) require ( "fs" ) . writeFile ( require ( "path" ) . join ( BdApi . Plugins . folder , "0BDFDB.plugin.js" ) , b , _ => BdApi . showToast ( "Finished downloading BDFDB Library" , { type : "success" } ) ) ;
2021-02-01 17:13:13 +01:00
else BdApi . alert ( "Error" , "Could not download BDFDB Library Plugin, try again later or download it manually from GitHub: https://github.com/mwittrien/BetterDiscordAddons/tree/master/Library/" ) ;
} ) ;
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
load ( ) {
2020-11-19 16:51:14 +01:00
if ( ! window . BDFDB _Global || ! Array . isArray ( window . BDFDB _Global . pluginQueue ) ) window . BDFDB _Global = Object . assign ( { } , window . BDFDB _Global , { pluginQueue : [ ] } ) ;
2020-09-19 20:49:33 +02:00
if ( ! window . BDFDB _Global . downloadModal ) {
window . BDFDB _Global . downloadModal = true ;
2021-01-14 16:14:44 +01:00
BdApi . showConfirmationModal ( "Library Missing" , ` The Library Plugin needed for ${ config . info . name } is missing. Please click "Download Now" to install it. ` , {
2020-09-19 20:49:33 +02:00
confirmText : "Download Now" ,
cancelText : "Cancel" ,
onCancel : _ => { delete window . BDFDB _Global . downloadModal ; } ,
2020-09-20 08:15:13 +02:00
onConfirm : _ => {
delete window . BDFDB _Global . downloadModal ;
2021-02-01 17:13:13 +01:00
this . downloadLibrary ( ) ;
2020-09-20 08:15:13 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ;
}
if ( ! window . BDFDB _Global . pluginQueue . includes ( config . info . name ) ) window . BDFDB _Global . pluginQueue . push ( config . info . name ) ;
2020-10-09 21:09:35 +02:00
}
2021-01-06 12:38:36 +01:00
start ( ) { this . load ( ) ; }
stop ( ) { }
getSettingsPanel ( ) {
2020-11-28 23:12:09 +01:00
let template = document . createElement ( "template" ) ;
2021-01-14 16:14:44 +01:00
template . innerHTML = ` <div style="color: var(--header-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${ config . info . name } is missing. \n Please click <a style="font-weight: 500;">Download Now</a> to install it.</div> ` ;
2021-02-01 17:13:13 +01:00
template . content . firstElementChild . querySelector ( "a" ) . addEventListener ( "click" , this . downloadLibrary ) ;
2020-11-28 23:12:09 +01:00
return template . content . firstElementChild ;
}
2020-10-09 21:09:35 +02:00
} : ( ( [ Plugin , BDFDB ] ) => {
2020-09-19 20:49:33 +02:00
var oldBlockedMessages , oldCensoredMessages , words ;
var settings = { } , replaces = { } , configs = { } ;
2020-10-09 21:09:35 +02:00
return class ChatFilter extends Plugin {
2021-01-06 12:38:36 +01:00
onLoad ( ) {
2020-09-19 20:49:33 +02:00
this . defaults = {
configs : {
2021-01-20 15:31:30 +01:00
empty : { value : false , noBlocked : false , description : "Allow the Replacement Value to be empty (ignoring the default)" } ,
case : { value : false , noBlocked : false , description : "Handle the Word Value case sensitive" } ,
exact : { value : true , noBlocked : false , description : "Handle the Word Value as an exact Word and not as part of a Word" } ,
segment : { value : false , noBlocked : true , description : "Only replace the caught Segment of the Word with the Replacement" } ,
regex : { value : false , noBlocked : false , description : "Handle the Word Value as a RegExp String" }
2020-02-09 14:38:05 +01:00
} ,
2020-09-19 20:49:33 +02:00
replaces : {
2021-01-26 21:40:18 +01:00
blocked : { value : "~~BLOCKED~~" , description : "Default Replacement Value for blocked Messages: " } ,
censored : { value : "$!%&%!&" , description : "Default Replacement Value for censored Messages: " }
2020-02-09 14:38:05 +01:00
} ,
2020-09-19 20:49:33 +02:00
settings : {
2021-01-23 22:41:16 +01:00
addContextMenu : { value : true , description : "Add a Context Menu Entry to faster add new blocked/censored Words" } ,
targetMessages : { value : true , description : "Check Messages for blocked/censored Words" } ,
2021-02-13 11:34:31 +01:00
targetStatuses : { value : true , description : "Check Custom Statuses for blocked/censored Words" } ,
targetOwn : { value : true , description : "Filter/Block your own Messages/Custom Status" }
2020-09-19 20:49:33 +02:00
}
} ;
2020-02-09 14:38:05 +01:00
2020-09-19 20:49:33 +02:00
this . patchedModules = {
2021-01-14 17:40:45 +01:00
before : {
2021-03-03 11:20:00 +01:00
Message : "default" ,
2021-01-23 22:41:16 +01:00
MessageContent : "type" ,
UserPopout : "render" ,
UserProfile : "render" ,
UserInfo : "default" ,
MemberListItem : "render" ,
PrivateChannel : "render"
2021-01-14 17:40:45 +01:00
} ,
2020-09-19 20:49:33 +02:00
after : {
Messages : "type" ,
2021-01-13 18:54:21 +01:00
MessageContent : "type" ,
Embed : "render"
2020-09-19 20:49:33 +02:00
}
} ;
2021-01-14 17:40:45 +01:00
this . css = `
$ { BDFDB . dotCN . _chatfilterblocked } {
color : $ { BDFDB . DiscordConstants . Colors . STATUS _RED } ! important ;
}
$ { BDFDB . dotCN . messagerepliedmessagecontentclickable } : hover $ { BDFDB . dotCN . _chatfilterblocked } {
filter : saturate ( 2 ) ;
2020-09-19 20:49:33 +02:00
}
` ;
2020-02-09 14:38:05 +01:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStart ( ) {
2020-02-09 14:38:05 +01:00
words = BDFDB . DataUtils . load ( this , "words" ) ;
2020-08-29 15:57:35 +02:00
for ( let rType in this . defaults . replaces ) if ( ! BDFDB . ObjectUtils . is ( words [ rType ] ) ) words [ rType ] = { } ;
2020-02-09 14:38:05 +01:00
2020-06-08 20:07:08 +02:00
this . forceUpdateAll ( ) ;
2020-02-09 14:38:05 +01:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStop ( ) {
2020-06-08 20:07:08 +02:00
this . forceUpdateAll ( ) ;
2020-02-09 14:38:05 +01:00
}
2018-10-11 10:21:26 +02:00
2020-09-19 20:49:33 +02:00
getSettingsPanel ( collapseStates = { } ) {
2021-02-19 11:54:23 +01:00
let settingsPanel ;
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , {
2021-02-19 11:47:32 +01:00
collapseStates : collapseStates ,
2021-02-19 11:54:23 +01:00
children : _ => {
let settingsItems = [ ] ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Settings" ,
collapseStates : collapseStates ,
children : Object . keys ( settings ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
} ) ) . concat ( Object . keys ( replaces ) . map ( rType => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
type : "TextInput" ,
plugin : this ,
keys : [ "replaces" , rType ] ,
label : this . defaults . replaces [ rType ] . description ,
value : replaces [ rType ] ,
placeholder : this . defaults . replaces [ rType ] . value
} ) ) )
} ) ) ;
let values = { wordValue : "" , replaceValue : "" , choice : "blocked" } ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : ` Add new blocked/censored word ` ,
collapseStates : collapseStates ,
2020-09-19 20:49:33 +02:00
children : [
2021-02-19 11:54:23 +01:00
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
type : "Button" ,
label : "Pick a Word Value and Replacement Value" ,
disabled : ! Object . keys ( values ) . every ( valuename => values [ valuename ] ) ,
children : BDFDB . LanguageUtils . LanguageStrings . ADD ,
ref : instance => { if ( instance ) values . addButton = instance ; } ,
onClick : _ => {
this . saveWord ( values ) ;
BDFDB . PluginUtils . refreshSettingsPanel ( this , settingsPanel , collapseStates ) ;
2020-09-19 20:49:33 +02:00
}
} ) ,
2021-02-19 11:54:23 +01:00
this . createInputs ( values )
] . flat ( 10 ) . filter ( n => n )
} ) ) ;
for ( let rType in replaces ) if ( ! BDFDB . ObjectUtils . isEmpty ( words [ rType ] ) ) settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : ` Added ${ rType } Words ` ,
collapseStates : collapseStates ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsList , {
settings : Object . keys ( this . defaults . configs ) . filter ( n => ! this . defaults . configs [ n ] [ "no" + BDFDB . LibraryModules . StringUtils . upperCaseFirstChar ( rType ) ] ) ,
data : Object . keys ( words [ rType ] ) . map ( wordValue => Object . assign ( { } , words [ rType ] [ wordValue ] , {
key : wordValue ,
label : wordValue
} ) ) ,
renderLabel : data => BDFDB . ReactUtils . createElement ( "div" , {
style : { width : "100%" } ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextInput , {
value : data . label ,
placeholder : data . label ,
size : BDFDB . LibraryComponents . TextInput . Sizes . MINI ,
maxLength : 100000000000000000000 ,
onChange : value => {
words [ rType ] [ value ] = words [ rType ] [ data . label ] ;
delete words [ rType ] [ data . label ] ;
data . label = value ;
BDFDB . DataUtils . save ( words , this , "words" ) ;
}
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextInput , {
value : data . replace ,
placeholder : data . replace ,
size : BDFDB . LibraryComponents . TextInput . Sizes . MINI ,
maxLength : 100000000000000000000 ,
onChange : value => {
words [ rType ] [ data . label ] . replace = value ;
BDFDB . DataUtils . save ( words , this , "words" ) ;
}
} )
]
} ) ,
onCheckboxChange : ( value , instance ) => {
words [ rType ] [ instance . props . cardId ] [ instance . props . settingId ] = value ;
BDFDB . DataUtils . save ( words , this , "words" ) ;
} ,
onRemove : ( e , instance ) => {
delete words [ rType ] [ instance . props . cardId ] ;
BDFDB . DataUtils . save ( words , this , "words" ) ;
BDFDB . PluginUtils . refreshSettingsPanel ( this , settingsPanel , collapseStates ) ;
}
} )
} ) ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Remove All" ,
collapseStates : collapseStates ,
children : Object . keys ( replaces ) . map ( rType => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
type : "Button" ,
color : BDFDB . LibraryComponents . Button . Colors . RED ,
label : ` Remove all ${ rType } Words ` ,
onClick : _ => {
BDFDB . ModalUtils . confirm ( this , ` Are you sure you want to remove all ${ rType } Words? ` , _ => {
words [ rType ] = { } ;
BDFDB . DataUtils . remove ( this , "words" , rType ) ;
BDFDB . PluginUtils . refreshSettingsPanel ( this , settingsPanel , collapseStates ) ;
} ) ;
} ,
children : BDFDB . LanguageUtils . LanguageStrings . REMOVE
} ) )
} ) ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Config Guide" ,
collapseStates : collapseStates ,
children : [
"Case: Will block/censor Words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe" ,
"Not Case: Will block/censor Words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe" ,
"Exact: Will block/censor Words that are exactly the selected Word. apple => apple, not applepie or pineapple" ,
"Not Exact: Will block/censor all Words containing the selected Word. apple => apple, applepie and pineapple" ,
"Segment: Will only replace the caught segment in the censored Word. apple with peach => applepie => peachpie" ,
"Not Segment: Will replae the whole censored Word. apple with peach => applepie => peach" ,
"Empty: Ignores the default/choosen Replacement Value and removes the Word/Message instead." ,
[
"Regex: Will treat the entered Word Value as a Regular Expression. " ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Anchor , { href : "https://regexr.com/" , children : BDFDB . LanguageUtils . LanguageStrings . HELP + "?" } )
] ,
] . map ( string => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormText , {
type : BDFDB . LibraryComponents . FormComponents . FormTextTypes . DESCRIPTION ,
children : string
} ) )
} ) ) ;
return settingsItems ;
}
} ) ;
2020-09-19 20:49:33 +02:00
}
2019-10-22 11:37:23 +02:00
2021-01-06 12:38:36 +01:00
onSettingsClosed ( ) {
2020-09-19 20:49:33 +02:00
if ( this . SettingsUpdated ) {
delete this . SettingsUpdated ;
this . forceUpdateAll ( ) ;
}
}
2021-01-06 12:38:36 +01:00
forceUpdateAll ( ) {
2020-09-19 20:49:33 +02:00
settings = BDFDB . DataUtils . get ( this , "settings" ) ;
replaces = BDFDB . DataUtils . get ( this , "replaces" ) ;
configs = BDFDB . DataUtils . get ( this , "configs" ) ;
oldBlockedMessages = { } ;
oldCensoredMessages = { } ;
2020-02-09 14:38:05 +01:00
2020-09-19 20:49:33 +02:00
BDFDB . PatchUtils . forceAllUpdates ( this ) ;
BDFDB . MessageUtils . rerenderAll ( ) ;
2020-02-09 14:38:05 +01:00
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
onNativeContextMenu ( e ) {
if ( e . instance . props . value && e . instance . props . value . trim ( ) ) {
if ( ( e . instance . props . type == "NATIVE_TEXT" || e . instance . props . type == "CHANNEL_TEXT_AREA" ) && settings . addContextMenu ) this . injectItem ( e , e . instance . props . value . trim ( ) ) ;
}
2020-02-09 14:38:05 +01:00
}
2019-12-10 13:59:44 +01:00
2020-09-19 20:49:33 +02:00
onSlateContextMenu ( e ) {
let text = document . getSelection ( ) . toString ( ) . trim ( ) ;
if ( text && settings . addContextMenu ) this . injectItem ( e , text ) ;
}
2019-02-06 16:21:07 +01:00
2020-09-19 20:49:33 +02:00
onMessageContextMenu ( e ) {
let text = document . getSelection ( ) . toString ( ) . trim ( ) ;
if ( text && settings . addContextMenu ) this . injectItem ( e , text ) ;
}
injectItem ( e , text ) {
let [ children , index ] = BDFDB . ContextMenuUtils . findItem ( e . returnvalue , { id : "devmode-copy-id" , group : true } ) ;
children . splice ( index > - 1 ? index : children . length , 0 , BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuGroup , {
children : BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
2020-12-22 20:55:39 +01:00
label : BDFDB . LanguageUtils . LibraryStringsFormat ( "add_to" , "ChatFilter" ) ,
2020-09-19 20:49:33 +02:00
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "add-filter" ) ,
action : _ => {
this . openAddModal ( text . replace ( /\n/g , "\\n" ) . replace ( /\r/g , "\\r" ) . replace ( /\t/g , "\\t" ) ) ;
}
} )
} ) ) ;
}
2019-02-06 16:21:07 +01:00
2020-09-19 20:49:33 +02:00
processMessages ( e ) {
2021-01-23 22:41:16 +01:00
if ( settings . targetMessages ) {
e . returnvalue . props . children . props . channelStream = [ ] . concat ( e . returnvalue . props . children . props . channelStream ) ;
for ( let i in e . returnvalue . props . children . props . channelStream ) {
let message = e . returnvalue . props . children . props . channelStream [ i ] . content ;
if ( message ) {
if ( BDFDB . ArrayUtils . is ( message . attachments ) ) this . checkMessage ( e . returnvalue . props . children . props . channelStream [ i ] , message ) ;
else if ( BDFDB . ArrayUtils . is ( message ) ) for ( let j in message ) {
let childMessage = message [ j ] . content ;
if ( childMessage && BDFDB . ArrayUtils . is ( childMessage . attachments ) ) this . checkMessage ( message [ j ] , childMessage ) ;
}
2020-09-19 20:49:33 +02:00
}
2020-07-02 11:43:05 +02:00
}
2020-01-17 13:12:34 +01:00
}
2020-07-02 11:43:05 +02:00
}
2020-09-19 20:49:33 +02:00
checkMessage ( stream , message ) {
2021-01-13 18:54:21 +01:00
let { blocked , censored , content , embeds } = this . parseMessage ( message ) ;
let changeMessage = ( change , cache ) => {
if ( change ) {
if ( ! cache [ message . id ] ) cache [ message . id ] = new BDFDB . DiscordObjects . Message ( message ) ;
stream . content . content = content ;
stream . content . embeds = embeds ;
}
else if ( cache [ message . id ] && Object . keys ( message ) . some ( key => ! BDFDB . equals ( cache [ message . id ] [ key ] , message [ key ] ) ) ) {
stream . content . content = cache [ message . id ] . content ;
stream . content . embeds = cache [ message . id ] . embeds ;
delete cache [ message . id ] ;
}
} ;
changeMessage ( blocked , oldBlockedMessages ) ;
changeMessage ( censored , oldCensoredMessages ) ;
2020-02-09 14:38:05 +01:00
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
processMessage ( e ) {
2021-01-23 22:41:16 +01:00
if ( settings . targetMessages ) {
let repliedMessage = e . instance . props . childrenRepliedMessage ;
if ( repliedMessage && repliedMessage . props && repliedMessage . props . children && repliedMessage . props . children . props && repliedMessage . props . children . props . referencedMessage && repliedMessage . props . children . props . referencedMessage . message && ( oldBlockedMessages [ repliedMessage . props . children . props . referencedMessage . message . id ] || oldCensoredMessages [ repliedMessage . props . children . props . referencedMessage . message . id ] ) ) {
let { blocked , censored , content , embeds } = this . parseMessage ( repliedMessage . props . children . props . referencedMessage . message ) ;
repliedMessage . props . children . props . referencedMessage . message = new BDFDB . DiscordObjects . Message ( Object . assign ( { } , repliedMessage . props . children . props . referencedMessage . message , { content , embeds } ) ) ;
}
2020-09-19 20:49:33 +02:00
}
2020-02-09 14:38:05 +01:00
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
processMessageContent ( e ) {
2021-01-23 22:41:16 +01:00
if ( e . instance . props . message && settings . targetMessages ) {
2021-01-14 17:40:45 +01:00
if ( ! e . returnvalue ) {
if ( oldBlockedMessages [ e . instance . props . message . id ] ) e . instance . props . className = BDFDB . DOMUtils . formatClassName ( e . instance . props . className , BDFDB . disCN . _chatfilterblocked ) ;
if ( oldCensoredMessages [ e . instance . props . message . id ] && e . instance . props . message . content != oldCensoredMessages [ e . instance . props . message . id ] . content ) e . instance . props . className = BDFDB . DOMUtils . formatClassName ( e . instance . props . className , BDFDB . disCN . _chatfiltercensored ) ;
}
else {
if ( oldBlockedMessages [ e . instance . props . message . id ] ) e . returnvalue . props . children . push ( this . createStamp ( oldBlockedMessages [ e . instance . props . message . id ] . content , "blocked" ) ) ;
if ( oldCensoredMessages [ e . instance . props . message . id ] ) e . returnvalue . props . children . push ( this . createStamp ( oldCensoredMessages [ e . instance . props . message . id ] . content , "censored" ) ) ;
}
2021-01-13 18:54:21 +01:00
}
}
processEmbed ( e ) {
if ( e . instance . props . embed && e . instance . props . embed . censored && oldCensoredMessages [ e . instance . props . embed . message _id ] ) {
let [ children , index ] = BDFDB . ReactUtils . findParent ( e . returnvalue , { props : [ [ "className" , BDFDB . disCN . embeddescription ] ] } ) ;
2021-01-23 22:41:16 +01:00
if ( index > - 1 ) children [ index ] . props . children = [
children [ index ] . props . children ,
this . createStamp ( oldCensoredMessages [ e . instance . props . embed . message _id ] . embeds [ e . instance . props . embed . index ] . rawDescription , "censored" )
] . flat ( 10 ) . filter ( n => n ) ;
}
}
processUserPopout ( e ) {
this . checkStatus ( e ) ;
}
processUserProfile ( e ) {
this . checkStatus ( e ) ;
}
processUserInfo ( e ) {
this . checkActivities ( e ) ;
}
processMemberListItem ( e ) {
this . checkActivities ( e ) ;
}
processPrivateChannel ( e ) {
this . checkActivities ( e ) ;
}
checkStatus ( e ) {
2021-02-13 11:34:31 +01:00
if ( settings . targetStatuses && e . instance . props . customStatusActivity && e . instance . props . user ) {
let { content } = this . parseMessage ( { content : e . instance . props . customStatusActivity . state , embeds : [ ] , id : "status" , author : e . instance . props . user } ) ;
2021-01-23 22:41:16 +01:00
if ( content ) e . instance . props . customStatusActivity = Object . assign ( { } , e . instance . props . customStatusActivity , { state : content } ) ;
else if ( ! e . instance . props . customStatusActivity . emoji ) delete e . instance . props . customStatusActivity ;
}
}
checkActivities ( e ) {
2021-02-13 11:34:31 +01:00
if ( settings . targetStatuses && e . instance . props . activities && e . instance . props . activities . length && e . instance . props . user ) {
2021-01-23 22:41:16 +01:00
let index = e . instance . props . activities . findIndex ( n => n && n . type == BDFDB . DiscordConstants . ActivityTypes . CUSTOM _STATUS ) ;
if ( index > - 1 && e . instance . props . activities [ index ] . state ) {
2021-02-13 11:34:31 +01:00
let { content } = this . parseMessage ( { content : e . instance . props . activities [ index ] . state , embeds : [ ] , id : "status" , author : e . instance . props . user } ) ;
2021-01-23 22:41:16 +01:00
if ( content ) e . instance . props . activities [ index ] = Object . assign ( { } , e . instance . props . activities [ index ] , { state : content } ) ;
else if ( ! e . instance . props . activities [ index ] . emoji ) {
e . instance . props . activities = [ ] . concat ( e . instance . props . activities ) ;
e . instance . props . activities . splice ( index , 1 ) ;
}
}
2020-09-19 20:49:33 +02:00
}
}
createStamp ( tooltipText , label ) {
return BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : tooltipText ,
tooltipConfig : { style : "max-width: 400px" } ,
children : BDFDB . ReactUtils . createElement ( "time" , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . messageedited , BDFDB . disCN [ ` _chatfilter ${ label } stamp ` ] ) ,
children : ` ( ${ label } ) `
} )
} ) ;
2020-02-09 14:38:05 +01:00
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
parseMessage ( message ) {
2021-01-13 18:54:21 +01:00
let blocked = false , censored = false ;
let content = ( oldBlockedMessages [ message . id ] || oldCensoredMessages [ message . id ] || { } ) . content || message . content ;
let embeds = [ ] . concat ( ( oldBlockedMessages [ message . id ] || oldCensoredMessages [ message . id ] || { } ) . embeds || message . embeds ) ;
let isContent = content && typeof content == "string" ;
2021-02-13 11:34:31 +01:00
if ( ( isContent || embeds . length ) && ( message . author . id != BDFDB . UserUtils . me . id || settings . targetOwn ) ) {
2020-09-19 20:49:33 +02:00
let blockedReplace ;
for ( let bWord in words . blocked ) {
2021-01-13 18:54:21 +01:00
let compareContent = [ isContent && content , embeds . map ( e => e . rawDescription ) ] . flat ( 10 ) . filter ( n => n ) . join ( " " ) ;
2020-09-19 20:49:33 +02:00
blockedReplace = words . blocked [ bWord ] . empty ? "" : ( words . blocked [ bWord ] . replace || replaces . blocked ) ;
let reg = this . createReg ( bWord , words . blocked [ bWord ] ) ;
if ( words . blocked [ bWord ] . regex || bWord . indexOf ( " " ) > - 1 ) {
2021-01-13 18:54:21 +01:00
if ( isContent && this . testWord ( compareContent , reg ) ) blocked = true ;
2020-08-29 15:57:35 +02:00
}
2021-01-13 18:54:21 +01:00
else for ( let word of compareContent . replace ( /([\n\t\r])/g , " $1 " ) . split ( " " ) ) {
2020-09-19 20:49:33 +02:00
if ( this . testWord ( word , reg ) ) {
blocked = true ;
break ;
2020-08-29 15:57:35 +02:00
}
}
2020-09-19 20:49:33 +02:00
if ( blocked ) break ;
}
2021-01-13 18:54:21 +01:00
if ( blocked ) return { blocked , censored , content : blockedReplace , embeds : [ ] } ;
2020-09-19 20:49:33 +02:00
else {
2021-01-13 18:54:21 +01:00
let checkCensor = string => {
let singleCensored = false ;
string = string . replace ( /([\n\t\r])/g , " $1 " ) ;
for ( let cWord in words . censored ) {
let censoredReplace = words . censored [ cWord ] . empty ? "" : ( words . censored [ cWord ] . replace || replaces . censored ) ;
let reg = this . createReg ( cWord , words . censored [ cWord ] ) ;
let newString = [ ] ;
2021-01-20 15:31:30 +01:00
if ( words . censored [ cWord ] . segment || words . censored [ cWord ] . regex || cWord . indexOf ( " " ) > - 1 ) {
2021-01-13 18:54:21 +01:00
if ( this . testWord ( string , reg ) ) {
singleCensored = true ;
censored = true ;
newString = [ string . replace ( reg , censoredReplace ) ] ;
}
else newString = [ string ] ;
2020-09-19 20:49:33 +02:00
}
2021-01-13 18:54:21 +01:00
else for ( let word of string . split ( " " ) ) {
if ( this . testWord ( word , reg ) ) {
singleCensored = true ;
censored = true ;
newString . push ( censoredReplace ) ;
}
else newString . push ( word ) ;
2020-09-19 20:49:33 +02:00
}
2021-01-13 18:54:21 +01:00
string = newString . join ( " " ) ;
2020-09-19 20:49:33 +02:00
}
2021-01-13 18:54:21 +01:00
return { parsedContent : string . replace ( / ([\n\t\r]) /g , "$1" ) , singleCensored : singleCensored } ;
} ;
if ( isContent ) {
let { parsedContent , singleCensored } = checkCensor ( content ) ;
if ( singleCensored ) content = parsedContent ;
}
for ( let i in embeds ) if ( embeds [ i ] . rawDescription ) {
let { parsedContent , singleCensored } = checkCensor ( embeds [ i ] . rawDescription ) ;
if ( singleCensored ) embeds [ i ] = Object . assign ( { } , embeds [ i ] , { rawDescription : parsedContent , index : i , message _id : message . id , censored : true } ) ;
2020-08-29 15:57:35 +02:00
}
2018-10-11 10:21:26 +02:00
}
}
2021-01-13 18:54:21 +01:00
return { blocked , censored , content , embeds } ;
2018-10-11 10:21:26 +02:00
}
2020-09-19 20:49:33 +02:00
testWord ( word , reg ) {
let nativeEmoji = BDFDB . LibraryModules . EmojiUtils . translateSurrogatesToInlineEmoji ( word ) ;
if ( nativeEmoji != word ) return this . regTest ( nativeEmoji , reg ) ;
else {
let customEmoji = ( /<a{0,1}(:.*:)[0-9]{7,}>/i . exec ( word ) || [ ] ) [ 1 ] ;
if ( customEmoji ) return this . regTest ( customEmoji , reg ) ;
else return this . regTest ( word , reg ) ;
}
}
regTest ( word , reg ) {
2021-02-19 11:54:23 +01:00
let wordWithoutSpecial = word . replace ( /[\?\¿\!\¡\.\"\*\-\_\~\u180E\u200B-\u200D\u2060\uFEFF]/g , "" ) ;
2020-09-19 20:49:33 +02:00
return word && reg . test ( word ) || wordWithoutSpecial && reg . test ( wordWithoutSpecial ) ;
2020-02-13 11:25:13 +01:00
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
createReg ( word , config ) {
let escapedWord = config . regex ? word : BDFDB . StringUtils . regEscape ( word ) ;
return new RegExp ( BDFDB . StringUtils . htmlEscape ( config . exact ? "^" + escapedWord + "$" : escapedWord ) , ` ${ config . case ? "" : "i" } ${ config . exact ? "" : "g" } ` ) ;
}
2019-01-26 22:45:19 +01:00
2021-01-26 21:40:18 +01:00
openAddModal ( wordValue ) {
let values = { wordValue , replaceValue : "" , choice : "blocked" } ;
2021-01-29 20:57:25 +01:00
let configs = BDFDB . ObjectUtils . map ( this . defaults . configs , n => n . value ) ;
2020-09-19 20:49:33 +02:00
BDFDB . ModalUtils . open ( this , {
size : "MEDIUM" ,
2020-12-22 20:55:39 +01:00
header : BDFDB . LanguageUtils . LibraryStringsFormat ( "add_to" , "ChatFilter" ) ,
2021-01-23 18:50:24 +01:00
subHeader : "" ,
2020-09-19 20:49:33 +02:00
children : [
this . createInputs ( values ) ,
2021-01-29 20:57:25 +01:00
Object . keys ( configs ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
2020-09-19 20:49:33 +02:00
type : "Switch" ,
label : this . defaults . configs [ key ] . description ,
2021-01-29 20:57:25 +01:00
value : configs [ key ] ,
onChange : value => { configs [ key ] = value ; }
2020-09-19 20:49:33 +02:00
} ) )
] . flat ( 10 ) . filter ( n => n ) ,
buttons : [ {
2021-01-26 21:40:18 +01:00
disabled : ! values . wordValue ,
2020-09-19 20:49:33 +02:00
contents : BDFDB . LanguageUtils . LanguageStrings . ADD ,
color : "BRAND" ,
close : true ,
2021-01-29 20:57:25 +01:00
ref : instance => { if ( instance ) values . addButton = instance ; } ,
onClick : _ => {
this . saveWord ( values , configs ) ;
2021-01-13 18:54:21 +01:00
this . forceUpdateAll ( ) ;
2020-07-02 10:42:56 +02:00
}
2020-09-19 20:49:33 +02:00
} ]
} ) ;
}
createInputs ( values ) {
2021-01-29 20:57:25 +01:00
let wordValueInput ;
2020-09-19 20:49:33 +02:00
return [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormItem , {
2020-11-19 16:45:36 +01:00
title : "Block/Censor:" ,
2021-01-13 18:54:21 +01:00
className : BDFDB . disCN . marginbottom8 ,
2020-09-19 20:49:33 +02:00
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextInput , {
2021-01-26 21:40:18 +01:00
value : values . wordValue ,
placeholder : values . wordValue ,
errorMessage : ! values . wordValue && "Choose a Word Value" || words [ values . choice ] [ values . wordValue ] && ` Word Value already used, saving will overwrite old ${ values . choice } Word ` ,
2021-01-29 20:57:25 +01:00
ref : instance => { if ( instance ) wordValueInput = instance ; } ,
2020-09-19 20:49:33 +02:00
onChange : ( value , instance ) => {
2021-01-26 21:40:18 +01:00
values . wordValue = value . trim ( ) ;
if ( ! values . wordValue ) instance . props . errorMessage = "Choose a Word Value" ;
else if ( words [ values . choice ] [ values . wordValue ] ) instance . props . errorMessage = ` Word Value already used, saving will overwrite old ${ values . choice } word ` ;
2020-09-19 20:49:33 +02:00
else delete instance . props . errorMessage ;
2021-01-29 20:57:25 +01:00
values . addButton . props . disabled = ! values . wordValue ;
BDFDB . ReactUtils . forceUpdate ( values . addButton ) ;
2020-09-19 20:49:33 +02:00
}
} )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormItem , {
2020-11-19 16:45:36 +01:00
title : "With:" ,
2021-01-13 18:54:21 +01:00
className : BDFDB . disCN . marginbottom8 ,
2020-09-19 20:49:33 +02:00
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextInput , {
2021-01-26 21:40:18 +01:00
value : values . replaceValue ,
placeholder : values . replaceValue ,
2020-09-19 20:49:33 +02:00
autoFocus : true ,
2021-01-29 20:57:25 +01:00
onChange : value => { values . replaceValue = value ; }
2020-09-19 20:49:33 +02:00
} )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . RadioGroup , {
className : BDFDB . disCN . marginbottom8 ,
value : values . choice ,
2020-11-19 16:51:14 +01:00
options : [ { value : "blocked" , name : "Block" } , { value : "censored" , name : "Censor" } ] ,
2021-01-29 20:57:25 +01:00
onChange : valueObj => {
values . choice = valueObj . value ;
if ( ! values . wordValue ) wordValueInput . props . errorMessage = "Choose a Word Value" ;
else if ( words [ values . choice ] [ values . wordValue ] ) wordValueInput . props . errorMessage = ` Word Value already used, saving will overwrite old ${ values . choice } Word ` ;
else delete wordValueInput . props . errorMessage ;
BDFDB . ReactUtils . forceUpdate ( wordValueInput ) ;
2020-07-02 10:42:56 +02:00
}
} )
2020-09-19 20:49:33 +02:00
] ;
}
2020-07-26 17:02:25 +02:00
2020-09-19 20:49:33 +02:00
saveWord ( values , wordConfigs = configs ) {
2021-01-26 21:40:18 +01:00
if ( ! values . wordValue || ! values . choice ) return ;
2020-09-19 20:49:33 +02:00
if ( ! BDFDB . ObjectUtils . is ( words [ values . choice ] ) ) words [ values . choice ] = { } ;
2021-01-26 21:40:18 +01:00
words [ values . choice ] [ values . wordValue ] = {
replace : values . replaceValue ,
2020-09-19 20:49:33 +02:00
empty : wordConfigs . empty ,
case : wordConfigs . case ,
2021-01-26 21:40:18 +01:00
exact : values . wordValue . indexOf ( " " ) > - 1 ? false : wordConfigs . exact ,
2020-09-19 20:49:33 +02:00
regex : false
} ;
BDFDB . DataUtils . save ( words , this , "words" ) ;
}
} ;
2020-10-09 21:09:35 +02:00
} ) ( window . BDFDB _Global . PluginUtils . buildPlugin ( config ) ) ;
2020-09-19 20:49:33 +02:00
} ) ( ) ;