mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2024-11-25 14:42:44 +01:00
Compare commits
No commits in common. "af48bf60ce30fda95680b07936705be8fff4daf0" and "6ca386b7419e4769423f2e9d1eac3fe79193ea93" have entirely different histories.
af48bf60ce
...
6ca386b741
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
4
build.py
4
build.py
@ -8,8 +8,8 @@ import os
|
||||
import re
|
||||
import distutils.dir_util
|
||||
|
||||
VERSION_SHORT = "v.31g"
|
||||
VERSION_FULL = VERSION_SHORT + ", released 25 December 2023"
|
||||
VERSION_SHORT = "v.31f"
|
||||
VERSION_FULL = VERSION_SHORT + ", released 20 November 2023"
|
||||
|
||||
EXEC_UGLIFYJS_WIN = "{2}/lib/uglifyjs.cmd --parse bare_returns --compress --output \"{1}\" \"{0}\""
|
||||
EXEC_UGLIFYJS_AUTO = "uglifyjs --parse bare_returns --compress --output \"{1}\" \"{0}\""
|
||||
|
4
src/tracker/bootstrap.js
vendored
4
src/tracker/bootstrap.js
vendored
@ -61,11 +61,9 @@ const onTrackingContinued = function(anyNewMessages) {
|
||||
let action = null;
|
||||
|
||||
if (!DISCORD.hasMoreMessages()) {
|
||||
console.debug("[DHT] Reached first message.");
|
||||
action = SETTINGS.afterFirstMsg;
|
||||
}
|
||||
if (isNoAction(action) && !anyNewMessages) {
|
||||
console.debug("[DHT] No new messages.");
|
||||
action = SETTINGS.afterSavedMsg;
|
||||
}
|
||||
|
||||
@ -108,7 +106,7 @@ const onMessagesUpdated = async messages => {
|
||||
isSending = true;
|
||||
|
||||
try {
|
||||
STATE.addDiscordChannel(info.server, info.channel);
|
||||
await STATE.addDiscordChannel(info.server, info.channel);
|
||||
} catch (e) {
|
||||
onError(e);
|
||||
return;
|
||||
|
@ -1,23 +1,5 @@
|
||||
// noinspection JSUnresolvedVariable
|
||||
// noinspection LocalVariableNamingConventionJS
|
||||
class DISCORD {
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
||||
static CHANNEL_TYPE = {
|
||||
DM: 1,
|
||||
GROUP_DM: 3,
|
||||
ANNOUNCEMENT_THREAD: 10,
|
||||
PUBLIC_THREAD: 11,
|
||||
PRIVATE_THREAD: 12
|
||||
};
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#message-object-message-types
|
||||
static MESSAGE_TYPE = {
|
||||
DEFAULT: 0,
|
||||
REPLY: 19,
|
||||
THREAD_STARTER: 21
|
||||
};
|
||||
|
||||
static getMessageOuterElement() {
|
||||
return DOM.queryReactClass("messagesWrapper");
|
||||
}
|
||||
@ -46,11 +28,46 @@ class DISCORD {
|
||||
* Calls the provided function with a list of messages whenever the currently loaded messages change.
|
||||
*/
|
||||
static setupMessageCallback(callback) {
|
||||
let skipsLeft = 0;
|
||||
let waitForCleanup = false;
|
||||
const previousMessages = new Set();
|
||||
|
||||
const onMessageElementsChanged = function() {
|
||||
const messages = DISCORD.getMessages();
|
||||
const hasChanged = messages.some(message => !previousMessages.has(message.id)) || !DISCORD.hasMoreMessages();
|
||||
const timer = window.setInterval(() => {
|
||||
if (skipsLeft > 0) {
|
||||
--skipsLeft;
|
||||
return;
|
||||
}
|
||||
|
||||
const view = this.getMessageOuterElement();
|
||||
|
||||
if (!view) {
|
||||
skipsLeft = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
const anyMessage = DOM.queryReactClass("message", this.getMessageOuterElement());
|
||||
const messageCount = anyMessage ? anyMessage.parentElement.children.length : 0;
|
||||
|
||||
if (messageCount > 300) {
|
||||
if (waitForCleanup) {
|
||||
return;
|
||||
}
|
||||
|
||||
skipsLeft = 3;
|
||||
waitForCleanup = true;
|
||||
|
||||
window.setTimeout(() => {
|
||||
const view = this.getMessageScrollerElement();
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
view.scrollTop = view.scrollHeight / 2;
|
||||
}, 1);
|
||||
}
|
||||
else {
|
||||
waitForCleanup = false;
|
||||
}
|
||||
|
||||
const messages = this.getMessages();
|
||||
const hasChanged = messages.some(message => !previousMessages.has(message.id)) || !this.hasMoreMessages();
|
||||
|
||||
if (!hasChanged) {
|
||||
return;
|
||||
@ -62,74 +79,24 @@ class DISCORD {
|
||||
}
|
||||
|
||||
callback(messages);
|
||||
};
|
||||
}, 200);
|
||||
|
||||
let debounceTimer;
|
||||
|
||||
/**
|
||||
* Do not trigger the callback too often due to autoscrolling.
|
||||
*/
|
||||
const onMessageElementsChangedLater = function() {
|
||||
window.clearTimeout(debounceTimer);
|
||||
debounceTimer = window.setTimeout(onMessageElementsChanged, 100);
|
||||
};
|
||||
|
||||
const observer = new MutationObserver(function () {
|
||||
onMessageElementsChangedLater();
|
||||
});
|
||||
|
||||
let skipsLeft = 0;
|
||||
let observedElement = null;
|
||||
|
||||
const observerTimer = window.setInterval(() => {
|
||||
if (skipsLeft > 0) {
|
||||
--skipsLeft;
|
||||
return;
|
||||
}
|
||||
|
||||
const view = this.getMessageOuterElement();
|
||||
|
||||
if (!view) {
|
||||
skipsLeft = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (observedElement !== null && observedElement.isConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
observedElement = view.querySelector("[data-list-id='chat-messages']");
|
||||
|
||||
if (observedElement) {
|
||||
console.debug("[DHT] Observed message container.");
|
||||
observer.observe(observedElement, { childList: true });
|
||||
onMessageElementsChangedLater();
|
||||
}
|
||||
}, 400);
|
||||
|
||||
window.DHT_ON_UNLOAD.push(() => {
|
||||
observer.disconnect();
|
||||
observedElement = null;
|
||||
window.clearInterval(observerTimer);
|
||||
});
|
||||
window.DHT_ON_UNLOAD.push(() => window.clearInterval(timer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message from a message element.
|
||||
* @returns { null | DiscordMessage } }
|
||||
* Returns the property object of a message element.
|
||||
* @returns { null | { message: DiscordMessage, channel: Object } }
|
||||
*/
|
||||
static getMessageFromElement(ele) {
|
||||
static getMessageElementProps(ele) {
|
||||
const props = DOM.getReactProps(ele);
|
||||
|
||||
if (props && Array.isArray(props.children)) {
|
||||
for (const child of props.children) {
|
||||
if (!(child instanceof Object)) {
|
||||
continue;
|
||||
}
|
||||
if (props.children && props.children.length) {
|
||||
for (let i = 3; i < props.children.length; i++) {
|
||||
const childProps = props.children[i].props;
|
||||
|
||||
const childProps = child.props;
|
||||
if (childProps instanceof Object && "message" in childProps) {
|
||||
return childProps.message;
|
||||
if (childProps && "message" in childProps && "channel" in childProps) {
|
||||
return childProps;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,10 +113,10 @@ class DISCORD {
|
||||
|
||||
for (const ele of this.getMessageElements()) {
|
||||
try {
|
||||
const message = this.getMessageFromElement(ele);
|
||||
const props = this.getMessageElementProps(ele);
|
||||
|
||||
if (message != null) {
|
||||
messages.push(message);
|
||||
if (props != null) {
|
||||
messages.push(props.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[DHT] Error extracing message data, skipping it.", e, ele, DOM.tryGetReactProps(ele));
|
||||
@ -170,7 +137,7 @@ class DISCORD {
|
||||
*/
|
||||
static getSelectedChannel() {
|
||||
try {
|
||||
let obj = null;
|
||||
let obj;
|
||||
|
||||
try {
|
||||
for (const child of DOM.getReactProps(DOM.queryReactClass("chatContent")).children) {
|
||||
@ -181,6 +148,15 @@ class DISCORD {
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[DHT] Error retrieving selected channel from 'chatContent' element.", e);
|
||||
|
||||
for (const ele of this.getMessageElements()) {
|
||||
const props = this.getMessageElementProps(ele);
|
||||
|
||||
if (props != null) {
|
||||
obj = props.channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!obj || typeof obj.id !== "string") {
|
||||
@ -209,8 +185,8 @@ class DISCORD {
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
||||
switch (obj.type) {
|
||||
case DISCORD.CHANNEL_TYPE.DM: type = "DM"; break;
|
||||
case DISCORD.CHANNEL_TYPE.GROUP_DM: type = "GROUP"; break;
|
||||
case 1: type = "DM"; break;
|
||||
case 3: type = "GROUP"; break;
|
||||
default: return null;
|
||||
}
|
||||
|
||||
@ -248,7 +224,7 @@ class DISCORD {
|
||||
}
|
||||
};
|
||||
|
||||
if (obj.type === DISCORD.CHANNEL_TYPE.ANNOUNCEMENT_THREAD || obj.type === DISCORD.CHANNEL_TYPE.PUBLIC_THREAD || obj.type === DISCORD.CHANNEL_TYPE.PRIVATE_THREAD) {
|
||||
if (obj.parent_id) {
|
||||
channel["extra"]["parent"] = obj.parent_id;
|
||||
}
|
||||
else {
|
||||
|
@ -204,12 +204,12 @@ ${btn("close", "X")}`);
|
||||
<label><input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll</label><br>
|
||||
<br>
|
||||
<label>After reaching the first message in channel...</label><br>
|
||||
${radio("afm", "nothing", "Continue Tracking")}
|
||||
${radio("afm", "nothing", "Do Nothing")}
|
||||
${radio("afm", "pause", "Pause Tracking")}
|
||||
${radio("afm", "switch", "Switch to Next Channel")}
|
||||
<br>
|
||||
<label>After reaching a previously saved message...</label><br>
|
||||
${radio("asm", "nothing", "Continue Tracking")}
|
||||
${radio("asm", "nothing", "Do Nothing")}
|
||||
${radio("asm", "pause", "Pause Tracking")}
|
||||
${radio("asm", "switch", "Switch to Next Channel")}
|
||||
<p id='dht-cfg-note'>
|
||||
|
@ -269,9 +269,11 @@ class SAVEFILE{
|
||||
|
||||
addMessagesFromDiscord(discordMessageArray){
|
||||
var hasNewMessages = false;
|
||||
|
||||
for(var discordMessage of discordMessageArray){
|
||||
if (this.addMessage(discordMessage.channel_id, discordMessage.id, this.convertToMessageObject(discordMessage))){
|
||||
var type = discordMessage.type;
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure
|
||||
if ((type === 0 || type === 19) && discordMessage.state === "SENT" && this.addMessage(discordMessage.channel_id, discordMessage.id, this.convertToMessageObject(discordMessage))){
|
||||
hasNewMessages = true;
|
||||
}
|
||||
}
|
||||
|
@ -122,13 +122,12 @@ const STATE = (function() {
|
||||
this._triggerStateChanged("data", "channel");
|
||||
}
|
||||
}
|
||||
// Right. Upstream desktop `bootstrap.js` expects an `async` here. I think it's fine.
|
||||
|
||||
/*
|
||||
* Adds all messages from the array to the specified channel. Returns true if the savefile was updated.
|
||||
*/
|
||||
addDiscordMessages(discordMessageArray){
|
||||
discordMessageArray = discordMessageArray.filter(msg => (msg.type === DISCORD.MESSAGE_TYPE.DEFAULT || msg.type === DISCORD.MESSAGE_TYPE.REPLY || msg.type === DISCORD.MESSAGE_TYPE.THREAD_STARTER) && msg.state === "SENT");
|
||||
|
||||
if (this.getSavefile().addMessagesFromDiscord(discordMessageArray)){
|
||||
this._triggerStateChanged("data", "messages");
|
||||
return true;
|
||||
|
@ -1,8 +1,7 @@
|
||||
var DISCORD = (function(){
|
||||
var REGEX = {
|
||||
formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g,
|
||||
formatItalic1: /\*([\s\S]+?)\*(?!\*)/g,
|
||||
formatItalic2: /_([\s\S]+?)_(?!_)\b/g,
|
||||
formatItalic: /(.)?\*([\s\S]+?)\*(?!\*)/g,
|
||||
formatUnderline: /__([\s\S]+?)__(?!_)/g,
|
||||
formatStrike: /~~([\s\S]+?)~~(?!~)/g,
|
||||
formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g,
|
||||
@ -55,8 +54,7 @@ var DISCORD = (function(){
|
||||
.replace(REGEX.specialEscapedSingle, escapeHtmlMatch)
|
||||
.replace(REGEX.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch))
|
||||
.replace(REGEX.formatBold, "<b>$1</b>")
|
||||
.replace(REGEX.formatItalic1, "<i>$1</i>")
|
||||
.replace(REGEX.formatItalic2, "<i>$1</i>")
|
||||
.replace(REGEX.formatItalic, (full, pre, match) => pre === '\\' ? full : (pre || "")+"<i>"+match+"</i>")
|
||||
.replace(REGEX.formatUnderline, "<u>$1</u>")
|
||||
.replace(REGEX.formatStrike, "<s>$1</s>");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user