Skip to content

Instantly share code, notes, and snippets.

@shinmai
Last active January 31, 2025 11:04
Show Gist options
  • Save shinmai/3f7a0e2585a238735f5856d259e4824c to your computer and use it in GitHub Desktop.
Save shinmai/3f7a0e2585a238735f5856d259e4824c to your computer and use it in GitHub Desktop.
/**
* @name BrutalHonesty
* @author @shi.rip
* @description Replaces subtext with brutal honesty
* @version 0.0.3
*/
/*
CHANGELOG
0.0.1 - 250131 - initial version
0.0.2 - 250131 - add channel change handler to process already received messages
0.0.3 - 250131 - connect mutation observer on DM channels to process scrollback
*/
module.exports = class BrutalHonesty {
constructor() {
this.emojiCriteria = ["hug", "heart", "joy"]
this.replacementText = "i ain't reading all that. im happy for you tho, or sorry that happened."
const { getModule, getStore, Filters } = BdApi.Webpack
const Dispatcher = getModule(Filters.byProps("dispatch", "subscribe"), { searchExports: false })
this.Dispatcher = Dispatcher
this.getChannel = getStore("ChannelStore").getChannel
this.me = BdApi.findModuleByProps("getCurrentUser").getCurrentUser().id
this.observer = null
}
isOnlyEmoji = message => {
for (const child of message.children) {
if(!child.tagName === "SPAN") return false
if (child.querySelector("img[data-type='emoji']")) continue
else if (/^\s*$/.test(child.textContent)) continue
return false
}
return true
}
checkEmojiCriteria = message => {
for (const img of message.querySelectorAll("img[data-type='emoji']")) {
const emojiName = img.getAttribute("data-name")?img.getAttribute("data-name"):img.alt
if (!emojiName || !this.emojiCriteria.some(criteria => (emojiName.includes(criteria)))) return false
}
return true
}
processMessages = _ => {
for (const messageElement of document.querySelectorAll("[id^='message-content-']")) {
if (messageElement.closest("[data-author-id]")?.dataset.authorId === this.me) continue
if(!this.isOnlyEmoji(messageElement) || !this.checkEmojiCriteria(messageElement)) continue
messageElement.innerHTML = `<span>${this.replacementText}</span>`
}
}
messageCreateListener = e => {
if (e.message.channel_type !== 1 || e.message.author.id === BdApi.findModuleByProps("getCurrentUser").getCurrentUser().id) return
setTimeout(_ => {
const messageElement = document.getElementById(`message-content-${e.message.id}`)
if(!messageElement || !this.isOnlyEmoji(messageElement) || !this.checkEmojiCriteria(messageElement)) return
messageElement.innerHTML = `<span>${this.replacementText}</span>`
}, 150)
}
channelSelectListener = e => {
if (this.observer) {
this.observer.disconnect()
this.observer = null
}
setTimeout(_ => {
const channel = this.getChannel(e.channelId)
if (channel?.type !== 1) return
this.processMessages()
const chatContainer = document.querySelector("[data-list-id='chat-messages']")
if (chatContainer && !this.observer) {
this.observer = new MutationObserver((mutations) => {
for (const mutation of mutations)
if (mutation.type === "childList" && mutation.addedNodes.length > 0) this.processMessages()
})
this.observer.observe(chatContainer, { childList: true, subtree: true })
}
}, 150)
}
start() {
this.Dispatcher.subscribe("MESSAGE_CREATE", this.messageCreateListener)
this.Dispatcher.subscribe("CHANNEL_SELECT", this.channelSelectListener)
}
stop() {
this.Dispatcher.unsubscribe("MESSAGE_CREATE", this.messageCreateListener)
this.Dispatcher.unsubscribe("CHANNEL_SELECT", this.channelSelectListener)
if (this.observer) {
this.observer.disconnect()
this.observer = null
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment