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
2592
bld/track.user.js
2592
bld/track.user.js
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 re
|
||||||
import distutils.dir_util
|
import distutils.dir_util
|
||||||
|
|
||||||
VERSION_SHORT = "v.31g"
|
VERSION_SHORT = "v.31f"
|
||||||
VERSION_FULL = VERSION_SHORT + ", released 25 December 2023"
|
VERSION_FULL = VERSION_SHORT + ", released 20 November 2023"
|
||||||
|
|
||||||
EXEC_UGLIFYJS_WIN = "{2}/lib/uglifyjs.cmd --parse bare_returns --compress --output \"{1}\" \"{0}\""
|
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}\""
|
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;
|
let action = null;
|
||||||
|
|
||||||
if (!DISCORD.hasMoreMessages()) {
|
if (!DISCORD.hasMoreMessages()) {
|
||||||
console.debug("[DHT] Reached first message.");
|
|
||||||
action = SETTINGS.afterFirstMsg;
|
action = SETTINGS.afterFirstMsg;
|
||||||
}
|
}
|
||||||
if (isNoAction(action) && !anyNewMessages) {
|
if (isNoAction(action) && !anyNewMessages) {
|
||||||
console.debug("[DHT] No new messages.");
|
|
||||||
action = SETTINGS.afterSavedMsg;
|
action = SETTINGS.afterSavedMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ const onMessagesUpdated = async messages => {
|
|||||||
isSending = true;
|
isSending = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
STATE.addDiscordChannel(info.server, info.channel);
|
await STATE.addDiscordChannel(info.server, info.channel);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
onError(e);
|
onError(e);
|
||||||
return;
|
return;
|
||||||
|
@ -1,23 +1,5 @@
|
|||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
// noinspection LocalVariableNamingConventionJS
|
|
||||||
class DISCORD {
|
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() {
|
static getMessageOuterElement() {
|
||||||
return DOM.queryReactClass("messagesWrapper");
|
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.
|
* Calls the provided function with a list of messages whenever the currently loaded messages change.
|
||||||
*/
|
*/
|
||||||
static setupMessageCallback(callback) {
|
static setupMessageCallback(callback) {
|
||||||
|
let skipsLeft = 0;
|
||||||
|
let waitForCleanup = false;
|
||||||
const previousMessages = new Set();
|
const previousMessages = new Set();
|
||||||
|
|
||||||
const onMessageElementsChanged = function() {
|
const timer = window.setInterval(() => {
|
||||||
const messages = DISCORD.getMessages();
|
if (skipsLeft > 0) {
|
||||||
const hasChanged = messages.some(message => !previousMessages.has(message.id)) || !DISCORD.hasMoreMessages();
|
--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) {
|
if (!hasChanged) {
|
||||||
return;
|
return;
|
||||||
@ -62,74 +79,24 @@ class DISCORD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callback(messages);
|
callback(messages);
|
||||||
};
|
}, 200);
|
||||||
|
|
||||||
let debounceTimer;
|
window.DHT_ON_UNLOAD.push(() => window.clearInterval(timer));
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message from a message element.
|
* Returns the property object of a message element.
|
||||||
* @returns { null | DiscordMessage } }
|
* @returns { null | { message: DiscordMessage, channel: Object } }
|
||||||
*/
|
*/
|
||||||
static getMessageFromElement(ele) {
|
static getMessageElementProps(ele) {
|
||||||
const props = DOM.getReactProps(ele);
|
const props = DOM.getReactProps(ele);
|
||||||
|
|
||||||
if (props && Array.isArray(props.children)) {
|
if (props.children && props.children.length) {
|
||||||
for (const child of props.children) {
|
for (let i = 3; i < props.children.length; i++) {
|
||||||
if (!(child instanceof Object)) {
|
const childProps = props.children[i].props;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const childProps = child.props;
|
if (childProps && "message" in childProps && "channel" in childProps) {
|
||||||
if (childProps instanceof Object && "message" in childProps) {
|
return childProps;
|
||||||
return childProps.message;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,10 +113,10 @@ class DISCORD {
|
|||||||
|
|
||||||
for (const ele of this.getMessageElements()) {
|
for (const ele of this.getMessageElements()) {
|
||||||
try {
|
try {
|
||||||
const message = this.getMessageFromElement(ele);
|
const props = this.getMessageElementProps(ele);
|
||||||
|
|
||||||
if (message != null) {
|
if (props != null) {
|
||||||
messages.push(message);
|
messages.push(props.message);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[DHT] Error extracing message data, skipping it.", e, ele, DOM.tryGetReactProps(ele));
|
console.error("[DHT] Error extracing message data, skipping it.", e, ele, DOM.tryGetReactProps(ele));
|
||||||
@ -170,7 +137,7 @@ class DISCORD {
|
|||||||
*/
|
*/
|
||||||
static getSelectedChannel() {
|
static getSelectedChannel() {
|
||||||
try {
|
try {
|
||||||
let obj = null;
|
let obj;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const child of DOM.getReactProps(DOM.queryReactClass("chatContent")).children) {
|
for (const child of DOM.getReactProps(DOM.queryReactClass("chatContent")).children) {
|
||||||
@ -181,6 +148,15 @@ class DISCORD {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[DHT] Error retrieving selected channel from 'chatContent' element.", 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") {
|
if (!obj || typeof obj.id !== "string") {
|
||||||
@ -209,8 +185,8 @@ class DISCORD {
|
|||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
||||||
switch (obj.type) {
|
switch (obj.type) {
|
||||||
case DISCORD.CHANNEL_TYPE.DM: type = "DM"; break;
|
case 1: type = "DM"; break;
|
||||||
case DISCORD.CHANNEL_TYPE.GROUP_DM: type = "GROUP"; break;
|
case 3: type = "GROUP"; break;
|
||||||
default: return null;
|
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;
|
channel["extra"]["parent"] = obj.parent_id;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -204,12 +204,12 @@ ${btn("close", "X")}`);
|
|||||||
<label><input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll</label><br>
|
<label><input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll</label><br>
|
||||||
<br>
|
<br>
|
||||||
<label>After reaching the first message in channel...</label><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", "pause", "Pause Tracking")}
|
||||||
${radio("afm", "switch", "Switch to Next Channel")}
|
${radio("afm", "switch", "Switch to Next Channel")}
|
||||||
<br>
|
<br>
|
||||||
<label>After reaching a previously saved message...</label><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", "pause", "Pause Tracking")}
|
||||||
${radio("asm", "switch", "Switch to Next Channel")}
|
${radio("asm", "switch", "Switch to Next Channel")}
|
||||||
<p id='dht-cfg-note'>
|
<p id='dht-cfg-note'>
|
||||||
|
@ -269,9 +269,11 @@ class SAVEFILE{
|
|||||||
|
|
||||||
addMessagesFromDiscord(discordMessageArray){
|
addMessagesFromDiscord(discordMessageArray){
|
||||||
var hasNewMessages = false;
|
var hasNewMessages = false;
|
||||||
|
|
||||||
for(var discordMessage of discordMessageArray){
|
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;
|
hasNewMessages = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,13 +122,12 @@ const STATE = (function() {
|
|||||||
this._triggerStateChanged("data", "channel");
|
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.
|
* Adds all messages from the array to the specified channel. Returns true if the savefile was updated.
|
||||||
*/
|
*/
|
||||||
addDiscordMessages(discordMessageArray){
|
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)){
|
if (this.getSavefile().addMessagesFromDiscord(discordMessageArray)){
|
||||||
this._triggerStateChanged("data", "messages");
|
this._triggerStateChanged("data", "messages");
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
var DISCORD = (function(){
|
var DISCORD = (function(){
|
||||||
var REGEX = {
|
var REGEX = {
|
||||||
formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g,
|
formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g,
|
||||||
formatItalic1: /\*([\s\S]+?)\*(?!\*)/g,
|
formatItalic: /(.)?\*([\s\S]+?)\*(?!\*)/g,
|
||||||
formatItalic2: /_([\s\S]+?)_(?!_)\b/g,
|
|
||||||
formatUnderline: /__([\s\S]+?)__(?!_)/g,
|
formatUnderline: /__([\s\S]+?)__(?!_)/g,
|
||||||
formatStrike: /~~([\s\S]+?)~~(?!~)/g,
|
formatStrike: /~~([\s\S]+?)~~(?!~)/g,
|
||||||
formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g,
|
formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g,
|
||||||
@ -55,8 +54,7 @@ var DISCORD = (function(){
|
|||||||
.replace(REGEX.specialEscapedSingle, escapeHtmlMatch)
|
.replace(REGEX.specialEscapedSingle, escapeHtmlMatch)
|
||||||
.replace(REGEX.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch))
|
.replace(REGEX.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch))
|
||||||
.replace(REGEX.formatBold, "<b>$1</b>")
|
.replace(REGEX.formatBold, "<b>$1</b>")
|
||||||
.replace(REGEX.formatItalic1, "<i>$1</i>")
|
.replace(REGEX.formatItalic, (full, pre, match) => pre === '\\' ? full : (pre || "")+"<i>"+match+"</i>")
|
||||||
.replace(REGEX.formatItalic2, "<i>$1</i>")
|
|
||||||
.replace(REGEX.formatUnderline, "<u>$1</u>")
|
.replace(REGEX.formatUnderline, "<u>$1</u>")
|
||||||
.replace(REGEX.formatStrike, "<s>$1</s>");
|
.replace(REGEX.formatStrike, "<s>$1</s>");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user