2019-09-20 22:32:52 +02:00
//META{"name":"ReverseImageSearch","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ReverseImageSearch","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ReverseImageSearch/ReverseImageSearch.plugin.js"}*//
2018-10-11 10:21:26 +02:00
class ReverseImageSearch {
2019-01-17 23:48:29 +01:00
getName ( ) { return "ReverseImageSearch" ; }
2019-10-06 16:41:40 +02:00
getVersion ( ) { return "3.4.6" ; }
2019-01-26 22:45:19 +01:00
2019-01-17 23:48:29 +01:00
getAuthor ( ) { return "DevilBro" ; }
getDescription ( ) { return "Adds a reverse image search option to the context menu." ; }
2019-01-26 22:45:19 +01:00
2019-09-04 12:34:02 +02:00
constructor ( ) {
2019-02-18 09:27:40 +01:00
this . changelog = {
2019-10-06 17:07:31 +02:00
"added" : [ [ "New Options" , "Right clicking a user avatar/server icon/custom emoji now also adds a context menu entry to reverse image search the image, can be disabled" ] ]
2019-02-18 09:27:40 +01:00
} ;
2019-09-04 12:34:02 +02:00
}
initConstructor ( ) {
2018-10-11 10:21:26 +02:00
this . imgUrlReplaceString = "DEVILBRO_BD_REVERSEIMAGESEARCH_REPLACE_IMAGEURL" ;
2019-01-26 22:45:19 +01:00
2018-10-11 10:21:26 +02:00
this . defaults = {
2019-10-05 17:46:38 +02:00
settings : {
2019-10-06 16:41:40 +02:00
addUserAvatarEntry : { value : true , description : "User Avatars" } ,
addGuildIconEntry : { value : true , description : "Server Icons" } ,
addEmojiEntry : { value : true , description : "Custom Emojis/Emotes" }
2019-10-05 17:46:38 +02:00
} ,
2018-10-11 10:21:26 +02:00
engines : {
2019-10-19 11:41:39 +02:00
_all : { value : true , name : BDFDB . LanguageUtils . LanguageStrings . FORM _LABEL _ALL , url : null } ,
2018-10-11 10:21:26 +02:00
Baidu : { value : true , name : "Baidu" , url : "http://image.baidu.com/pcdutu?queryImageUrl=" + this . imgUrlReplaceString } ,
Bing : { value : true , name : "Bing" , url : "https://www.bing.com/images/search?q=imgurl:" + this . imgUrlReplaceString + "&view=detailv2&iss=sbi&FORM=IRSBIQ" } ,
Google : { value : true , name : "Google" , url : "https://images.google.com/searchbyimage?image_url=" + this . imgUrlReplaceString } ,
IQDB : { value : true , name : "IQDB" , url : "https://iqdb.org/?url=" + this . imgUrlReplaceString } ,
Reddit : { value : true , name : "Reddit" , url : "http://karmadecay.com/search?q=" + this . imgUrlReplaceString } ,
SauceNAO : { value : true , name : "SauceNAO" , url : "https://saucenao.com/search.php?db=999&url=" + this . imgUrlReplaceString } ,
Sogou : { value : true , name : "Sogou" , url : "http://pic.sogou.com/ris?flag=1&drag=0&query=" + this . imgUrlReplaceString + "&flag=1" } ,
TinEye : { value : true , name : "TinEye" , url : "https://tineye.com/search?url=" + this . imgUrlReplaceString } ,
2018-11-02 22:39:42 +01:00
WhatAnime : { value : true , name : "WhatAnime" , url : "https://trace.moe/?url=" + this . imgUrlReplaceString } ,
2018-10-11 10:21:26 +02:00
Yandex : { value : true , name : "Yandex" , url : "https://yandex.com/images/search?url=" + this . imgUrlReplaceString + "&rpt=imageview" }
}
} ;
}
getSettingsPanel ( ) {
2019-01-22 11:28:32 +01:00
if ( ! global . BDFDB || typeof BDFDB != "object" || ! BDFDB . loaded || ! this . started ) return ;
2019-10-22 19:49:57 +02:00
let settings = BDFDB . DataUtils . get ( this , "settings" ) ;
let engines = BDFDB . DataUtils . get ( this , "engines" ) ;
2019-10-09 14:18:28 +02:00
let settingshtml = ` <div class=" ${ this . name } -settings BDFDB-settings"><div class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . titlesize18 + BDFDB . disCNS . height24 + BDFDB . disCNS . weightnormal + BDFDB . disCN . marginbottom8 } "> ${ this . name } </div><div class="BDFDB-settings-inner"> ` ;
settingshtml += ` <div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom8 } " style="flex: 1 1 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . marginreset + BDFDB . disCNS . weightmedium + BDFDB . disCNS . titlesize16 + BDFDB . disCNS . height24 + BDFDB . disCN . flexchild } " style="flex: 0 0 auto;">Add a contextmenu entry when right clicking</h3></div><div class="BDFDB-settings-inner-list"> ` ;
2019-10-05 17:46:38 +02:00
for ( let key in settings ) {
2019-10-09 14:18:28 +02:00
settingshtml += ` <div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom8 } " style="flex: 1 1 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . marginreset + BDFDB . disCNS . weightmedium + BDFDB . disCNS . titlesize16 + BDFDB . disCNS . height24 + BDFDB . disCN . flexchild } " style="flex: 1 1 auto;"> ${ this . defaults . settings [ key ] . description } </h3><div class=" ${ BDFDB . disCNS . flexchild + BDFDB . disCNS . switchenabled + BDFDB . disCNS . switch + BDFDB . disCNS . switchvalue + BDFDB . disCNS . switchsizedefault + BDFDB . disCNS . switchsize + BDFDB . disCN . switchthemedefault } " style="flex: 0 0 auto;"><input type="checkbox" value="settings ${ key } " class=" ${ BDFDB . disCNS . switchinnerenabled + BDFDB . disCN . switchinner } settings-switch" ${ settings [ key ] ? " checked" : "" } ></div></div> ` ;
2019-10-05 17:46:38 +02:00
}
2019-10-06 16:41:40 +02:00
settingshtml += ` </div> ` ;
2019-10-09 14:18:28 +02:00
settingshtml += ` <div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom8 } " style="flex: 1 1 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . marginreset + BDFDB . disCNS . weightmedium + BDFDB . disCNS . titlesize16 + BDFDB . disCNS . height24 + BDFDB . disCN . flexchild } " style="flex: 0 0 auto;">Search Engines:</h3></div><div class="BDFDB-settings-inner-list"> ` ;
2018-10-11 10:21:26 +02:00
for ( let key in engines ) {
2019-10-09 14:18:28 +02:00
settingshtml += ` <div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom8 } " style="flex: 1 1 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . marginreset + BDFDB . disCNS . weightmedium + BDFDB . disCNS . titlesize16 + BDFDB . disCNS . height24 + BDFDB . disCN . flexchild } " style="flex: 1 1 auto;"> ${ this . defaults . engines [ key ] . name } </h3><div class=" ${ BDFDB . disCNS . flexchild + BDFDB . disCNS . switchenabled + BDFDB . disCNS . switch + BDFDB . disCNS . switchvalue + BDFDB . disCNS . switchsizedefault + BDFDB . disCNS . switchsize + BDFDB . disCN . switchthemedefault } " style="flex: 0 0 auto;"><input type="checkbox" value="engines ${ key } " class=" ${ BDFDB . disCNS . switchinnerenabled + BDFDB . disCN . switchinner } settings-switch" ${ engines [ key ] ? " checked" : "" } ></div></div> ` ;
2018-10-11 10:21:26 +02:00
}
settingshtml += ` </div> ` ;
settingshtml += ` </div></div> ` ;
2019-01-26 22:45:19 +01:00
2019-10-23 11:10:01 +02:00
let settingspanel = BDFDB . DOMUtils . create ( settingshtml ) ;
2018-10-11 10:21:26 +02:00
2019-01-17 23:48:29 +01:00
BDFDB . initElements ( settingspanel , this ) ;
2019-01-26 22:45:19 +01:00
2018-10-11 10:21:26 +02:00
return settingspanel ;
}
2019-01-26 22:45:19 +01:00
2018-10-11 10:21:26 +02:00
//legacy
load ( ) { }
start ( ) {
2019-02-04 09:13:15 +01:00
if ( ! global . BDFDB ) global . BDFDB = { myPlugins : { } } ;
if ( global . BDFDB && global . BDFDB . myPlugins && typeof global . BDFDB . myPlugins == "object" ) global . BDFDB . myPlugins [ this . getName ( ) ] = this ;
2019-05-26 13:55:26 +02:00
var libraryScript = document . querySelector ( 'head script#BDFDBLibraryScript' ) ;
if ( ! libraryScript || ( performance . now ( ) - libraryScript . getAttribute ( "date" ) ) > 600000 ) {
2018-10-11 10:21:26 +02:00
if ( libraryScript ) libraryScript . remove ( ) ;
libraryScript = document . createElement ( "script" ) ;
2019-05-26 13:55:26 +02:00
libraryScript . setAttribute ( "id" , "BDFDBLibraryScript" ) ;
2018-10-11 10:21:26 +02:00
libraryScript . setAttribute ( "type" , "text/javascript" ) ;
2019-10-18 10:56:41 +02:00
libraryScript . setAttribute ( "src" , "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js" ) ;
2019-01-17 23:48:29 +01:00
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
2019-05-26 13:55:26 +02:00
libraryScript . addEventListener ( "load" , ( ) => { this . initialize ( ) ; } ) ;
2018-10-11 10:21:26 +02:00
document . head . appendChild ( libraryScript ) ;
2019-05-26 13:55:26 +02:00
}
else if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) this . initialize ( ) ;
2018-10-11 10:21:26 +02:00
this . startTimeout = setTimeout ( ( ) => { this . initialize ( ) ; } , 30000 ) ;
}
initialize ( ) {
2019-01-17 23:48:29 +01:00
if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-01-22 11:05:54 +01:00
if ( this . started ) return ;
2019-10-22 18:55:25 +02:00
BDFDB . PluginUtils . init ( this ) ;
2018-10-11 10:21:26 +02:00
}
2019-10-22 18:55:25 +02:00
else console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , 'color: #3a71c1; font-weight: 700;' , '' , 'Fatal Error: Could not load BD functions!' ) ;
2018-10-11 10:21:26 +02:00
}
stop ( ) {
2019-01-17 23:48:29 +01:00
if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-10-22 11:37:23 +02:00
this . stopping = true ;
2019-10-22 18:55:25 +02:00
BDFDB . PluginUtils . clear ( this ) ;
2018-10-11 10:21:26 +02:00
}
}
2019-01-26 22:45:19 +01:00
2018-10-11 10:21:26 +02:00
// begin of own functions
2019-01-26 22:45:19 +01:00
2019-10-06 16:41:40 +02:00
onGuildContextMenu ( instance , menu , returnvalue ) {
if ( instance . props && instance . props . guild && instance . props . target ) {
2019-10-23 11:10:01 +02:00
let guildicon = BDFDB . DOMUtils . containsClass ( instance . props . target , BDFDB . disCN . avataricon ) ? instance . props . target : instance . props . target . querySelector ( BDFDB . dotCN . guildicon ) ;
2019-10-22 23:04:35 +02:00
if ( guildicon && BDFDB . DataUtils . get ( this , "settings" , "addGuildIconEntry" ) ) this . appendItem ( menu , returnvalue , guildicon . tagName == "IMG" ? guildicon . getAttribute ( "src" ) : guildicon . style . getPropertyValue ( "background-image" ) ) ;
2019-10-06 16:41:40 +02:00
}
}
2019-10-05 17:46:38 +02:00
onUserContextMenu ( instance , menu , returnvalue ) {
if ( instance . props && instance . props . user && instance . props . target ) {
2019-10-23 11:10:01 +02:00
let avatar = BDFDB . DOMUtils . containsClass ( instance . props . target , BDFDB . disCN . avataricon ) ? instance . props . target : instance . props . target . querySelector ( BDFDB . dotCN . avatar ) ;
2019-10-22 23:04:35 +02:00
if ( avatar && BDFDB . DataUtils . get ( this , "settings" , "addUserAvatarEntry" ) ) this . appendItem ( menu , returnvalue , avatar . tagName == "IMG" ? avatar . getAttribute ( "src" ) : avatar . style . getPropertyValue ( "background-image" ) ) ;
2019-10-05 17:46:38 +02:00
}
}
2019-09-11 12:14:43 +02:00
onNativeContextMenu ( instance , menu , returnvalue ) {
if ( instance . props && instance . props . type == "NATIVE_IMAGE" && ( instance . props . href || instance . props . src ) && ! menu . querySelector ( ` ${ this . name } -contextMenuSubItem ` ) ) {
this . appendItem ( menu , returnvalue , instance . props . href || instance . props . src ) ;
2019-01-03 11:30:54 +01:00
}
}
2019-01-26 22:45:19 +01:00
2019-09-11 12:14:43 +02:00
onMessageContextMenu ( instance , menu , returnvalue ) {
2019-01-03 11:30:54 +01:00
if ( instance . props && instance . props . message && instance . props . channel && instance . props . target && ! menu . querySelector ( ".reverseimagesearch-item" ) ) {
if ( instance . props . attachment ) {
2019-09-11 12:14:43 +02:00
this . appendItem ( menu , returnvalue , instance . props . attachment . url ) ;
2019-01-03 11:30:54 +01:00
}
2019-02-28 22:56:56 +01:00
if ( instance . props . target . tagName == "A" && instance . props . message . embeds && instance . props . message . embeds [ 0 ] && instance . props . message . embeds [ 0 ] . type == "image" ) {
2019-09-11 12:14:43 +02:00
this . appendItem ( menu , returnvalue , instance . props . target . href ) ;
2018-10-11 10:21:26 +02:00
}
2019-10-23 11:10:01 +02:00
if ( instance . props . target . tagName == "IMG" && BDFDB . DOMUtils . containsClass ( instance . props . target , "emoji" , "emote" , false ) && BDFDB . DataUtils . get ( this , "settings" , "addEmojiEntry" ) ) {
2019-10-06 16:41:40 +02:00
this . appendItem ( menu , returnvalue , instance . props . target . src ) ;
}
2018-10-11 10:21:26 +02:00
}
}
2019-01-26 22:45:19 +01:00
2019-09-11 12:14:43 +02:00
appendItem ( menu , returnvalue , url ) {
2019-02-28 22:56:56 +01:00
if ( url && url . indexOf ( "discordapp.com/assets/" ) == - 1 && ! url . endsWith ( ".mp4" ) ) {
2019-10-06 16:41:40 +02:00
url = url . replace ( /^url\(|\)$|"|'/g , "" ) . replace ( /\?size\=\d+$/ , "?size=4096" ) ;
2019-02-18 20:35:44 +01:00
if ( url . indexOf ( "https://images-ext-1.discordapp.net/external/" ) > - 1 ) {
if ( url . split ( "/https/" ) . length != 1 ) url = "https://" + url . split ( "/https/" ) [ url . split ( "/https/" ) . length - 1 ] ;
else if ( url . split ( "/http/" ) . length != 1 ) url = "http://" + url . split ( "/http/" ) [ url . split ( "/http/" ) . length - 1 ] ;
2019-01-03 11:30:54 +01:00
}
2019-10-22 19:49:57 +02:00
let engines = BDFDB . DataUtils . get ( this , "engines" ) ;
2019-09-11 12:14:43 +02:00
let items = [ ] ;
2019-10-22 18:55:25 +02:00
for ( let key in engines ) if ( engines [ key ] ) items . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItem , {
2019-09-11 12:14:43 +02:00
label : this . defaults . engines [ key ] . name ,
className : ` BDFDB-contextMenuItem ${ this . name } -contextMenuItem ${ this . name } -engine-contextMenuItem ` ,
2019-10-05 17:48:33 +02:00
danger : key == "_all" ,
2019-09-11 12:14:43 +02:00
action : e => {
if ( ! e . shiftKey ) BDFDB . closeContextMenu ( menu ) ;
if ( key == "_all" ) {
for ( let key2 in engines ) if ( key2 != "_all" && engines [ key2 ] ) window . open ( this . defaults . engines [ key2 ] . url . replace ( this . imgUrlReplaceString , encodeURIComponent ( url ) ) , "_blank" ) ;
2019-02-18 20:35:44 +01:00
}
2019-09-11 12:14:43 +02:00
else window . open ( this . defaults . engines [ key ] . url . replace ( this . imgUrlReplaceString , encodeURIComponent ( url ) ) , "_blank" ) ;
}
} ) ) ;
2019-10-22 18:55:25 +02:00
if ( ! items . length ) items . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItem , {
2019-09-11 12:14:43 +02:00
label : this . labels . submenu _disabled _text ,
className : ` BDFDB-contextMenuItem ${ this . name } -contextMenuItem ${ this . name } -disabled-contextMenuItem ` ,
disabled : true
} ) ) ;
2019-10-22 19:38:25 +02:00
let [ children , index ] = BDFDB . ReactUtils . findChildren ( returnvalue , { name : [ "FluxContainer(MessageDeveloperModeGroup)" , "DeveloperModeGroup" ] } ) ;
2019-10-22 18:55:25 +02:00
const itemgroup = BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItemGroup , {
2019-09-11 12:14:43 +02:00
className : ` BDFDB-contextMenuItemGroup ${ this . name } -contextMenuItemGroup ` ,
children : [
2019-10-22 18:55:25 +02:00
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuSubItem , {
2019-09-11 12:14:43 +02:00
label : "Reverse Image Search" ,
className : ` BDFDB-contextMenuSubItem ${ this . name } -contextMenuSubItem ${ this . name } -search-contextMenuSubItem ` ,
render : items
} )
]
2019-02-18 20:35:44 +01:00
} ) ;
2019-09-11 12:14:43 +02:00
if ( index > - 1 ) children . splice ( index , 0 , itemgroup ) ;
else children . push ( itemgroup ) ;
2018-10-11 10:21:26 +02:00
}
}
2019-01-26 22:45:19 +01:00
2018-10-11 10:21:26 +02:00
setLabelsByLanguage ( ) {
2019-10-22 23:04:35 +02:00
switch ( BDFDB . LanguageUtils . getLanguage ( ) . id ) {
2018-10-11 10:21:26 +02:00
case "hr" : //croatian
return {
submenu _disabled _text : "Svi su onemogućeni"
} ;
case "da" : //danish
return {
submenu _disabled _text : "Alle deaktiveret"
} ;
case "de" : //german
return {
submenu _disabled _text : "Alle deaktiviert"
} ;
case "es" : //spanish
return {
submenu _disabled _text : "Todo desactivado"
} ;
case "fr" : //french
return {
submenu _disabled _text : "Tous désactivés"
} ;
case "it" : //italian
return {
submenu _disabled _text : "Tutto disattivato"
} ;
case "nl" : //dutch
return {
submenu _disabled _text : "Alles gedeactiveerd"
} ;
case "no" : //norwegian
return {
submenu _disabled _text : "Alle deaktivert"
} ;
case "pl" : //polish
return {
submenu _disabled _text : "Wszystkie wyłączone"
} ;
case "pt-BR" : //portuguese (brazil)
return {
submenu _disabled _text : "Todos desativados"
} ;
case "fi" : //finnish
return {
submenu _disabled _text : "Kaikki on poistettu käytöstä"
} ;
case "sv" : //swedish
return {
submenu _disabled _text : "Alla avaktiverade"
} ;
case "tr" : //turkish
return {
submenu _disabled _text : "Hepsi deaktive"
} ;
case "cs" : //czech
return {
submenu _disabled _text : "Všechny deaktivované"
} ;
case "bg" : //bulgarian
return {
submenu _disabled _text : "Всички с а деактивирани"
} ;
case "ru" : //russian
return {
submenu _disabled _text : "В с е деактивированные"
} ;
case "uk" : //ukrainian
return {
submenu _disabled _text : "В с і вимкнені"
} ;
case "ja" : //japanese
return {
submenu _disabled _text : "すべて非アクティブ化"
} ;
case "zh-TW" : //chinese (traditional)
return {
submenu _disabled _text : "全部停用"
} ;
case "ko" : //korean
return {
submenu _disabled _text : "모두 비활성화 됨"
} ;
default : //default: english
return {
submenu _disabled _text : "All disabled"
} ;
}
}
}