Skip to content

Instantly share code, notes, and snippets.

@mikhailsdv
Last active November 26, 2022 18:14
Show Gist options
  • Save mikhailsdv/7801a83cc8aac43d522fc2ca179d7836 to your computer and use it in GitHub Desktop.
Save mikhailsdv/7801a83cc8aac43d522fc2ca179d7836 to your computer and use it in GitHub Desktop.
Send any image to your Black Hole by pressing Ctrl + Q
// ==UserScript==
// @name Black Hole image downloader
// @version 1.0
// @description Send any image to your Black Hole by pressing Ctrl + Q
// @author https://github.com/mikhailsdv
// @license MIT
// @match https://*/*
// @match http://*/*
// @icon https://iili.io/HFm563g.png
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
;(function () {
"use strict"
const downloadImage =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFyWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNy4xLWMwMDAgNzkuYjBmOGJlOSwgMjAyMS8xMi8wOC0xOToxMToyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIzLjIgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0xMS0yNlQyMDo1OTowNiswNjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjItMTEtMjZUMjE6MDI6MzIrMDY6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMTEtMjZUMjE6MDI6MzIrMDY6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjhlNzhkN2E5LTI1ZmEtY2U0Ni05ZWMxLTRkYzlkODYxYmU5NiIgeG1wTU06RG9jdW1lbnRJRD0i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"
const loadingImage =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFyWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNy4xLWMwMDAgNzkuYjBmOGJlOSwgMjAyMS8xMi8wOC0xOToxMToyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIzLjIgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0xMS0yNlQyMDo1OTowNiswNjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjItMTEtMjZUMjE6NDU6NTYrMDY6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMTEtMjZUMjE6NDU6NTYrMDY6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOmQ0ZDI5NzFlLTRiMzAtZjk0ZC1iMmNjLTNjZGZhY2Q3M2ViNyIgeG1wTU06RG9jdW1lbnRJRD0i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"
const successImage =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFyWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNy4xLWMwMDAgNzkuYjBmOGJlOSwgMjAyMS8xMi8wOC0xOToxMToyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIzLjIgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0xMS0yNlQyMDo1OTowNiswNjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjItMTEtMjZUMjE6NDQ6MzIrMDY6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMTEtMjZUMjE6NDQ6MzIrMDY6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjU3N2RhZGQyLWM4ZWMtYjM0Ni1iNmJlLTRlZDcyZTk0YWFlZCIgeG1wTU06RG9jdW1lbnRJRD0i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"
let count = 0
const isValidIntegrationUrl = url => /^https?:\/\/.+?\/integration\/[A-Za-z0-9]+$/.test(url)
const removeButtons = () => {
Array.from(document.getElementsByClassName("bh-button")).forEach(element =>
element.remove()
)
document.getElementById("bh-change-url").remove()
count = 0
}
const saveFile = async (url, button) => {
button.style.backgroundImage = `url("${loadingImage}")`
const integrationURL =
GM_getValue("integration-url") ||
prompt("Set your Integration URL. This is one-time action.")
if (!integrationURL || !isValidIntegrationUrl(integrationURL)) {
return alert("Wrong Integration URL!")
}
GM_setValue("integration-url", integrationURL)
fetch(integrationURL, {
method: "POST",
body: JSON.stringify({url}),
headers: {"Content-Type": "application/json"},
})
.then(response => response.json())
.then(data => {
const {status, error, url} = data
if (error) {
button.style.backgroundImage = `url("${downloadImage}")`
return alert("Error: " + error)
}
button.style.backgroundImage = `url("${successImage}")`
setTimeout(() => {
removeButtons()
}, 2000)
})
}
const listenCombination = ({combination, callback, once, element = window}) => {
let combinationMemory = []
let emptyTimeout
const onKeyUp = e => {
const code = e.metaKey ? "MetaKey" : e.code
combinationMemory = combinationMemory.filter(item => item !== code)
emptyTimeout = setTimeout(() => {
combinationMemory = []
}, 500)
}
const onKeyDown = e => {
const code = e.metaKey ? "MetaKey" : e.code
clearTimeout(emptyTimeout)
if (!combinationMemory.includes(code)) {
combinationMemory.push(code)
}
if (combination.every((item, index) => item === combinationMemory[index])) {
if (once) {
element.removeEventListener("keydown", onKeyDown)
element.removeEventListener("keyup", onKeyUp)
}
callback()
}
}
element.addEventListener("keyup", onKeyUp)
element.addEventListener("keydown", onKeyDown)
}
const appendButton = ({width, height, top, left, element, url, fileName}) => {
const button = document.createElement("button")
const size = 20
let styles
if (!document.getElementById("#bh-button-styles")) {
styles = document.createElement("style")
styles.id = "bh-button-styles"
styles.innerHTML = `
.bh-button {
z-index: 99999;
position: absolute;
border: none;
outline: none;
padding: 0;
margin: 0;
cursor: pointer;
background-color: white;
background-size: 100%;
background-position: center;
background-repeat: no-repeat;
background-image: url("${downloadImage}");
border-radius: 100%;
height: ${size}px;
min-width: ${size}px;
min-height: ${size}px;
width: ${size}px;
box-shadow: 0 0 0 rgba(0, 0, 0, 0.3);
transition: all .2s ease-out;
}
.bh-button:hover {
transform: scale(1.1);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.bh-button:active {
transform: scale(1.05);
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
}
#bh-change-url {
position: fixed;
bottom: 14px;
left: 50%;
border: none;
transform: translateX(-50%);
z-index: 99999;
height: 54px;
padding: 14px 22px;
font-size: 16px;
font-weight: 500;
color: white;
cursor: pointer;
font-family: "Roboto", "Arial", sans-serif;
overflow: hidden;
user-select: none;
white-space: nowrap;
background-color: #ef39a8;
box-shadow: 0 2px 10px -2px #0000008c;
border-radius: 8px;
outline: none;
transition: background-color .2s ease-out;
}
#bh-change-url:hover {
background-color: #bd399c;
}
`
document.head.appendChild(styles)
}
button.style.top = top + height / 2 - size / 2 + "px"
button.style.left = left + width / 2 - size / 2 + "px"
button.classList.add("bh-button")
button.addEventListener("click", e => {
e.preventDefault()
e.stopImmediatePropagation()
e.stopPropagation()
saveFile(url, button)
})
element.prepend(button)
}
const getFileName = url => {
if (/^data:image\/([a-zA-Z0-9]+)/.test(url)) {
const extension = url.match(/^data:image\/([a-zA-Z0-9]+)/)
return "image." + extension[1]
} else {
const match = url.match(/^.*\/(.+?)(\?.+?)?$/)
if (match && match[1]) {
return match[1]
} else {
return "image.jpg"
}
}
}
const appendChangeUrlButton = () => {
const button = document.createElement("button")
button.id = "bh-change-url"
button.innerHTML = "Change Integration URL"
button.addEventListener("click", e => {
e.preventDefault()
e.stopImmediatePropagation()
e.stopPropagation()
const integrationURL = prompt("Set your Integration URL. This is one-time action.")
if (isValidIntegrationUrl(integrationURL)) {
GM_setValue("integration-url", integrationURL)
alert("Integration URL has been changed!")
} else {
alert("Wrong Integration URL!")
}
})
document.body.appendChild(button)
}
const callback = () => {
count++
if (count % 2 === 0) {
return removeButtons()
}
appendChangeUrlButton()
Array.from(document.querySelectorAll("*:not(img)")).forEach(element => {
if (element.offsetParent) {
const computedStyle = getComputedStyle(element)
const match = computedStyle.backgroundImage.match(/^url\(['"](.+?)['"]\)/)
if (match && match[1]) {
appendButton({
top: element.offsetTop,
left: element.offsetLeft,
width: element.offsetWidth,
height: element.offsetHeight,
element: element.offsetParent,
url: match[1],
fileName: getFileName(match[1]),
})
}
}
})
Array.from(document.getElementsByTagName("img")).forEach(element => {
if (element.offsetParent) {
element.setAttribute("crossorigin", "anonymous")
appendButton({
top: element.offsetTop,
left: element.offsetLeft,
width: element.offsetWidth,
height: element.offsetHeight,
element: element.offsetParent,
url: element.src,
fileName: getFileName(element.src),
})
}
})
}
listenCombination({
combination: ["MetaKey", "KeyQ"],
callback,
once: false,
})
listenCombination({
combination: ["ControlLeft", "KeyQ"],
callback,
once: false,
})
listenCombination({
combination: ["ControlRight", "KeyQ"],
callback,
once: false,
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment