Update ImageUtilities.plugin.js

This commit is contained in:
Mirco Wittrien 2022-03-02 00:10:26 +01:00
parent 298af32e51
commit 104b8d9149
1 changed files with 54 additions and 45 deletions

View File

@ -2,7 +2,7 @@
* @name ImageUtilities
* @author DevilBro
* @authorId 278543574059057154
* @version 4.6.0
* @version 4.6.1
* @description Adds several Utilities for Images/Videos (Gallery, Download, Reverse Search, Zoom, Copy, etc.)
* @invite Jx3TjNS
* @donate https://www.paypal.me/MircoWittrien
@ -17,8 +17,15 @@ module.exports = (_ => {
"info": {
"name": "ImageUtilities",
"author": "DevilBro",
"version": "4.6.0",
"version": "4.6.1",
"description": "Adds several Utilities for Images/Videos (Gallery, Download, Reverse Search, Zoom, Copy, etc.)"
},
"changeLog": {
"improved": {
"Alt Text": "Larger Image Alt Texts of Images will now be displayed in a new container below the Image Details",
"Server Specific Avatars/Banners": "Can also now be target by the context menu",
"Banners": "You can now view user banners in the full resolution (keep in mind that server specific user banners are always saved in a low resolution, because discord doesn't want to waste server space for each banner, can't be bypassed since no high resolution for them exists"
}
}
};
@ -209,6 +216,9 @@ module.exports = (_ => {
};
this.css = `
${BDFDB.dotCN._imageutilitiesimagedetails} {
display: inline-flex;
}
span + ${BDFDB.dotCN._imageutilitiesimagedetails} {
margin-left: 12px;
}
@ -311,18 +321,25 @@ module.exports = (_ => {
BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.MediaComponentUtils, "renderImageComponent", {
after: e => {
if (this.settings.general.showInDescription && e.methodArguments[0].original && e.methodArguments[0].src.indexOf("https://media.discordapp.net/attachments") == 0 && (e.methodArguments[0].className || "").indexOf(BDFDB.disCN.embedmedia) == -1 && (e.methodArguments[0].className || "").indexOf(BDFDB.disCN.embedthumbnail) == -1 && BDFDB.ReactUtils.findChild(e.returnValue, {name: ["LazyImageZoomable", "LazyImage"]})) {
const altText = e.returnValue.props.children[1] && e.returnValue.props.children[1].props.children;
const details = BDFDB.ReactUtils.createElement(ImageDetailsComponent, {
original: e.methodArguments[0].original,
attachment: {
height: 0,
width: 0,
filename: "unknown.png"
}
});
e.returnValue.props.children[1] = BDFDB.ReactUtils.createElement("span", {
className: BDFDB.disCN.imagealttext,
children: [
e.returnValue.props.children[1],
BDFDB.ReactUtils.createElement(ImageDetailsComponent, {
original: e.methodArguments[0].original,
attachment: {
height: 0,
width: 0,
filename: "unknown.png"
}
})
altText && altText.length >= 50 && BDFDB.ReactUtils.createElement("div", {
children: details
}),
altText && BDFDB.ReactUtils.createElement("span", {
children: altText
}),
(!altText || altText.length < 50) && details
]
});
}
@ -533,51 +550,53 @@ module.exports = (_ => {
if (e.instance.props.guild && this.settings.places.guildIcons) {
if (BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildheader, e.instance.props.target) || BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildchannels, e.instance.props.target) && !e.instance.props.target.className && e.instance.props.target.parentElement.firstElementChild == e.instance.props.target) {
let banner = BDFDB.GuildUtils.getBanner(e.instance.props.guild.id);
if (banner) this.injectItem(e, banner.replace(/\.webp|\.gif/, ".png"), e.instance.props.guild.banner && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.guild.banner), banner);
if (banner) this.injectItem(e, [banner.replace(/\.webp|\.gif/, ".png"), e.instance.props.guild.banner && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.guild.banner), banner], BDFDB.LanguageUtils.LibraryStrings.guildbanner);
}
else if (e.type != "GuildChannelListContextMenu") this.injectItem(e, (e.instance.props.guild.getIconURL(4096) || "").replace(/\.webp|\.gif/, ".png"), e.instance.props.guild.icon && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.guild.icon) && e.instance.props.guild.getIconURL(4096, true));
else if (e.type != "GuildChannelListContextMenu") this.injectItem(e, [(e.instance.props.guild.getIconURL(4096) || "").replace(/\.webp|\.gif/, ".png"), e.instance.props.guild.icon && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.guild.icon) && e.instance.props.guild.getIconURL(4096, true)], BDFDB.LanguageUtils.LibraryStrings.guildicon);
}
}
onUserContextMenu (e) {
if (e.instance.props.user && this.settings.places.userAvatars && e.subType == "useBlockUserItem") {
let validUrls = this.filterUrls((e.instance.props.user.getAvatarURL(null, 4096) || "").replace(/\.webp|\.gif/, ".png"), BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.user.avatar) && e.instance.props.user.getAvatarURL(null, 4096, true), (e.instance.props.user.getAvatarURL(e.instance.props.guildId, 4096) || "").replace(/\.webp|\.gif/, ".png"), BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.user.avatar) && e.instance.props.user.getAvatarURL(e.instance.props.guildId, 4096, true));
const guildId = BDFDB.LibraryModules.LastGuildStore.getGuildId();
const member = BDFDB.LibraryModules.MemberStore.getMember(guildId, e.instance.props.user.id);
let validUrls = this.filterUrls((e.instance.props.user.getAvatarURL(null, 4096) || "").replace(/\.webp|\.gif/, ".png"), BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.user.avatar) && e.instance.props.user.getAvatarURL(null, 4096, true), (e.instance.props.user.getAvatarURL(guildId, 4096) || "").replace(/\.webp|\.gif/, ".png"), member && member.avatar && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(member.avatar) && e.instance.props.user.getAvatarURL(guildId, 4096, true));
if (!validUrls.length) return;
if (e.returnvalue.length) e.returnvalue.push(BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuSeparator, {}));
e.returnvalue.push(BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
label: this.isValid(validUrls[0].file, "video") ? BDFDB.LanguageUtils.LanguageStrings.VIDEO : BDFDB.LanguageUtils.LanguageStrings.IMAGE + " " + BDFDB.LanguageUtils.LanguageStrings.ACTIONS,
id: BDFDB.ContextMenuUtils.createItemId(this.name, "main-subitem"),
children: this.createSubMenus(e.instance, validUrls)
children: this.createSubMenus(e.instance, validUrls, BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_AVATAR)
}));
}
}
onGroupDMContextMenu (e) {
if (e.instance.props.channel && e.instance.props.channel.isGroupDM() && this.settings.places.groupIcons) this.injectItem(e, (BDFDB.DMUtils.getIcon(e.instance.props.channel.id) || "").replace(/\.webp|\.gif/, ".png"));
if (e.instance.props.channel && e.instance.props.channel.isGroupDM() && this.settings.places.groupIcons) this.injectItem(e, [(BDFDB.DMUtils.getIcon(e.instance.props.channel.id) || "").replace(/\.webp|\.gif/, ".png")]);
}
onNativeContextMenu (e) {
if (e.type == "NativeImageContextMenu" && (e.instance.props.href || e.instance.props.src)) this.injectItem(e, e.instance.props.href || e.instance.props.src);
if (e.type == "NativeImageContextMenu" && (e.instance.props.href || e.instance.props.src)) this.injectItem(e, [e.instance.props.href || e.instance.props.src]);
}
onMessageContextMenu (e) {
if (e.instance.props.message && e.instance.props.channel && e.instance.props.target) {
if (e.instance.props.attachment) this.injectItem(e, e.instance.props.attachment.url);
else if (e.instance.props.target.tagName == "A" && e.instance.props.message.embeds && e.instance.props.message.embeds[0] && (e.instance.props.message.embeds[0].type == "image" || e.instance.props.message.embeds[0].type == "video")) this.injectItem(e, e.instance.props.target.href);
if (e.instance.props.attachment) this.injectItem(e, [e.instance.props.attachment.url]);
else if (e.instance.props.target.tagName == "A" && e.instance.props.message.embeds && e.instance.props.message.embeds[0] && (e.instance.props.message.embeds[0].type == "image" || e.instance.props.message.embeds[0].type == "video")) this.injectItem(e, [e.instance.props.target.href]);
else if (e.instance.props.target.tagName == "IMG" && e.instance.props.target.complete && e.instance.props.target.naturalHeight) {
if (BDFDB.DOMUtils.containsClass(e.instance.props.target.parentElement, BDFDB.disCN.imagewrapper)) this.injectItem(e, {file: e.instance.props.target.src, original: this.getTargetLink(e.instance.props.target)});
else if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.embedauthoricon) && this.settings.places.userAvatars) this.injectItem(e, e.instance.props.target.src);
else if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.emojiold, "emote", false) && this.settings.places.emojis) this.injectItem(e, {file: e.instance.props.target.src, alternativeName: e.instance.props.target.getAttribute("data-name")});
if (BDFDB.DOMUtils.containsClass(e.instance.props.target.parentElement, BDFDB.disCN.imagewrapper)) this.injectItem(e, [{file: e.instance.props.target.src, original: this.getTargetLink(e.instance.props.target)}]);
else if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.embedauthoricon) && this.settings.places.userAvatars) this.injectItem(e, [e.instance.props.target.src]);
else if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.emojiold, "emote", false) && this.settings.places.emojis) this.injectItem(e, [{file: e.instance.props.target.src, alternativeName: e.instance.props.target.getAttribute("data-name")}]);
}
else if (e.instance.props.target.tagName == "VIDEO") {
if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.embedvideo) || BDFDB.DOMUtils.getParent(BDFDB.dotCN.attachmentvideo, e.instance.props.target)) this.injectItem(e, {file: e.instance.props.target.src, original: this.getTargetLink(e.instance.props.target)});
if (BDFDB.DOMUtils.containsClass(e.instance.props.target, BDFDB.disCN.embedvideo) || BDFDB.DOMUtils.getParent(BDFDB.dotCN.attachmentvideo, e.instance.props.target)) this.injectItem(e, [{file: e.instance.props.target.src, original: this.getTargetLink(e.instance.props.target)}]);
}
else {
const reaction = BDFDB.DOMUtils.getParent(BDFDB.dotCN.messagereaction, e.instance.props.target);
if (reaction && this.settings.places.emojis) {
const emoji = reaction.querySelector(BDFDB.dotCN.emojiold);
if (emoji) this.injectItem(e, {file: emoji.src, alternativeName: emoji.getAttribute("data-name")});
if (emoji) this.injectItem(e, [{file: emoji.src, alternativeName: emoji.getAttribute("data-name")}]);
}
}
}
@ -590,7 +609,7 @@ module.exports = (_ => {
return href || src;
}
injectItem (e, ...urls) {
injectItem (e, urls, prefix) {
let validUrls = this.filterUrls(...urls);
if (!validUrls.length) return;
let [removeParent, removeIndex] = BDFDB.ContextMenuUtils.findItem(e.returnvalue, {id: "copy-native-link", group: true});
@ -603,7 +622,7 @@ module.exports = (_ => {
let type = this.isValid(validUrls[0].file, "video") ? BDFDB.LanguageUtils.LanguageStrings.VIDEO : BDFDB.LanguageUtils.LanguageStrings.IMAGE;
let isNative = validUrls.length == 1 && removeIndex > -1;
let subMenu = this.createSubMenus(e.instance, validUrls);
let subMenu = this.createSubMenus(e.instance, validUrls, prefix);
let [children, index] = isNative ? [removeParent, removeIndex] : BDFDB.ContextMenuUtils.findItem(e.returnvalue, {id: "devmode-copy-id", group: true});
children.splice(index > -1 ? index : children.length, 0, isNative ? subMenu : BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, {
@ -616,9 +635,10 @@ module.exports = (_ => {
}
filterUrls (...urls) {
let fileTypes = [];
let addedUrls = [];
return urls.filter(n => this.isValid(n && n.file || n)).map(n => {
let srcUrl = (n.file || n).replace(/^url\(|\)$|"|'/g, "").replace(/\?size\=\d+$/, "?size=4096").replace(/[\?\&](height|width)=\d+/g, "").split("%3A")[0];
if (srcUrl.startsWith("https://cdn.discordapp.com/") && !srcUrl.endsWith("?size=4096")) srcUrl += "?size=4096";
let originalUrl = (n.original || n.file || n).replace(/^url\(|\)$|"|'/g, "").replace(/\?size\=\d+$/, "?size=4096").replace(/[\?\&](height|width)=\d+/g, "").split("%3A")[0];
let fileUrl = srcUrl;
if (fileUrl.indexOf("https://images-ext-1.discordapp.net/external/") > -1 || fileUrl.indexOf("https://images-ext-2.discordapp.net/external/") > -1) {
@ -627,7 +647,7 @@ module.exports = (_ => {
}
const file = fileUrl && (BDFDB.LibraryModules.URLParser.parse(fileUrl).pathname || "").toLowerCase();
const fileType = file && (file.split(".").pop() || "");
return fileUrl && fileType && !fileTypes.includes(fileType) && fileTypes.push(fileType) && {file: fileUrl, src: srcUrl, original: originalUrl, fileType, alternativeName: escape((n.alternativeName || "").replace(/:/g, ""))};
return fileUrl && fileType && !addedUrls.includes(srcUrl) && addedUrls.push(srcUrl) && {file: fileUrl, src: srcUrl, original: originalUrl, isGuildSpecific: /^https:\/\/cdn\.discordapp\.com\/guilds\/\d+\/users\/\d+/.test(srcUrl), fileType, alternativeName: escape((n.alternativeName || "").replace(/:/g, ""))};
}).filter(n => n);
}
@ -637,21 +657,9 @@ module.exports = (_ => {
return file && (!type && (url.indexOf("discord.com/streams/guild:") > -1 || url.indexOf("discordapp.com/streams/guild:") > -1 || url.indexOf("discordapp.net/streams/guild:") > -1 || url.startsWith("https://images-ext-1.discordapp.net/") || url.startsWith("https://images-ext-2.discordapp.net/") || Object.keys(fileTypes).some(t => file.endsWith(`/${t}`) || file.endsWith(`.${t}`))) || type && Object.keys(fileTypes).filter(t => fileTypes[t][type]).some(t => file.endsWith(`/${t}`) || file.endsWith(`.${t}`)));
}
createSubMenus (instance, validUrls) {
createSubMenus (instance, validUrls, prefix) {
return validUrls.length == 1 ? this.createUrlMenu(instance, validUrls[0]) : validUrls.map((urlData, i) => BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
label: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.AvatarComponents.default, {
src: urlData.src || urlData.file,
size: BDFDB.LibraryComponents.AvatarComponents.Sizes.SIZE_40
}),
BDFDB.ReactUtils.createElement("span", {
style: {marginLeft: 12},
children: urlData.fileType.toUpperCase()
})
]
}),
label: [urlData.isGuildSpecific && BDFDB.LanguageUtils.LanguageStrings.CHANGE_IDENTITY_SERVER_PROFILE, prefix, urlData.fileType.toUpperCase()].filter(n => n).join(" "),
id: BDFDB.ContextMenuUtils.createItemId(this.name, "subitem", i),
children: this.createUrlMenu(instance, urlData)
}));
@ -1077,12 +1085,13 @@ module.exports = (_ => {
processUserBanner (e) {
let banner = e.instance.props.user && this.settings.places.userAvatars && BDFDB.UserUtils.getBanner(e.instance.props.user.id);
if (banner) e.returnvalue.props.onContextMenu = event => {
let validUrls = this.filterUrls(banner, BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.user.banner) && BDFDB.UserUtils.getBanner(e.instance.props.user.id, true));
const member = BDFDB.LibraryModules.MemberStore.getMember(e.instance.props.guildId, e.instance.props.user.id);
let validUrls = this.filterUrls(banner, BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(e.instance.props.user.banner) && BDFDB.UserUtils.getBanner(e.instance.props.user.id, true), member && member.banner && BDFDB.LibraryModules.BannerUtils.getUserBannerURLForContext({user: e.instance.props.user, guildMember: member, canAnimate: false}), member && member.banner && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(member.banner) && BDFDB.LibraryModules.BannerUtils.getUserBannerURLForContext({user: e.instance.props.user, guildMember: member, canAnimate: true}));
if (validUrls.length) BDFDB.ContextMenuUtils.open(this, event, BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, {
children: validUrls.length == 1 ? this.createSubMenus({}, validUrls) : BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
children: validUrls.length == 1 ? this.createSubMenus({}, validUrls, BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_PROFILE_BANNER) : BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
label: BDFDB.LanguageUtils.LanguageStrings.IMAGE + " " + BDFDB.LanguageUtils.LanguageStrings.ACTIONS,
id: BDFDB.ContextMenuUtils.createItemId(this.name, "main-subitem"),
children: this.createSubMenus({}, validUrls)
children: this.createSubMenus({}, validUrls, BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_PROFILE_BANNER)
})
}));
};