Skip to content

Instantly share code, notes, and snippets.

@headzoo
Last active August 26, 2023 03:35
Show Gist options
  • Save headzoo/85528e64de6642457cb1675cf3d3be4b to your computer and use it in GitHub Desktop.
Save headzoo/85528e64de6642457cb1675cf3d3be4b to your computer and use it in GitHub Desktop.
Tampermonkey script for DiscImg.
// ==UserScript==
// @name DiscImg Upload
// @namespace http://discimg.com/
// @version 0.1
// @description Upload images to DiscImg.
// @author contact@discimg.com
// @updateURL https://gist.githubusercontent.com/headzoo/85528e64de6642457cb1675cf3d3be4b/raw/
// @downloadURL https://gist.githubusercontent.com/headzoo/85528e64de6642457cb1675cf3d3be4b/raw/
// @match https://discuit.net/*
// @icon data:image/webp;base64,UklGRuIPAABXRUJQVlA4WAoAAAAwAAAAHwAAIwAASUNDUEgMAAAAAAxITGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAAABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxiVFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2thcmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAAABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVhcwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgfCDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEcIUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWHNcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvoPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGNmI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfgmEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopajBqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4trqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZGxsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7ZzuKO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9Kf26/kv+3P9t//9BTFBILAEAAAGQo23bsUdH6iwiffaQOpVt2+xso08622qTFqPY+ca2XjzvPXyf791BREzAADT+bwghYSBYaoxcWkGgrh/ChvD8kZ1EyRCU3e0hqxHSzjtiNXEes8o7XGW3utEY34Z2AQIIdrccEMHa4C2LbeAK5tCRgSODD4cQSpE/WimB21P8Tb7881no2szs2EOQH7sLC9Mr4QHpZbmR09A8g/qY5MTEwCX8TfDR4O+dU/xUUsNXrZTAzX1oOCScH7nROHNEODt0o3F45IZwfujqySMOEefiAYMAstI4OrBTGB2DsiGcMSQK6yDtzvc4VY2cS1ZFF+d2n1M2zLnbg6S/jTGAQEk3fpKlwt0jWGuUtYD5IuvlnffYe/z0ixBSfjsPCr587HmPvcePH3uPvds3pVZQOCBAAgAAUA0AnQEqIAAkAD51LpNGpKKhoSqsAJAOiWwAnTLLsDeRfkVyyXF3cnaESoVAHsT21fiZ+kR6gPxm9SvrL/QA/gH+H9M/9bvhc8re7h7hA5q6ZL+wB6wNGjX0ER5qkKYzRSw78QmO448uNfgRgb6PekPbgAD+/YD+2YFJU0nP/+dmPMioXwuO/ml1McDToOEf5ootc/gRI6nNVXWlLXwdHQM09heYTj/3zuAcPzMwEMMbY/+0CguuVnovSOOvf/wpLLBgS8+Ql66rE3Nlh7k/c3O/CFZ40W875txo/uO3KpX+O38dvVt7pE4Q9O2gPXyNvpgNLj/50ZpG8Hsz/hmATsk5DDc6Is9r6Lxou5IIsuR0OE21eKIGAmR2+tX2aKqBi65flmo0c6O6Tms21rHNayNznQ9H9YpNIcxJPeKoGQ/y4YSXcnt1aT7koXNwwTLTsyaLCiXXHtPwxHd2l82npw7D1zDRauc5u13KSfb+K4RAgLEc8JF/uiupC4k/osvUKm2Ea3st19dJ0qFJP+83NmLiB/vwFH44e26MXK9W0+SvJt2GWFKup3y08hHT0pki+0i0ekQ+r1qwyCprDhwApRxIdHRBTy/XnhJn7hT5flpDE9fakGs2aKxSxlqZyzHPFP/ot353647Il8HYXIvUscTbFA78GyCal0N20njG0SA3zCpzpyL64In9IdEu/Bn8Cc6zjdq/4E51nOvSvrlcO9qsNm0r75CrMLq57lOnJQ1jHtylcf05WyuII1gwAAAA
// @grant none
// @require https://raw.githubusercontent.com/soufianesakhi/node-creation-observer-js/master/release/node-creation-observer-latest.js
// ==/UserScript==
(async function () {
'use strict';
NodeCreationObserver.onCreation('.page-new-post-body', (body) => {
const existing = document.querySelector('.discuit-image-downloader');
if (existing) {
existing.remove();
}
const downloader = document.createElement('div');
downloader.innerHTML = `
<div class="discuit-image-downloader">
<div style="display: flex; align-items: center; margin-bottom: 1rem">
<img
src="https://discimg.com/_next/image?url=%2Flogo.png&w=32&q=75"
alt=""
style="width: 26px; height: 26px; border-radius: 2px; margin-right: 0.5rem"
/>
<h3 style="font-size: 18px">DiscImg</h3>
</div>
<button class="discuit-image-btn" style="margin-bottom: 0.25rem;">Select Image</button>
<div style="margin-bottom: 0.25rem;">OR</div>
<input id="discuit-image-downloader__url" placeholder="Paste URL" />
<div class="discuit-image-progress" style="display: none;">Uploading...</div>
<input type="file" id="discuit-image-downloader__input" accept="image/*" />
</div>
`;
body.after(downloader);
const btn = downloader.querySelector('.discuit-image-btn');
const progress = downloader.querySelector('.discuit-image-progress');
const inputFile = downloader.querySelector('#discuit-image-downloader__input');
const inputUrl = downloader.querySelector('#discuit-image-downloader__url');
let selectionStart = 0;
const sendFile = (formData) => {
btn.disabled = true;
inputUrl.disabled = true;
progress.style.display = 'block';
fetch('https://discimg.com/api/upload', {
method: 'POST',
body: formData,
})
.then((resp) => {
resp.json().then((data) => {
const img = data.urls[0];
const textarea = document.querySelector('.page-new-post-body');
const tab = document.querySelector('.pn-tabs-item.is-selected');
const selected = tab.querySelector('svg').getAttribute('class');
// Prevents discuit from undoing the textarea changes. It doesn't work
// to simply set textarea.value = 'some value' because frontend framework
// removes it when done that way.
// @see https://stackoverflow.com/a/75430383
function setNativeValue(element, value) {
const { set: valueSetter } = Object.getOwnPropertyDescriptor(element, 'value') || {};
const prototype = Object.getPrototypeOf(element);
const { set: prototypeValueSetter } =
Object.getOwnPropertyDescriptor(prototype, 'value') || {};
if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
prototypeValueSetter.call(element, value);
} else if (valueSetter) {
valueSetter.call(element, value);
} else {
throw new Error('The given element does not have a value setter');
}
}
if (selected === 'page-new-icon-link') {
setNativeValue(textarea, img);
} else {
if (selectionStart) {
setNativeValue(
textarea,
(textarea.value =
textarea.value.substring(0, selectionStart) +
img +
textarea.value.substring(selectionStart)),
);
} else {
setNativeValue(textarea, img + textarea.value);
}
}
textarea.dispatchEvent(new Event('input', { bubbles: true }));
selectionStart = 0;
});
})
.finally(() => {
btn.disabled = false;
inputUrl.disabled = false;
inputUrl.value = '';
progress.style.display = 'none';
});
};
btn.addEventListener('click', () => {
const textarea = document.querySelector('.page-new-post-body');
selectionStart = textarea.selectionStart;
downloader.querySelector('#discuit-image-downloader__input').click();
});
inputUrl.addEventListener('input', (e) => {
try {
new URL(e.target.value);
} catch {
return;
}
const formData = new FormData();
formData.append('url', e.target.value);
sendFile(formData);
});
inputFile.addEventListener('change', (e) => {
const files = e.target.files;
if (files.length > 0) {
const formData = new FormData();
formData.append('files', files[0]);
sendFile(formData);
}
});
});
function GM_addStyle(css) {
const style =
document.getElementById('GM_addStyleBy8626') ||
(function () {
const style = document.createElement('style');
style.type = 'text/css';
style.id = 'GM_addStyleBy8626';
document.head.appendChild(style);
return style;
})();
style.textContent = css;
}
GM_addStyle(`
.discuit-image-downloader {
border: 2px dashed #ccc;
border-radius: 6px;
transition: border-color 0.2s;
padding: 20px;
margin: 1rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.discuit-image-downloader:hover {
border-color: #e0e0e0;
}
.discuit-image-downloader:focus {
outline: 0;
box-shadow: 0 0 0 5px rgba(255, 49, 186, 0.5);
}
.discuit-image-btn {
background-color: #0297db;
padding: 0.5rem 1rem;
border-radius: 6px;
transition: all 0.2s;
}
.discuit-image-btn:hover {
background-color: #12a8eb;
}
.discuit-image-btn:focus {
outline: 0;
box-shadow: 0 0 0 5px rgba(3, 174, 251, 0.51);
}
#discuit-image-downloader__input {
display: none;
}
`);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment