View user's profile from chat user script

  • 🔧 Actively working on site again.

PoonBrosAreValid

kiwifarms.net
Joined
Sep 15, 2023
The annoying thing about chat is you can't easily view the profiles of the people you are chatting with.
All the data needed to build the link is there, it just isn't used. It doesn't use any special features so should work on all userscript extensions.

JavaScript:
// ==UserScript==
// @name         Kiwifarms Profile Links Chat
// @namespace    http://tampermonkey.net/
// @version      2024-10-08
// @description  Adds a link to users profiles on the Kiwifarms chat.
// @author       PoonBrosAreValid
// @match        https://kiwifarms.st/chat/*
// @match        https://kiwifarms.st/
// @icon         https://kiwifarms.st/styles/custom/logos/kiwi_square.og.png
// @grant        none
// ==/UserScript==

const chat = {
    get frame() {
        return document.querySelector("#rust-shim")
    },

    get document() {
        return this.frame.contentWindow.document
    },

    buildUserUrl(id) {
        const origin = new URL(location.href).origin
        return `${origin}/members/${id}`
    },

    /** Formatted like "chat-activity-{{USER_ID}}" */
    urlFromActivityId(activityId) {
        const userId = activityId.replace('chat-activity-', '')
        return this.buildUserUrl(userId)
    },

    /** Formatted like "/blah/blah/blah/{{USER_ID}}.jpg" */
    urlFromMessageAvatarSrc(src) {
        const path = new URL(location.origin + src).pathname
        const pieces = path.split('/')
        const userId = pieces[pieces.length - 1].replace('.jpg', '')
        return this.buildUserUrl(userId)
    },

    /** Create and click a fake link to avoid popup warnings */
    openProfile(url) {
        const fakeLink = document.createElement('a')
        fakeLink.href = url
        fakeLink.target = '_blank'
        fakeLink.click()
    },

    addAvatarClick(avatar, url) {
        if (avatar.dataset.hasListener) return

        avatar.style.cursor = 'pointer'
        avatar.dataset.hasListener = 'true'
        avatar.classList.add('clickable-avatar')
        avatar.addEventListener('click', (_) => {
            chat.openProfile(url)
        })
    },

    observe(selector, callback) {
        const observerOptions = {
            childList: true,
            subtree: true,
        }

        const elem = chat.document.querySelector(selector)
        const observer = new MutationObserver(callback, observerOptions)
        observer.observe(elem, observerOptions)
    },
}

function onMembersChange(event) {
    const unfilledLinks = chat.document.querySelectorAll('.chat .activity a:not([href])')

    for (const link of unfilledLinks) {
        const activityId = link.parentElement.id
        const profileUrl = chat.urlFromActivityId(activityId)
        link.href = profileUrl
        link.style.textDecoration = 'none'
        link.style.color = "white"
        link.target = '_blank'

        const username = link.innerText
        link.title = `Go to ${username}'s profile`

        const avatar = link.parentElement.querySelector('.avatar')
        if (avatar) {
            chat.addAvatarClick(avatar, profileUrl)
        }
    }
}

function onMessagesChange(event) {
    const avatars = chat.document.querySelectorAll('.chat-message .avatar:not(.clickable-avatar)')

    for (const avatar of avatars) {
        const url = chat.urlFromMessageAvatarSrc(avatar.src)
        chat.addAvatarClick(avatar, url)
    }
}

function init() {
    // Try to grab the frame and observe the chat
    let timerInit = setInterval(() => {
        if (!chat.frame) return
        if (chat.document.readyState !== 'complete') return

        chat.observe('#chat-activity', onMembersChange)
        chat.observe('#chat-messages', onMessagesChange)
        clearInterval(timerInit)
    }, 500)
}
init()
 
Last edited:
this seems like the exact kind of things a faggot genchat user would need
 
Users' PFP's are named after their IDs, which means that if I right click their PFP and "open image in another tab", I just need to put after the Kiwifarms domain: "/members/ID" and that's it.

But cool anyways.
 
NOW I SHALL BE ABLE TO DOX EVERY CHAT PARTICIPANT ... I JUST NEED TO GET UNBANNED FROM CHAT. WHEN THAT HAPPENS, WATCH OUT. I WILL ABUSE THE ABSOLUTE POWER OF THIS USER SCRIPT! I WILL ABUSE THE ABSOLUTE POWER OF THIS USER SCRIPT!! REMEMBER, SHIT ROLLS DOWNHILL UNTIL IT LANDS ON MY CHEST. —MARK
 
Back