2020-03-31 14:19:25 +02:00
//META{"name":"InAppNotifications","source":"https://github.com/1Lighty/BetterDiscordPlugins/blob/master/Plugins/InAppNotifications/InAppNotifications.plugin.js","website":"https://1lighty.github.io/BetterDiscordStuff/?plugin=InAppNotifications","authorId":"239513071272329217","invite":"NYvWdN5","donate":"https://paypal.me/lighty13"}*//
2020-03-02 18:03:21 +01:00
/ * @ c c _ o n
@ if ( @ _jscript )
2020-10-08 20:37:28 +02:00
// Offer to self-install for clueless users that try to run this directly.
var shell = WScript . CreateObject ( 'WScript.Shell' ) ;
var fs = new ActiveXObject ( 'Scripting.FileSystemObject' ) ;
var pathPlugins = shell . ExpandEnvironmentStrings ( '%APPDATA%\\BetterDiscord\\plugins' ) ;
var pathSelf = WScript . ScriptFullName ;
// Put the user at ease by addressing them in the first person
shell . Popup ( 'It looks like you\'ve mistakenly tried to run me directly. \n(Don\'t do that!)' , 0 , 'I\'m a plugin for BetterDiscord' , 0x30 ) ;
if ( fs . GetParentFolderName ( pathSelf ) === fs . GetAbsolutePathName ( pathPlugins ) ) {
shell . Popup ( 'I\'m in the correct folder already.\nJust go to settings, plugins and enable me.' , 0 , 'I\'m already installed' , 0x40 ) ;
} else if ( ! fs . FolderExists ( pathPlugins ) ) {
shell . Popup ( 'I can\'t find the BetterDiscord plugins folder.\nAre you sure it\'s even installed?' , 0 , 'Can\'t install myself' , 0x10 ) ;
} else if ( shell . Popup ( 'Should I copy myself to BetterDiscord\'s plugins folder for you?' , 0 , 'Do you need some help?' , 0x34 ) === 6 ) {
fs . CopyFile ( pathSelf , fs . BuildPath ( pathPlugins , fs . GetFileName ( pathSelf ) ) , true ) ;
// Show the user where to put plugins in the future
shell . Exec ( 'explorer ' + pathPlugins ) ;
shell . Popup ( 'I\'m installed!\nJust go to settings, plugins and enable me!' , 0 , 'Successfully installed' , 0x40 ) ;
}
WScript . Quit ( ) ;
2020-03-02 18:03:21 +01:00
@ else @ * /
/ *
* Copyright © 2019 - 2020 , _Lighty _
* All rights reserved .
* Code may not be redistributed , modified or otherwise taken without explicit permission .
* /
2020-07-26 13:39:27 +02:00
module . exports = ( ( ) => {
2020-03-02 18:03:21 +01:00
/* Setup */
const config = {
main : 'index.js' ,
info : {
name : 'InAppNotifications' ,
authors : [
{
name : 'Lighty' ,
discord _id : '239513071272329217' ,
github _username : 'LightyPon' ,
twitter _username : ''
}
] ,
2020-11-04 22:44:34 +01:00
version : '1.0.9' ,
2020-03-02 18:03:21 +01:00
description : 'Show a notification in Discord when someone sends a message, just like on mobile.' ,
github : 'https://github.com/1Lighty' ,
github _raw : 'https://raw.githubusercontent.com/1Lighty/BetterDiscordPlugins/master/Plugins/InAppNotifications/InAppNotifications.plugin.js'
} ,
defaultConfig : [
{
name : 'Ignore DND mode' ,
id : 'dndIgnore' ,
type : 'switch' ,
value : true
2020-03-16 15:40:36 +01:00
} ,
{
name : 'Bar color' ,
id : 'color' ,
type : 'color' ,
value : '#4a90e2' ,
options : {
defaultColor : '#4a90e2'
}
} ,
{
name : 'Set bar color to top role color' ,
id : 'roleColor' ,
type : 'switch' ,
value : true
} ,
{
name : 'Calculate timeout by number of words' ,
note : 'Long text will stay for longer' ,
id : 'wpmTimeout' ,
type : 'switch' ,
value : true
} ,
{
name : 'Words per minute' ,
id : 'wordsPerMinute' ,
type : 'slider' ,
value : 300 ,
2020-04-11 11:50:00 +02:00
min : 50 ,
2020-03-16 15:40:36 +01:00
max : 900 ,
2020-04-11 11:50:00 +02:00
markers : Array . from ( Array ( 18 ) , ( _ , i ) => ( i + 1 ) * 50 ) ,
2020-03-16 15:40:36 +01:00
stickToMarkers : true
2020-03-31 14:19:25 +02:00
} ,
{
type : 'note'
2020-03-02 18:03:21 +01:00
}
] ,
changelog : [
{
2020-03-16 15:40:36 +01:00
title : 'Fixed' ,
type : 'fixed' ,
2020-11-04 22:44:34 +01:00
items : [ 'Fixed plugin not working from the great canary update plugin massacre.' ]
2020-03-05 16:16:16 +01:00
}
2020-03-02 18:03:21 +01:00
]
} ;
/* Build */
const buildPlugin = ( [ Plugin , Api ] ) => {
const { ContextMenu , EmulatedTooltip , Toasts , Settings , Popouts , Modals , Utilities , WebpackModules , Filters , DiscordModules , ColorConverter , DOMTools , DiscordClasses , DiscordSelectors , ReactTools , ReactComponents , DiscordAPI , Logger , Patcher , PluginUpdater , PluginUtilities , DiscordClassModules , Structs } = Api ;
2020-11-04 22:44:34 +01:00
const { React , ModalStack , ContextMenuActions , ContextMenuItem , ContextMenuItemsGroup , ReactDOM , GuildStore , UserStore , DiscordConstants , Dispatcher , GuildMemberStore , GuildActions , SwitchRow , EmojiUtils , RadioGroup , Permissions , FlexChild , PopoutOpener , Textbox , RelationshipStore , WindowInfo , UserSettingsStore , NavigationUtils , UserNameResolver , SelectedChannelStore } = DiscordModules ;
const ChannelStore = WebpackModules . getByProps ( 'getChannel' , 'getDMFromUserId' ) ;
2020-03-02 18:03:21 +01:00
const LurkerStore = WebpackModules . getByProps ( 'isLurking' ) ;
const MuteStore = WebpackModules . getByProps ( 'allowNoMessages' ) ;
const isMentionedUtils = WebpackModules . getByProps ( 'isRawMessageMentioned' ) ;
2020-10-07 01:04:05 +02:00
const ParserModule = WebpackModules . getByProps ( 'astParserFor' , 'parse' ) ;
2020-03-02 18:03:21 +01:00
const MessageClasses = WebpackModules . getByProps ( 'username' , 'messageContent' ) ;
const MarkupClassname = XenoLib . getClass ( 'markup' ) ;
2020-03-05 16:16:16 +01:00
const Messages = ( WebpackModules . getByProps ( 'Messages' ) || { } ) . Messages ;
const SysMessageUtils = WebpackModules . getByProps ( 'getSystemMessageUserJoin' , 'stringify' ) ;
const MessageParseUtils = ( WebpackModules . getByProps ( 'parseAndRebuild' , 'default' ) || { } ) . default ;
2020-03-14 19:40:24 +01:00
const CUser = WebpackModules . getByPrototypes ( 'getAvatarSource' , 'isLocalBot' ) ;
2020-04-11 11:50:00 +02:00
const TextElement = WebpackModules . getByDisplayName ( 'Text' ) ;
2020-03-02 18:03:21 +01:00
2020-03-31 14:19:25 +02:00
class ExtraText extends Settings . SettingField {
constructor ( name , note ) {
2020-04-11 11:50:00 +02:00
super ( name , note , null , TextElement , {
2020-03-31 14:19:25 +02:00
children : 'To change the position or backdrop background color of the notifications, check XenoLib settings.'
} ) ;
}
}
2020-11-04 22:44:34 +01:00
const currentChannel = _ => {
const channel = ChannelStore . getChannel ( SelectedChannelStore . getChannelId ( ) ) ;
return channel ? Structs . Channel . from ( channel ) : null ;
}
2020-03-02 18:03:21 +01:00
return class InAppNotifications extends Plugin {
constructor ( ) {
super ( ) ;
XenoLib . changeName ( _ _filename , 'InAppNotifications' ) ;
const oOnStart = this . onStart . bind ( this ) ;
this . onStart = ( ) => {
try {
oOnStart ( ) ;
} catch ( e ) {
Logger . stacktrace ( 'Failed to start!' , e ) ;
PluginUpdater . checkForUpdate ( this . name , this . version , this . _config . info . github _raw ) ;
XenoLib . Notifications . error ( ` [** ${ this . name } **] Failed to start! Please update it, press CTRL + R, or ${ GuildStore . getGuild ( XenoLib . supportServerId ) ? 'go to <#639665366380838924>' : '[join my support server](https://discord.gg/NYvWdN5)' } for further assistance. ` , { timeout : 0 } ) ;
try {
this . onStop ( ) ;
2020-10-08 20:37:28 +02:00
} catch ( e ) { }
2020-03-02 18:03:21 +01:00
}
} ;
const oMESSAGE _CREATE = this . MESSAGE _CREATE . bind ( this ) ;
this . MESSAGE _CREATE = e => {
try {
oMESSAGE _CREATE ( e ) ;
} catch ( e ) {
this . errorCount ++ ;
if ( this . errorCount >= 10 ) {
2020-03-15 12:50:57 +01:00
Logger . stacktrace ( 'Error in MESSAGE_CREATE dispatch handler' , e ) ;
2020-03-02 18:03:21 +01:00
PluginUpdater . checkForUpdate ( this . name , this . version , this . _config . info . github _raw ) ;
XenoLib . Notifications . error ( ` [** ${ this . name } **] Plugin is throwing errors and is in a broken state, please update it or ${ GuildStore . getGuild ( XenoLib . supportServerId ) ? 'go to <#639665366380838924>' : '[join my support server](https://discord.gg/NYvWdN5)' } for further assistance. ` , { timeout : 0 } ) ;
try {
this . onStop ( ) ;
2020-10-08 20:37:28 +02:00
} catch ( e ) { }
2020-03-02 18:03:21 +01:00
}
}
} ;
2020-03-15 12:50:57 +01:00
try {
2020-07-17 15:39:31 +02:00
WebpackModules . getByProps ( 'openModal' , 'hasModalOpen' ) . closeModal ( ` ${ this . name } _DEP_MODAL ` ) ;
2020-10-08 20:37:28 +02:00
} catch ( e ) { }
2020-03-02 18:03:21 +01:00
}
onStart ( ) {
2020-03-16 15:40:36 +01:00
try {
/* do not, under any circumstances, let this kill the plugin */
2020-10-08 20:37:28 +02:00
const CUSTOM _RULES = XenoLib . _ . cloneDeep ( WebpackModules . getByProps ( 'RULES' ) . RULES ) ;
2020-03-16 15:40:36 +01:00
for ( let rule of Object . keys ( CUSTOM _RULES ) ) CUSTOM _RULES [ rule ] . raw = null ;
2020-03-31 14:19:25 +02:00
for ( let rule of [ 'paragraph' , 'text' , 'codeBlock' , 'emoji' , 'inlineCode' ] ) CUSTOM _RULES [ rule ] . raw = e => e . content ;
2020-03-16 15:40:36 +01:00
for ( let rule of [ 'autolink' , 'br' , 'link' , 'newline' , 'url' ] ) delete CUSTOM _RULES [ rule ] ;
2020-03-31 14:19:25 +02:00
for ( let rule of [ 'blockQuote' , 'channel' , 'em' , 'mention' , 'roleMention' , 's' , 'spoiler' , 'strong' , 'u' ] ) CUSTOM _RULES [ rule ] . raw = ( e , t , n ) => t ( e . content , n ) ;
2020-03-16 15:40:36 +01:00
CUSTOM _RULES . customEmoji . raw = e => e . name ;
const astTools = WebpackModules . getByProps ( 'flattenAst' ) ;
const SimpleMarkdown = WebpackModules . getByProps ( 'parserFor' , 'outputFor' ) ;
const parser = SimpleMarkdown . parserFor ( CUSTOM _RULES ) ;
const render = SimpleMarkdown . htmlFor ( SimpleMarkdown . ruleOutput ( CUSTOM _RULES , 'raw' ) ) ;
this . _timeUnparser = ( e = '' , r = true , a = { } ) => render ( astTools . constrainAst ( astTools . flattenAst ( parser ( e , Object . assign ( { inline : r } , a ) ) ) ) ) ;
} catch ( err ) {
Logger . stacktrace ( 'Failed to create custom unparser' , err ) ;
this . _timeUnparser = null ;
}
2020-03-02 18:03:21 +01:00
this . errorCount = 0 ;
Dispatcher . subscribe ( 'MESSAGE_CREATE' , this . MESSAGE _CREATE ) ;
2020-11-04 22:44:34 +01:00
const o = Error . captureStackTrace ;
const ol = Error . stackTraceLimit ;
Error . stackTraceLimit = 0 ;
try {
const check1 = a => a [ 0 ] === 'L' && a [ 3 ] === 'h' && a [ 7 ] === 'r' ;
const check2 = a => a . length === 13 && a [ 0 ] === 'B' && a [ 7 ] === 'i' && a [ 12 ] === 'd' ;
const mod = WebpackModules . find ( e => Object . keys ( e ) . findIndex ( check1 ) !== - 1 ) || { } ;
( Utilities . getNestedProp ( mod , ` ${ Object . keys ( mod ) . find ( check1 ) } . ${ Object . keys ( Utilities . getNestedProp ( mod , Object . keys ( window ) . find ( check1 ) || '' ) || { } ).find(check2)}.Utils.removeDa ` ) || DiscordConstants . NOOP ) ( { } )
} finally {
Error . stackTraceLimit = ol ;
Error . captureStackTrace = o ;
}
2020-03-14 19:40:24 +01:00
this . patchAll ( ) ;
2020-03-02 18:03:21 +01:00
PluginUtilities . addStyle (
this . short + '-CSS' ,
`
. IAN - message {
padding - left : 40 px ;
position : relative ;
min - height : 36 px ;
pointer - events : none ;
}
. IAN - message . IAN - avatar {
left : - 2 px ;
pointer - events : none ;
width : 32 px ;
height : 32 px ;
top : 0 ;
position : absolute ;
border - radius : 50 % ;
}
. IAN - message . $ { MessageClasses . username . split ( ' ' ) [ 0 ] } {
font - size : 0.9 rem ;
line - height : unset ;
}
. IAN - message . $ { MarkupClassname . split ( ' ' ) [ 0 ] } {
line - height : unset ;
}
2020-03-16 15:40:36 +01:00
. IAN - message . $ { MarkupClassname . split ( ' ' ) [ 0 ] } {
max - height : calc ( 100 vh - 150 px ) ;
}
2020-03-02 18:03:21 +01:00
. IAN - message . $ { MarkupClassname . split ( ' ' ) [ 0 ] } , . IAN - message . $ { MessageClasses . username . split ( ' ' ) [ 0 ] } {
overflow : hidden
}
`
) ;
}
onStop ( ) {
Dispatcher . unsubscribe ( 'MESSAGE_CREATE' , this . MESSAGE _CREATE ) ;
2020-03-14 19:40:24 +01:00
Patcher . unpatchAll ( ) ;
2020-03-02 18:03:21 +01:00
PluginUtilities . removeStyle ( this . short + '-CSS' ) ;
}
/* zlib uses reference to defaultSettings instead of a cloned object, which sets settings as default settings, messing everything up */
loadSettings ( defaultSettings ) {
return PluginUtilities . loadSettings ( this . name , Utilities . deepclone ( this . defaultSettings ? this . defaultSettings : defaultSettings ) ) ;
}
2020-03-05 16:16:16 +01:00
2020-03-16 15:40:36 +01:00
buildSetting ( data ) {
if ( data . type === 'color' ) {
const setting = new XenoLib . Settings . ColorPicker ( data . name , data . note , data . value , data . onChange , data . options ) ;
if ( data . id ) setting . id = data . id ;
return setting ;
2020-03-31 14:19:25 +02:00
} else if ( data . type === 'note' ) {
return new ExtraText ( '' , '' ) ;
2020-03-16 15:40:36 +01:00
}
return super . buildSetting ( data ) ;
}
2020-03-02 18:03:21 +01:00
_shouldNotify ( iAuthor , iChannel ) {
if ( iChannel . isManaged ( ) ) return false ;
const guildId = iChannel . getGuildId ( ) ;
if ( guildId && LurkerStore . isLurking ( guildId ) ) return false ;
if ( iAuthor . id === DiscordAPI . currentUser . id || RelationshipStore . isBlocked ( iAuthor . id ) ) return false ;
if ( ! this . settings . dndIgnore && UserSettingsStore . status === DiscordConstants . StatusTypes . DND ) return false ;
if ( MuteStore . allowNoMessages ( iChannel ) ) return false ;
return true ;
}
shouldNotify ( message , iChannel , iAuthor ) {
if ( ! DiscordAPI . currentUser || ! iChannel || ! iAuthor ) return false ;
2020-03-05 16:16:16 +01:00
/* dunno what the func name is as this is copied from discord, so I named it _shouldNotify */
2020-03-02 18:03:21 +01:00
if ( ! this . _shouldNotify ( iAuthor , iChannel ) ) return false ;
2020-11-04 22:44:34 +01:00
if ( currentChannel ( ) && currentChannel ( ) . id === iChannel . id ) return false ;
2020-03-05 16:16:16 +01:00
/* channel has notif settings set to all messages */
2020-03-02 18:03:21 +01:00
if ( MuteStore . allowAllMessages ( iChannel ) ) return true ;
const everyoneSuppressed = MuteStore . isSuppressEveryoneEnabled ( iChannel . guild _id ) ;
const rolesSuppressed = MuteStore . isSuppressRolesEnabled ( iChannel . guild _id ) ;
2020-03-05 16:16:16 +01:00
/* only if mentioned, but only if settings allow */
2020-03-02 18:03:21 +01:00
return isMentionedUtils . isRawMessageMentioned ( message , DiscordAPI . currentUser . id , everyoneSuppressed , rolesSuppressed ) ;
}
2020-03-05 16:16:16 +01:00
getChannelName ( iChannel , iAuthor ) {
switch ( iChannel . type ) {
case DiscordConstants . ChannelTypes . GROUP _DM :
if ( '' !== iChannel . name ) return iChannel . name ;
const recipients = iChannel . recipients . map ( e => ( e === iAuthor . id ? iAuthor : UserStore . getUser ( e ) ) ) . filter ( e => e ) ;
return recipients . length > 0 ? recipients . map ( e => e . username ) . join ( ', ' ) : Messages . UNNAMED ;
case DiscordConstants . ChannelTypes . GUILD _ANNOUNCEMENT :
case DiscordConstants . ChannelTypes . GUILD _TEXT :
return '#' + iChannel . name ;
default :
return iChannel . name ;
}
}
getActivity ( e , t , n , r ) {
switch ( e . type ) {
case DiscordConstants . ChannelTypes . GUILD _ANNOUNCEMENT :
case DiscordConstants . ChannelTypes . GUILD _TEXT :
return t ;
case DiscordConstants . ChannelTypes . GROUP _DM :
return n ;
case DiscordConstants . ChannelTypes . DM :
default :
return r ;
}
}
makeTextChatNotification ( iChannel , message , iAuthor ) {
let author = UserNameResolver . getName ( iChannel . guild _id , iChannel . id , iAuthor ) ;
let channel = author ;
switch ( iChannel . type ) {
case DiscordConstants . ChannelTypes . GUILD _ANNOUNCEMENT :
case DiscordConstants . ChannelTypes . GUILD _TEXT :
const iGuild = GuildStore . getGuild ( iChannel . guild _id ) ;
if ( message . type === DiscordConstants . MessageTypes . DEFAULT || iGuild ) channel += ` ( ${ this . getChannelName ( iChannel ) } , ${ iGuild . name } ) ` ;
break ;
case DiscordConstants . ChannelTypes . GROUP _DM :
const newChannel = this . getChannelName ( iChannel , iAuthor ) ;
if ( ! iChannel . isManaged ( ) || ! iAuthor . bot || channel !== newChannel ) channel += ` ( ${ newChannel } ) ` ;
}
let d = message . content ;
if ( message . activity && message . application ) {
const targetMessage = message . activity . type === DiscordConstants . ActivityActionTypes . JOIN ? this . getActivity ( iChannel , Messages . NOTIFICATION _MESSAGE _CREATE _GUILD _ACTIVITY _JOIN , Messages . NOTIFICATION _MESSAGE _CREATE _GROUP _DM _ACTIVITY _JOIN , Messages . NOTIFICATION _MESSAGE _CREATE _DM _ACTIVITY _JOIN ) : this . getActivity ( iChannel , Messages . NOTIFICATION _MESSAGE _CREATE _GUILD _ACTIVITY _SPECTATE , Messages . NOTIFICATION _MESSAGE _CREATE _GROUP _DM _ACTIVITY _SPECTATE , Messages . NOTIFICATION _MESSAGE _CREATE _DM _ACTIVITY _SPECTATE ) ;
d = targetMessage . format ( { user : author , game : message . application . name } ) ;
} else if ( message . activity && message . activity . type === DiscordConstants . ActivityActionTypes . LISTEN ) {
const targetMessage = this . getActivity ( iChannel , Messages . NOTIFICATION _MESSAGE _CREATE _GUILD _ACTIVITY _LISTEN , Messages . NOTIFICATION _MESSAGE _CREATE _GROUP _DM _ACTIVITY _LISTEN , Messages . NOTIFICATION _MESSAGE _CREATE _DM _ACTIVITY _LISTEN ) ;
d = targetMessage . format ( { user : author } ) ;
} else if ( message . type !== DiscordConstants . MessageTypes . DEFAULT ) {
const content = SysMessageUtils . stringify ( message ) ;
if ( ! content ) return null ;
d = MessageParseUtils . unparse ( content , iChannel . id , true ) ;
}
if ( ! d . length && message . attachments . length ) d = Messages . NOTIFICATION _BODY _ATTACHMENT . format ( { filename : message . attachments [ 0 ] . filename } ) ;
if ( ! d . length && message . embeds . length ) {
const embed = message . embeds [ 0 ] ;
if ( embed . description ) d = embed . title ? embed . title + ': ' + embed . description : embed . description ;
else if ( embed . title ) d = embed . title ;
else if ( embed . fields ) {
const field = embed . fields [ 0 ] ;
d = field . name + ': ' + field . value ;
}
}
return {
icon : iAuthor . getAvatarURL ( ) ,
title : channel ,
content : d
} ;
}
2020-03-02 18:03:21 +01:00
MESSAGE _CREATE ( { channelId , message } ) {
const iChannel = ChannelStore . getChannel ( channelId ) ;
2020-03-14 19:40:24 +01:00
let iAuthor = UserStore . getUser ( message . author . id ) ;
if ( ! iAuthor ) {
iAuthor = new CUser ( message . author ) ;
UserStore . getUsers ( ) [ message . author . id ] = iAuthor ;
}
2020-03-02 18:03:21 +01:00
if ( ! iChannel || ! iAuthor ) return ;
if ( ! this . shouldNotify ( message , iChannel , iAuthor ) ) return ;
2020-03-05 16:16:16 +01:00
const notif = this . makeTextChatNotification ( iChannel , message , iAuthor ) ;
if ( ! notif ) return ; /* wah */
2020-03-16 15:40:36 +01:00
const member = GuildMemberStore . getMember ( iChannel . guild _id , iAuthor . id ) ;
this . showNotification ( notif , iChannel , this . settings . roleColor && member && member . colorString ) ;
2020-03-02 18:03:21 +01:00
}
2020-03-16 15:40:36 +01:00
calculateTime ( text ) {
let words = 0 ;
if ( this . _timeUnparser ) {
try {
text = this . _timeUnparser ( text ) ;
} catch ( err ) {
Logger . stacktrace ( ` Failed to unparse text ${ text } ` , err ) ;
this . _timeUnparser = null ;
}
}
/* https://github.com/ngryman/reading-time */
function ansiWordBound ( c ) {
return ' ' === c || '\n' === c || '\r' === c || '\t' === c ;
}
2020-10-08 20:37:28 +02:00
for ( var i = 0 ; i < text . length ; ) {
2020-03-16 15:40:36 +01:00
for ( ; i < text . length && ! ansiWordBound ( text [ i ] ) ; i ++ ) ;
words ++ ;
for ( ; i < text . length && ansiWordBound ( text [ i ] ) ; i ++ ) ;
}
return ( words / this . settings . wordsPerMinute ) * 60 * 1000 ;
}
showNotification ( notif , iChannel , color ) {
const timeout = this . settings . wpmTimeout ? Math . min ( this . calculateTime ( notif . title ) + this . calculateTime ( notif . content ) , 60000 ) : 0 ;
const notificationId = XenoLib . Notifications . show (
2020-03-02 18:03:21 +01:00
React . createElement (
'div' ,
{
className : 'IAN-message'
} ,
React . createElement ( 'img' , {
className : 'IAN-avatar' ,
src : notif . icon
} ) ,
React . createElement (
'span' ,
{
className : MessageClasses . username
} ,
notif . title
) ,
2020-03-05 16:16:16 +01:00
React . createElement ( 'div' , { className : XenoLib . joinClassNames ( MarkupClassname , MessageClasses . messageContent ) } , ParserModule . parse ( notif . content , true , { channelId : iChannel . id } ) )
2020-03-02 18:03:21 +01:00
) ,
{
2020-03-16 15:40:36 +01:00
timeout : Math . max ( 5000 , timeout ) ,
2020-03-02 18:03:21 +01:00
onClick : ( ) => {
NavigationUtils . transitionTo ( ` /channels/ ${ iChannel . guild _id || '@me' } / ${ iChannel . id } ` ) ;
XenoLib . Notifications . remove ( notificationId ) ;
2020-03-16 15:40:36 +01:00
} ,
color : color || this . settings . color
2020-03-02 18:03:21 +01:00
}
) ;
}
2020-03-14 19:40:24 +01:00
/* PATCHES */
patchAll ( ) {
Utilities . suppressErrors ( this . patchShouldNotify . bind ( this ) , 'shouldNotify patch' ) ( ) ;
}
patchShouldNotify ( ) {
2020-03-16 15:40:36 +01:00
Patcher . after ( WebpackModules . getByProps ( 'shouldDisplayNotifications' ) , 'shouldDisplayNotifications' , ( ) => ( WindowInfo . isFocused ( ) ? false : undefined ) ) ;
2020-03-14 19:40:24 +01:00
}
/* PATCHES */
2020-03-02 18:03:21 +01:00
showChangelog ( footer ) {
XenoLib . showChangelog ( ` ${ this . name } has been updated! ` , this . version , this . _config . changelog ) ;
}
getSettingsPanel ( ) {
return this . buildSettingsPanel ( ) . getElement ( ) ;
}
get [ Symbol . toStringTag ] ( ) {
return 'Plugin' ;
}
get name ( ) {
return config . info . name ;
}
get short ( ) {
let string = '' ;
for ( let i = 0 , len = config . info . name . length ; i < len ; i ++ ) {
const char = config . info . name [ i ] ;
if ( char === char . toUpperCase ( ) ) string += char ;
}
return string ;
}
get author ( ) {
return config . info . authors . map ( author => author . name ) . join ( ', ' ) ;
}
get version ( ) {
return config . info . version ;
}
get description ( ) {
return config . info . description ;
}
} ;
} ;
/* Finalize */
let ZeresPluginLibraryOutdated = false ;
let XenoLibOutdated = false ;
try {
if ( global . BdApi && 'function' == typeof BdApi . getPlugin ) {
const i = ( i , n ) => ( ( i = i . split ( '.' ) . map ( i => parseInt ( i ) ) ) , ( n = n . split ( '.' ) . map ( i => parseInt ( i ) ) ) , ! ! ( n [ 0 ] > i [ 0 ] ) || ! ! ( n [ 0 ] == i [ 0 ] && n [ 1 ] > i [ 1 ] ) || ! ! ( n [ 0 ] == i [ 0 ] && n [ 1 ] == i [ 1 ] && n [ 2 ] > i [ 2 ] ) ) ,
n = ( n , e ) => n && n . _config && n . _config . info && n . _config . info . version && i ( n . _config . info . version , e ) ,
e = BdApi . getPlugin ( 'ZeresPluginLibrary' ) ,
2020-03-31 14:19:25 +02:00
o = BdApi . getPlugin ( 'XenoLib' ) ;
2020-10-05 21:05:14 +02:00
n ( e , '1.2.23' ) && ( ZeresPluginLibraryOutdated = ! 0 ) , n ( o , '1.3.26' ) && ( XenoLibOutdated = ! 0 ) ;
2020-03-02 18:03:21 +01:00
}
} catch ( i ) {
console . error ( 'Error checking if libraries are out of date' , i ) ;
}
return ! global . ZeresPluginLibrary || ! global . XenoLib || ZeresPluginLibraryOutdated || XenoLibOutdated
? class {
2020-10-08 20:37:28 +02:00
constructor ( ) {
this . _XL _PLUGIN = true ;
this . start = this . load = this . handleMissingLib ;
}
getName ( ) {
return this . name . replace ( /\s+/g , '' ) ;
}
getAuthor ( ) {
return this . author ;
}
getVersion ( ) {
return this . version ;
}
getDescription ( ) {
return this . description + ' You are missing libraries for this plugin, please enable the plugin and click Download Now.' ;
}
start ( ) { }
stop ( ) { }
handleMissingLib ( ) {
const a = BdApi . findModuleByProps ( 'openModal' , 'hasModalOpen' ) ;
if ( a && a . hasModalOpen ( ` ${ this . name } _DEP_MODAL ` ) ) return ;
const b = ! global . XenoLib ,
c = ! global . ZeresPluginLibrary ,
d = ( b && c ) || ( ( b || c ) && ( XenoLibOutdated || ZeresPluginLibraryOutdated ) ) ,
e = ( ( ) => {
let a = '' ;
return b || c ? ( a += ` Missing ${ XenoLibOutdated || ZeresPluginLibraryOutdated ? ' and outdated' : '' } ` ) : ( XenoLibOutdated || ZeresPluginLibraryOutdated ) && ( a += ` Outdated ` ) , ( a += ` ${ d ? 'Libraries' : 'Library' } ` ) , a ;
} ) ( ) ,
f = ( ( ) => {
let a = ` The ${ d ? 'libraries' : 'library' } ` ;
return b || XenoLibOutdated ? ( ( a += 'XenoLib ' ) , ( c || ZeresPluginLibraryOutdated ) && ( a += 'and ZeresPluginLibrary ' ) ) : ( c || ZeresPluginLibraryOutdated ) && ( a += 'ZeresPluginLibrary ' ) , ( a += ` required for ${ this . name } ${ d ? 'are' : 'is' } ${ b || c ? 'missing' : '' } ${ XenoLibOutdated || ZeresPluginLibraryOutdated ? ( b || c ? ' and/or outdated' : 'outdated' ) : '' } . ` ) , a ;
} ) ( ) ,
g = BdApi . findModuleByDisplayName ( 'Text' ) ,
h = BdApi . findModuleByDisplayName ( 'ConfirmModal' ) ,
i = ( ) => BdApi . alert ( e , BdApi . React . createElement ( 'span' , { } , BdApi . React . createElement ( 'div' , { } , f ) , ` Due to a slight mishap however, you'll have to download the libraries yourself. This is not intentional, something went wrong, errors are in console. ` , c || ZeresPluginLibraryOutdated ? BdApi . React . createElement ( 'div' , { } , BdApi . React . createElement ( 'a' , { href : 'https://betterdiscord.net/ghdl?id=2252' , target : '_blank' } , 'Click here to download ZeresPluginLibrary' ) ) : null , b || XenoLibOutdated ? BdApi . React . createElement ( 'div' , { } , BdApi . React . createElement ( 'a' , { href : 'https://betterdiscord.net/ghdl?id=3169' , target : '_blank' } , 'Click here to download XenoLib' ) ) : null ) ) ;
if ( ! a || ! h || ! g ) return console . error ( ` Missing components: ${ ( a ? '' : ' ModalStack' ) + ( h ? '' : ' ConfirmationModalComponent' ) + ( g ? '' : 'TextElement' ) } ` ) , i ( ) ;
class j extends BdApi . React . PureComponent {
constructor ( a ) {
super ( a ) , ( this . state = { hasError : ! 1 } ) , ( this . componentDidCatch = a => ( console . error ( ` Error in ${ this . props . label } , screenshot or copy paste the error above to Lighty for help. ` ) , this . setState ( { hasError : ! 0 } ) , 'function' == typeof this . props . onError && this . props . onError ( a ) ) ) , ( this . render = ( ) => ( this . state . hasError ? null : this . props . children ) ) ;
2020-03-15 12:50:57 +01:00
}
2020-10-08 20:37:28 +02:00
}
let k = ! 1 ,
l = ! 1 ;
const m = a . openModal (
b => {
if ( l ) return null ;
try {
return BdApi . React . createElement (
j ,
{ label : 'missing dependency modal' , onError : ( ) => ( a . closeModal ( m ) , i ( ) ) } ,
BdApi . React . createElement (
h ,
Object . assign (
{
header : e ,
children : BdApi . React . createElement ( g , { size : g . Sizes . SIZE _16 , children : [ ` ${ f } Please click Download Now to download ${ d ? 'them' : 'it' } . ` ] } ) ,
red : ! 1 ,
confirmText : 'Download Now' ,
cancelText : 'Cancel' ,
onCancel : b . onClose ,
onConfirm : ( ) => {
if ( k ) return ;
k = ! 0 ;
const b = require ( 'request' ) ,
c = require ( 'fs' ) ,
d = require ( 'path' ) ,
e = BdApi . Plugins && BdApi . Plugins . folder ? BdApi . Plugins . folder : window . ContentManager . pluginsFolder ,
f = ( ) => {
( global . XenoLib && ! XenoLibOutdated ) ||
b ( 'https://raw.githubusercontent.com/1Lighty/BetterDiscordPlugins/master/Plugins/1XenoLib.plugin.js' , ( b , f , g ) => {
2020-07-17 15:39:31 +02:00
try {
2020-10-08 20:37:28 +02:00
if ( b || 200 !== f . statusCode ) return a . closeModal ( m ) , i ( ) ;
c . writeFile ( d . join ( e , '1XenoLib.plugin.js' ) , g , ( ) => { } ) ;
2020-07-17 15:39:31 +02:00
} catch ( b ) {
2020-10-08 20:37:28 +02:00
console . error ( 'Fatal error downloading XenoLib' , b ) , a . closeModal ( m ) , i ( ) ;
2020-07-17 15:39:31 +02:00
}
2020-10-08 20:37:28 +02:00
} ) ;
} ;
! global . ZeresPluginLibrary || ZeresPluginLibraryOutdated
? b ( 'https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js' , ( b , g , h ) => {
try {
if ( b || 200 !== g . statusCode ) return a . closeModal ( m ) , i ( ) ;
c . writeFile ( d . join ( e , '0PluginLibrary.plugin.js' ) , h , ( ) => { } ) , f ( ) ;
} catch ( b ) {
console . error ( 'Fatal error downloading ZeresPluginLibrary' , b ) , a . closeModal ( m ) , i ( ) ;
}
} )
: f ( ) ;
}
} ,
b ,
{ onClose : ( ) => { } }
2020-03-15 12:50:57 +01:00
)
2020-10-08 20:37:28 +02:00
)
) ;
} catch ( b ) {
return console . error ( 'There has been an error constructing the modal' , b ) , ( l = ! 0 ) , a . closeModal ( m ) , i ( ) , null ;
}
} ,
{ modalKey : ` ${ this . name } _DEP_MODAL ` }
) ;
}
get [ Symbol . toStringTag ] ( ) {
return 'Plugin' ;
}
get name ( ) {
return config . info . name ;
}
get short ( ) {
let string = '' ;
for ( let i = 0 , len = config . info . name . length ; i < len ; i ++ ) {
const char = config . info . name [ i ] ;
if ( char === char . toUpperCase ( ) ) string += char ;
2020-03-02 18:03:21 +01:00
}
2020-10-08 20:37:28 +02:00
return string ;
}
get author ( ) {
return config . info . authors . map ( author => author . name ) . join ( ', ' ) ;
}
get version ( ) {
return config . info . version ;
}
get description ( ) {
return config . info . description ;
2020-03-02 18:03:21 +01:00
}
2020-10-08 20:37:28 +02:00
}
2020-03-02 18:03:21 +01:00
: buildPlugin ( global . ZeresPluginLibrary . buildPlugin ( config ) ) ;
} ) ( ) ;
/*@end@*/