Skip to content

Instantly share code, notes, and snippets.

@spddl
Created August 16, 2026 18:12
Show Gist options
  • Select an option

  • Save spddl/ee4854873c1cabd4caf76d18f8af38a8 to your computer and use it in GitHub Desktop.

Select an option

Save spddl/ee4854873c1cabd4caf76d18f8af38a8 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name counter-strike.net
// @namespace script
// @icon https://www.counter-strike.net/favicon.ico
// @version 1.0.0
//
// @match https://www.counter-strike.net/vacnet/clips*
// @grant none
//
// @author spddl
// @description
// ==/UserScript==
;(function () {
'use strict'
function ensureDummyElements () {
if (!document.getElementById('showDetailsModal')) {
const dummy = document.createElement('div')
dummy.id = 'showDetailsModal'
dummy.style.display = 'none'
;(document.body || document.documentElement).appendChild(dummy)
}
}
function debounce (func, wait) {
let timeout
return function (...args) {
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(this, args), wait)
}
}
const css = `
.video-column { resize: horizontal; overflow: hidden; flex: 0 0 auto !important; max-width: none !important; }
.videocontainer, .video-js { width: 100% !important; height: auto !important; aspect-ratio: 16 / 9 !important; }
.verdict-column { container-type: inline-size; }
.verdict-desc, .verdictbutton label { font-size: clamp(10px, 1.2cqw + 5px, 15px) !important; }
.submitbuttons-row { display: flex; gap: 8px; align-items: center; justify-content: center; }
.verdict-column, .verdicts-container, .verdictbutton { user-select: none; -webkit-user-select: none; }
`
function injectCSS () {
if (document.getElementById('cs2-overwatch-custom-css')) return
const styleEl = document.createElement('style')
styleEl.id = 'cs2-overwatch-custom-css'
styleEl.textContent = css
;(document.head || document.documentElement).appendChild(styleEl)
}
let isDragging = false
let dragSelectInitialized = false
function selectRadioFromTarget (target) {
if (!target) return
const verdictBtn = target.closest('.verdictbutton') || target.closest('label') || target.closest('.verdict-option')
if (!verdictBtn) return
const radio = verdictBtn.querySelector('input[type="radio"]') || (verdictBtn.tagName === 'INPUT' && verdictBtn.type === 'radio' ? verdictBtn : null)
if (radio && !radio.checked) {
radio.checked = true
radio.dispatchEvent(new Event('change', { bubbles: true }))
radio.dispatchEvent(new Event('click', { bubbles: true }))
}
}
function initDragSelect () {
if (dragSelectInitialized) return
dragSelectInitialized = true
document.addEventListener('dragstart', (e) => {
if (e.target.closest('.verdict-column') || e.target.closest('.verdictbutton') || e.target.closest('.verdicts-container')) {
e.preventDefault()
}
})
document.addEventListener('mousedown', (e) => {
if (e.button !== 0) return
const target = e.target
if (target.closest('.verdictbutton') || target.closest('.verdict-column') || target.closest('.verdicts-container')) {
isDragging = true
selectRadioFromTarget(target)
}
})
document.addEventListener('mousemove', (e) => {
if (!isDragging) return
if (e.buttons !== 1) {
isDragging = false
return
}
const elem = document.elementFromPoint(e.clientX, e.clientY)
selectRadioFromTarget(elem)
})
document.addEventListener('mouseup', () => {
isDragging = false
})
}
let shortcutsInitialized = false
function initKeyboardShortcuts () {
if (shortcutsInitialized) return
shortcutsInitialized = true
document.addEventListener('keydown', (e) => {
if (['INPUT', 'TEXTAREA', 'SELECT'].includes(e.target.tagName) && e.target.type !== 'radio') {
return
}
if (e.key === '1' || e.code === 'Numpad1') {
setAllVerdicts('positive')
} else if (e.key === '2' || e.code === 'Numpad2') {
setAllVerdicts('skip')
} else if (e.key === '3' || e.code === 'Numpad3') {
setAllVerdicts('negative')
} else if (e.key === 'Enter') {
const proceedBtn = document.getElementById('submitVerdictButton')
if (proceedBtn && proceedBtn.style.display !== 'none') {
e.preventDefault()
proceedBtn.click()
}
}
})
}
function initVideoResizePersistence () {
const videoCol = document.querySelector('.video-column')
if (!videoCol || videoCol.dataset.resizeObserved === '1') return
videoCol.dataset.resizeObserved = '1'
const savedWidth = localStorage.getItem('cs2_overwatch_video_width')
if (savedWidth) {
videoCol.style.width = savedWidth
}
const saveWidthDebounced = debounce((width) => {
localStorage.setItem('cs2_overwatch_video_width', width + 'px')
}, 250)
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const width = entry.borderBoxSize ? entry.borderBoxSize[0].inlineSize : entry.contentRect.width
if (width > 0) {
saveWidthDebounced(width)
}
}
})
resizeObserver.observe(videoCol)
}
function setAllVerdicts (value) {
const categories = ['aimassist', 'wallhack', 'autobhop', 'bot']
categories.forEach((cat) => {
const radio = document.querySelector(`input[name="${cat}"][value="${value}"]`)
if (radio) {
radio.checked = true
radio.dispatchEvent(new Event('change', { bubbles: true }))
}
})
}
function injectButtons () {
ensureDummyElements()
initVideoResizePersistence()
initDragSelect()
initKeyboardShortcuts()
const submitButtons = document.getElementById('submitbuttons')
if (!submitButtons || document.getElementById('backbutton') || submitButtons.querySelector('.submitbuttons-row')) return
const proceedButton = submitButtons.querySelector('#submitVerdictButton')
if (!proceedButton) return
const onclickAttr = proceedButton.getAttribute('onclick') || ''
if (onclickAttr.includes('SubmitLabels')) return
const row = document.createElement('div')
row.className = 'submitbuttons-row'
row.style.marginTop= '5px'
const leftBtn = document.createElement('button')
leftBtn.type = 'button'
leftBtn.className = 'submitverdictbutton'
leftBtn.innerText = 'Cheater'
leftBtn.style.backgroundColor = '#4D4D4D'
leftBtn.style.color = '#FFC20A'
leftBtn.onclick = (e) => {
e.preventDefault()
setAllVerdicts('positive')
}
const rightBtn = document.createElement('button')
rightBtn.type = 'button'
rightBtn.className = 'submitverdictbutton'
rightBtn.innerText = 'Innocent'
rightBtn.style.backgroundColor = '#4D4D4D'
rightBtn.style.color = '#529cd8'
rightBtn.onclick = (e) => {
e.preventDefault()
setAllVerdicts('negative')
}
row.appendChild(leftBtn)
row.appendChild(proceedButton)
row.appendChild(rightBtn)
submitButtons.innerHTML = ''
submitButtons.appendChild(row)
}
function init () {
injectCSS()
ensureDummyElements()
injectButtons()
new MutationObserver(injectButtons).observe(document.documentElement, {
childList: true,
subtree: true
})
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init)
} else {
init()
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment