feat(MessageLoggerEnhanced): Add optional time-based cleanup (#603)
* feat(MessageLoggerEnhanced): Add optional time-based cleanup - temporal cleanup preserves DMs and messages in the current channel by default - proper dm detection via ChannelStore (lmk if this is the wrong way to check) - add time limit and server message preservation to mle settings * feat(EquicordHelper): add feat of removed vencord plugin NoDefaultHangStatus it anchors to the default hang status and force it to set enableHangStatus to false. im not sure if it really belongs in EquicordHelper but it feels too small to be its own plugin, and it doesnt fit anywhere else that I can see. Let me know what you think.
This commit is contained in:
parent
d9ef5e31eb
commit
42b9b26666
5 changed files with 96 additions and 9 deletions
|
|
@ -41,13 +41,19 @@ const settings = definePluginSettings({
|
|||
description: "Discord hides your own activity buttons for some reason",
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
noDefaultHangStatus: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Disable the default hang status when joining voice channels",
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "EquicordHelper",
|
||||
description: "Used to provide support, fix discord caused crashes, and other misc features.",
|
||||
authors: [Devs.thororen, EquicordDevs.nyx, EquicordDevs.Naibuu],
|
||||
authors: [Devs.thororen, EquicordDevs.nyx, EquicordDevs.Naibuu, EquicordDevs.keyages],
|
||||
required: true,
|
||||
settings,
|
||||
patches: [
|
||||
|
|
@ -120,6 +126,15 @@ export default definePlugin({
|
|||
replace: "$& && false"
|
||||
}
|
||||
},
|
||||
// No Default Hang Status
|
||||
{
|
||||
find: ".CHILLING)",
|
||||
predicate: () => settings.store.noDefaultHangStatus,
|
||||
replacement: {
|
||||
match: /{enableHangStatus:(\i),/,
|
||||
replace: "{_enableHangStatus:$1=false,"
|
||||
}
|
||||
},
|
||||
// Always show open legacy settings
|
||||
...[
|
||||
".DEVELOPER_SECTION,",
|
||||
|
|
|
|||
|
|
@ -17,18 +17,35 @@
|
|||
*/
|
||||
|
||||
import { Flogger, settings } from ".";
|
||||
import { addMessageIDB, db, DBMessageStatus, deleteMessagesBulkIDB, getOldestMessagesIDB } from "./db";
|
||||
import { addMessageIDB, db, DBMessageStatus, deleteMessagesBulkIDB, getOlderThanTimestampForGuildsIDB, getOldestMessagesIDB } from "./db";
|
||||
import { LoggedMessage, LoggedMessageJSON } from "./types";
|
||||
import { cleanupMessage } from "./utils";
|
||||
import { cacheMessageImages } from "./utils/saveImage";
|
||||
|
||||
export const addMessage = async (message: LoggedMessage | LoggedMessageJSON, status: DBMessageStatus) => {
|
||||
let lastCleanupTime = 0;
|
||||
const CLEANUP_COOLDOWN = 60 * 1000;
|
||||
|
||||
export const addMessage = async (message: LoggedMessage | LoggedMessageJSON, status: DBMessageStatus, currentChannelId?: string) => {
|
||||
if (settings.store.saveImages && status === DBMessageStatus.DELETED)
|
||||
await cacheMessageImages(message);
|
||||
const finalMessage = cleanupMessage(message);
|
||||
|
||||
await addMessageIDB(finalMessage, status);
|
||||
|
||||
if (settings.store.timeBasedCleanupMinutes > 0) {
|
||||
const now = Date.now();
|
||||
if (now - lastCleanupTime > CLEANUP_COOLDOWN) {
|
||||
lastCleanupTime = now;
|
||||
const cutoffTime = new Date(now - settings.store.timeBasedCleanupMinutes * 60 * 1000).toISOString();
|
||||
const oldGuildMessages = await getOlderThanTimestampForGuildsIDB(cutoffTime, currentChannelId, settings.store.preserveCurrentChannel);
|
||||
|
||||
if (oldGuildMessages.length > 0) {
|
||||
Flogger.info(`Deleting ${oldGuildMessages.length} old server messages older than ${settings.store.timeBasedCleanupMinutes} minutes`);
|
||||
await deleteMessagesBulkIDB(oldGuildMessages.map(m => m.message_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.store.messageLimit > 0) {
|
||||
const currentMessageCount = await db.count("messages");
|
||||
if (currentMessageCount > settings.store.messageLimit) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { ChannelStore } from "@webpack/common";
|
||||
import { DBSchema, IDBPDatabase, openDB } from "idb";
|
||||
|
||||
import { LoggedMessageJSON } from "./types";
|
||||
|
|
@ -109,6 +110,36 @@ export async function getOldestMessagesIDB(limit: number) {
|
|||
return cacheRecords(await db.getAllFromIndex("messages", "by_timestamp", undefined, limit));
|
||||
}
|
||||
|
||||
export async function getOlderThanTimestampIDB(timestamp: string) {
|
||||
const tx = db.transaction("messages", "readonly");
|
||||
const { store } = tx;
|
||||
const index = store.index("by_timestamp");
|
||||
|
||||
const cursor = await index.openCursor(IDBKeyRange.upperBound(timestamp));
|
||||
|
||||
if (!cursor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const messages: DBMessageRecord[] = [];
|
||||
for await (const c of cursor) {
|
||||
messages.push(c.value);
|
||||
}
|
||||
|
||||
return cacheRecords(messages);
|
||||
}
|
||||
|
||||
export async function getOlderThanTimestampForGuildsIDB(timestamp: string, currentChannelId?: string, preserveCurrentChannel?: boolean) {
|
||||
const allOldMessages = await getOlderThanTimestampIDB(timestamp);
|
||||
return allOldMessages.filter(record => {
|
||||
const { message } = record;
|
||||
const channel = ChannelStore.getChannel(message.channel_id);
|
||||
const isGuildMessage = channel?.guild_id != null;
|
||||
const isCurrentChannel = preserveCurrentChannel && currentChannelId && message.channel_id === currentChannelId;
|
||||
return isGuildMessage && !isCurrentChannel;
|
||||
});
|
||||
}
|
||||
|
||||
export async function getDateStortedMessagesByStatusIDB(newest: boolean, limit: number, status: DBMessageStatus) {
|
||||
const tx = db.transaction("messages", "readonly");
|
||||
const { store } = tx;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ export const Native = getNative();
|
|||
|
||||
import "./styles.css";
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { FluxDispatcher, MessageStore, UserStore } from "@webpack/common";
|
||||
import { FluxDispatcher, MessageStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
|
||||
import { LogsIcon, OpenLogsButton } from "./components/LogsButton";
|
||||
import { openLogModal } from "./components/LogsModal";
|
||||
|
|
@ -89,7 +89,8 @@ async function messageDeleteHandler(payload: MessageDeletePayload & { isBulk: bo
|
|||
if (payload.isBulk)
|
||||
return message;
|
||||
|
||||
await addMessage(message, ghostPinged ? idb.DBMessageStatus.GHOST_PINGED : idb.DBMessageStatus.DELETED);
|
||||
const currentChannelId = SelectedChannelStore.getChannelId();
|
||||
await addMessage(message, ghostPinged ? idb.DBMessageStatus.GHOST_PINGED : idb.DBMessageStatus.DELETED, currentChannelId);
|
||||
}
|
||||
finally {
|
||||
handledMessageIds.delete(payload.id);
|
||||
|
|
@ -105,6 +106,17 @@ async function messageDeleteBulkHandler({ channelId, guildId, ids }: MessageDele
|
|||
}
|
||||
|
||||
await idb.addMessagesBulkIDB(messages);
|
||||
|
||||
if (messages.length > 0 && settings.store.timeBasedCleanupMinutes > 0) {
|
||||
const currentChannelId = SelectedChannelStore.getChannelId();
|
||||
const cutoffTime = new Date(Date.now() - settings.store.timeBasedCleanupMinutes * 60 * 1000).toISOString();
|
||||
const oldGuildMessages = await idb.getOlderThanTimestampForGuildsIDB(cutoffTime, currentChannelId, settings.store.preserveCurrentChannel);
|
||||
|
||||
if (oldGuildMessages.length > 0) {
|
||||
Flogger.info(`Deleting ${oldGuildMessages.length} old server messages older than ${settings.store.timeBasedCleanupMinutes} minutes (bulk cleanup)`);
|
||||
await idb.deleteMessagesBulkIDB(oldGuildMessages.map(m => m.message_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function messageUpdateHandler(payload: MessageUpdatePayload) {
|
||||
|
|
@ -154,7 +166,8 @@ async function messageUpdateHandler(payload: MessageUpdatePayload) {
|
|||
if (message == null || message.channel_id == null || message.editHistory == null || message.editHistory.length === 0) return;
|
||||
|
||||
// Flogger.log("ADDING MESSAGE (EDITED)", message, payload);
|
||||
await addMessage(message, idb.DBMessageStatus.EDITED);
|
||||
const currentChannelId = SelectedChannelStore.getChannelId();
|
||||
await addMessage(message, idb.DBMessageStatus.EDITED, currentChannelId);
|
||||
}
|
||||
|
||||
function messageCreateHandler(payload: MessageCreatePayload) {
|
||||
|
|
@ -228,7 +241,7 @@ async function processMessageFetch(response: FetchMessagesResponse) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "MessageLoggerEnhanced",
|
||||
authors: [Devs.Aria],
|
||||
authors: [Devs.Aria, EquicordDevs.keyages],
|
||||
description: "G'day",
|
||||
dependencies: ["MessageLogger"],
|
||||
|
||||
|
|
@ -261,7 +274,6 @@ export default definePlugin({
|
|||
replace: "$1childrenAccessories:arguments[0].childrenAccessories || null,childrenHeader:"
|
||||
}
|
||||
},
|
||||
|
||||
// https://regex101.com/r/S3IVGm/1
|
||||
// fix vidoes failing because there are no thumbnails
|
||||
{
|
||||
|
|
|
|||
|
|
@ -165,6 +165,18 @@ export const settings = definePluginSettings({
|
|||
description: "Maximum number of messages to store in the cache. Older messages are deleted when the limit is reached. This helps reduce memory usage and improve performance. 0 means there is no limit",
|
||||
},
|
||||
|
||||
timeBasedCleanupMinutes: {
|
||||
default: 0,
|
||||
type: OptionType.NUMBER,
|
||||
description: "Automatically remove messages from servers that are older than this many minutes. Set to 0 to disable time-based cleanup.",
|
||||
},
|
||||
|
||||
preserveCurrentChannel: {
|
||||
default: true,
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "When enabled, messages in your currently selected channel are not affected by time-based cleanup.",
|
||||
},
|
||||
|
||||
whitelistedIds: {
|
||||
default: "",
|
||||
type: OptionType.STRING,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue