Fix broken channel detection after a Discord update (browser script)

#161
This commit is contained in:
chylex 2022-02-12 12:41:33 +01:00
parent edc23d616d
commit cacf43d1d8
No known key found for this signature in database
GPG Key ID: 4DE42C8F19A80548
2 changed files with 76 additions and 61 deletions

View File

@ -70,3 +70,4 @@ messages
msSaveBlob msSaveBlob
messageReference messageReference
message_id message_id
guild_id

View File

@ -7,6 +7,36 @@ var DISCORD = (function(){
return getMessageOuterElement().querySelector("[class*='scroller-']"); return getMessageOuterElement().querySelector("[class*='scroller-']");
}; };
var getMessageElements = function() {
return getMessageOuterElement().querySelectorAll("[class*='message-']");
};
var getReactProps = function(ele) {
var keys = Object.keys(ele || {});
var key = keys.find(key => key.startsWith("__reactInternalInstance"));
if (key){
return ele[key].memoizedProps;
}
key = keys.find(key => key.startsWith("__reactProps$"));
return key ? ele[key] : null;
};
var getMessageElementProps = function(ele) {
const props = getReactProps(ele);
if (props.children && props.children.length >= 4) {
const childProps = props.children[3].props;
if ("message" in childProps && "channel" in childProps) {
return childProps;
}
}
return null;
};
var observerTimer = 0, waitingForCleanup = 0; var observerTimer = 0, waitingForCleanup = 0;
return { return {
@ -60,15 +90,7 @@ var DISCORD = (function(){
* Returns internal React state object of an element. * Returns internal React state object of an element.
*/ */
getReactProps: function(ele){ getReactProps: function(ele){
var keys = Object.keys(ele || {}); return getReactProps(ele);
var key = keys.find(key => key.startsWith("__reactInternalInstance"));
if (key){
return ele[key].memoizedProps;
}
key = keys.find(key => key.startsWith("__reactProps$"));
return key ? ele[key] : null;
}, },
/* /*
@ -76,83 +98,75 @@ var DISCORD = (function(){
* For types DM and GROUP, the server and channel names are identical. * For types DM and GROUP, the server and channel names are identical.
* For SERVER type, the channel has to be in view, otherwise Discord unloads it. * For SERVER type, the channel has to be in view, otherwise Discord unloads it.
*/ */
getSelectedChannel: function(){ getSelectedChannel: function() {
try{ try {
var obj; let obj;
var channelListEle = DOM.queryReactClass("privateChannels");
if (channelListEle){ for (const ele of getMessageElements()) {
var channel = DOM.queryReactClass("selected", channelListEle); const props = getMessageElementProps(ele);
if (!channel || !("href" in channel) || !channel.href.includes("/@me/")){ if (props != null) {
return null; obj = props.channel;
break;
} }
}
if (!obj) {
return null;
}
var dms = DOM.queryReactClass("privateChannels");
if (dms){
let name;
var linkSplit = channel.href.split("/"); for (const ele of dms.querySelectorAll("[class*='channel-'] [class*='selected-'] [class^='name-'] *, [class*='channel-'][class*='selected-'] [class^='name-'] *")) {
var link = linkSplit[linkSplit.length-1]; const node = Array.prototype.find.call(ele.childNodes, node => node.nodeType === Node.TEXT_NODE);
if (!(/^\d+$/.test(link))){
return null;
}
var name;
for(let ele of channel.querySelectorAll("[class^='name-'] *")){
let node = Array.prototype.find.call(ele.childNodes, node => node.nodeType === Node.TEXT_NODE);
if (node){ if (node) {
name = node.nodeValue; name = node.nodeValue;
break; break;
} }
} }
if (!name){ if (!name) {
return null; return null;
} }
var icon = channel.querySelector("img[class*='avatar']"); let type;
var iconParent = icon && icon.closest("foreignObject");
var iconMask = iconParent && iconParent.getAttribute("mask");
obj = { // https://discord.com/developers/docs/resources/channel#channel-object-channel-types
switch (obj.type) {
case 1: type = "DM"; break;
case 3: type = "GROUP"; break;
default: return null;
}
return {
"server": name, "server": name,
"channel": name, "channel": name,
"id": link, "id": obj.id,
"type": (iconMask && iconMask.includes("#svg-mask-avatar-default")) ? "GROUP" : "DM", "type": type,
"extra": {} "extra": {}
}; };
} }
else{ else if (obj.guild_id) {
channelListEle = document.getElementById("channels"); return {
var channel = channelListEle.querySelector("[class*='modeSelected']").parentElement;
var props = DISCORD.getReactProps(channel).children.props;
if (!props){
return null;
}
var channelObj = props.channel || props.children().props.channel;
if (!channelObj){
return null;
}
obj = {
"server": document.querySelector("nav header > h1").innerText, "server": document.querySelector("nav header > h1").innerText,
"channel": channelObj.name, "channel": obj.name,
"id": channelObj.id, "id": obj.id,
"type": "SERVER", "type": "SERVER",
"extra": { "extra": {
"position": channelObj.position, "position": obj.position,
"topic": channelObj.topic, "topic": obj.topic,
"nsfw": channelObj.nsfw "nsfw": obj.nsfw
} }
}; };
} }
else {
return obj.channel.length === 0 ? null : obj; return null;
}catch(e){ }
} catch(e) {
console.error(e); console.error(e);
return null; return null;
} }