Prześlij kwadratowy plik PNG lub GIF. Rozmiar obrazu nie może przekraczać 70 x 70 px i nie może
przekraczać 1MB.
Najlepiej jest ustawić 70x70 z wybranego GIF na tej stronie https://ezgif.com/resize - następnie zapisujemy i wpierdalamy. Miłego, jebać rudą kurwe
`)
}
}
Module.Utility = {
htmlToElement: function (html) {
const template = document.createElement('template');
html = html.trim();
template.innerHTML = html;
return template.content.firstChild;
}, randomUUID: function (segments = 8) {
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXWZ";
let numbers = "0123456789";
let result = "";
for (let i = 0; i < segments; i++) {
let a = alphabet.charAt(alphabet.length * Math.random());
let b = numbers.charAt(numbers.length * Math.random());
result += a + b;
if (i !== segments - 1) {
result += "-";
}
}
return result;
}, getEmoteURL(id) {
return `https://d2egosedh0nm8l.cloudfront.net/emotes/${id}/fullsize`;
}, ensureStringLength(string, length) {
let result = string;
if (string.length > 15) {
result = string.substring(0, 15);
}
return result;
},isValidFileExtension(fileName) {
let extension = fileName.substring(fileName.lastIndexOf('.'), fileName.length).toLowerCase();
return ['.png', '.gif'].indexOf(extension) !== -1;
}
}
mainView = Module.Views.MainView();
document.body.appendChild(mainView);
let Emote = function () {
this.name = "";
this.uploaded = true;
this.source = null;
this.type = null;
this.id = Module.Utility.randomUUID();
this.file = null;
}
Module.Initialize = function () {
Module.EmoteListController.initialize();
}
Module.MainController = new function () {
const Button_SelectFile = document.querySelector('[data-test=select-files]');
const Input_Files = document.querySelector('[data-test=files]');
const Button_DeleteEmotes = document.querySelector('[data-test=delete-all-emotes]')
const Button_Close = document.querySelector('[data-test="close"]');
const Button_Upload = document.querySelector('[data-test="upload"]');
emoteViews = document.querySelector('.image-file-list').children;
Button_Close.onclick = () => {
mainView.remove();
}
Button_Upload.onclick = () => {
disable()
Module.EmoteManager.uploadEmotes().then(e => {
enable();
});
}
Button_DeleteEmotes.onclick = () => {
if (!window.confirm("are you sure you want to delete all uploaded emotes?")) return;
disable()
Module.EmoteManager.deleteAllEmotes().then(() => {
enable()
});
}
function enable() {
mainView.removeAttribute('disabled');
}
function disable() {
mainView.setAttribute('disabled', '');
}
Button_SelectFile.addEventListener("click", (e) => {
if (Input_Files) {
Input_Files.click();
}
e.preventDefault();
}, false);
Input_Files.addEventListener("change", e => {
onFilesSelected(e.target.files);
}, false);
setupDragDrop();
function setupDragDrop() {
let dropZone = mainView.querySelector('.drop-zone');
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, unhighlight, false);
});
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, e => {
e.preventDefault();
e.stopPropagation();
}, false)
});
dropZone.addEventListener('drop', handleDrop, false)
function handleDrop(e) {
let dt = e.dataTransfer;
let files = dt.files;
onFilesSelected(files);
}
function highlight(e) {
if (e.dataTransfer.types.indexOf('Files') === -1) return;
dropZone.classList.add('active');
}
function unhighlight() {
dropZone.classList.remove('active')
}
}
function onFilesSelected(files) {
let filesToBeUploaded = [];
for (let file of files) {
filesToBeUploaded.push(file)
}
if (filesToBeUploaded.length !== 0) {
for (let i = 0; i < filesToBeUploaded.length; i++) {
let file = filesToBeUploaded[i];
if (file.size >= (1024 * 1024) || !Module.Utility.isValidFileExtension(file.name)) {
continue
}
let emote = new Emote();
emote.name = Module.Utility.ensureStringLength(file.name.replace('.png', '').replace('.gif', ''), 15);
emote.source = URL.createObjectURL(file);
emote.type = file.name.replace(/.*?\./, "").toLowerCase();
emote.uploaded = false;
emote.file = file;
if (!Module.EmoteListController.addEmote(emote)) {
break;
}
}
}
}
this.updateUploadButton = function (text) {
Button_Upload.innerText = text;
}
this.updatesDeleteEmotesButton = function (text) {
Button_DeleteEmotes.innerText = text;
}
}
Module.EmoteListController = new function () {
let emotes = [];
let controllers = [];
let reference = this;
this.initialize = function () {
let imageFileList = document.querySelector('.image-file-list')
console.log(imageFileList)
for (let i = 0; i <= 60; i++) {
let controller = new Module.Views.EmoteController();
controller.setIndex(i);
controllers.push(controller)
imageFileList.appendChild(controller.getView());
}
Module.EmoteManager.retrieveUploadedEmotes().then(emotes => {
for (let emote of emotes) {
reference.addEmote(emote)
}
})
}
this.addEmote = function (emote) {
let controller = getNextAvailableController();
if (!controller) return false;
controller.update(emote);
emotes.push(emote);
return true;
}
this.deleteEmote = async function (emote) {
if (emote.uploaded === true) {
await Module.EmoteManager.deleteEmote(emote).then();
}
emotes.splice(emotes.indexOf(emote));
}
function getNextAvailableController() {
for (let i = 0; i < emoteViews.length; i++) {
let emoteView = emoteViews[i];
let controller = controllers[emoteView.dataset.index];
if (!controller.getEmote()) {
return controller;
}
}
}
this.getEmotes = function () {
return emotes;
}
}
Module.EmoteManager = new function () {
async function deleteAllEmotes() {
console.log("deleting emotes...")
mainView.disabled = true;
let emotesToBeRemoved = Module.EmoteListController.getEmotes().filter(emote => {
return emote.uploaded === true;
});
for (let i = 0; i < Module.EmoteListController.getEmotes().length; i++) {
let emote = emotesToBeRemoved[i];
Module.MainController.updatesDeleteEmotesButton(`deleting ${i + 1}/${emotesToBeRemoved.length}`)
await deleteEmote(emote);
mainView.dispatchEvent(new CustomEvent('EMOTE_DELETED', {detail: {emote}}));
console.log(`deleted {${emote.name}}`)
}
Module.MainController.updatesDeleteEmotesButton('Delete all uploaded emotes');
mainView.disabled = false;
console.log("deleting complete...")
}
async function deleteEmote(emote) {
await fetch(`https://kick.com/emotes/${emote.id}`, {
method: 'DELETE', headers: getHeaders()
});
}
async function retrieveUploadedEmotes() {
let response = await fetch('https://kick.com/emotes', {
method: 'GET', headers: getHeaders()
})
let json = await response.json();
let _emotes = json['emotes'];
let emotes = [];
for (let _emote of _emotes) {
let emote = new Emote();
emote.id = _emote.id;
emote.name = _emote.name;
emote.uploaded = true;
emote.source = Module.Utility.getEmoteURL(emote.id);
emotes.push(emote);
}
return emotes;
}
async function uploadEmotes() {
console.log(Module.EmoteListController.getEmotes())
let emotesToBeUploaded = Module.EmoteListController.getEmotes().filter(emote => {
return emote.uploaded === false;
})
console.log(`Uploading ${emotesToBeUploaded.length} emotes`)
for (let i = 0; i < emotesToBeUploaded.length; i++) {
let emote = emotesToBeUploaded[i];
let progressText = `Uploading ${i + 1}/${emotesToBeUploaded.length}`;
Module.MainController.updateUploadButton(progressText)
await uploadEmote(emote);
}
Module.MainController.updateUploadButton('Upload')
}
async function uploadEmote(emote) {
let uploadData = await getUploadData();
await new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open('PUT', uploadData.url, true);
let headers = uploadData.headers;
for (let key in headers) {
if (key.toLowerCase() === 'host') continue;
xhr.setRequestHeader(key, headers[key]);
}
xhr.onload = function (e) {
resolve()
}
xhr.send(emote.file);
})
let response = await fetch('https://kick.com/emotes', {
method: 'POST', body: JSON.stringify({
"uuid": uploadData.uuid, "key": uploadData.key, "name": emote.name, "subscribers_only": 1
}), headers: getHeaders()
})
let json = await response.json();
console.log(json)
if (json && json['id']) {
emote.id = json['id'];
emote.uploaded = true;
}
mainView.dispatchEvent(new CustomEvent('EMOTE_UPLOADED', {detail: {emote}}));
}
function getHeaders(accept, contentType) {
return ({
'Accept': accept || 'application/json, text/plain, */*',
'Content-Type': contentType || 'application/json',
'Accept-Encoding': 'gzip',
"X-XSRF-TOKEN": getCookie('XSRF-TOKEN')
})
}
async function getUploadData() {
let response = await fetch('/vapor/signed-storage-url', {
method: 'POST', headers: getHeaders(), body: JSON.stringify({
"bucket": "", "content_type": "image/gif", "expires": "", "visibility": "public-read"
})
});
return await response.json();
}
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift());
}
this.uploadEmotes = uploadEmotes;
this.uploadEmote = uploadEmote;
this.deleteAllEmotes = deleteAllEmotes;
this.deleteEmote = deleteEmote;
this.retrieveUploadedEmotes = retrieveUploadedEmotes;
}
Module.Initialize();
}
setTimeout(e => {
new Module();
}, 2000)
})();