Maybe click on the red x at the top so that only errors are shown; that’s a lot of warnings
Or maybe that doesn’t filter them? You can also open up the sidebar and filter there

Maybe click on the red x at the top so that only errors are shown; that’s a lot of warnings
Or maybe that doesn’t filter them? You can also open up the sidebar and filter there

Ok, I don’t see any errors…
Ok. If you go back to the cache, then add an emote, does the cache update accordingly?
Sorry for making you do so much, I am at a loss as for what would cause this
It’s the top one that increases whenever I try to add one
I don’t understand what you mean by that
:tj3stargoodegg:
:tj3stargoodegg:
My cache does not seem to increase
@Kumirei the one marked with 11 on here.
Thank you for working on this. I don’t know what to do about it 
Ah, I meant if you go back to the Applications tab (then local storage → Emoter), does the data in there update? It should get added right away as you add an emote using the “!emote new” command
Yes, that’s what I checked, but it doesn’t change.
Have you tried removing and reinstalling the script ?
I’ll try now
:tj3stargoodegg:
dio filling characters
No dice ):
Jerry failes to use script
I should probably make at least hyphens and underscores work (but right now only letters and digits work)
Hmm, it was more that I hadn’t hard refreshed ![]()
Now I just need to import all my Discord emojis…
By this I assume that the script actually did somthing when you wrote the command, right?
Yes, it converted the input text into an icon, but no icon and didn’t save it to the list
Ok. Let’s try some logging. Replace your script with this (and refresh the page!)
// ==UserScript==
// @name Wanikani Forums: Emoter
// @namespace http://tampermonkey.net/
// @version 1.1.7
// @description Custom emote handler
// @author Kumirei
// @include https://community.wanikani.com/*
// @grant none
// ==/UserScript==
;(function () {
// Wait until the save function is defined
const i = setInterval(tryInject, 100)
// Inject if the save function is defined
function tryInject() {
const old_save = window.require('discourse/controllers/composer').default.prototype.save
const old_cook = window.require('pretty-text/engines/discourse-markdown-it').cook
if (old_save) {
clearInterval(i)
inject(old_save, old_cook)
}
}
// Wrap the save function with our own function
function inject(old_save, old_cook) {
const new_save = async function (t) {
const composer = document.querySelector('textarea.d-editor-input') // Reply box
composer.value = await emote(composer) // Modify message
composer.dispatchEvent(new Event('change', { bubbles: true, cancelable: true })) // Let Discourse know
old_save.call(this, t) // Call regular save function
}
const new_cook = async function (raw, ops) {
return old_cook(emote_cooker(raw), ops)
}
window.require('discourse/controllers/composer').default.prototype.save = new_save // Inject
window.require('pretty-text/engines/discourse-markdown-it').cook = new_cook // Inject
}
// Handles emotifications when saving
function emote(composer) {
const cache = get_local()
const original_text = composer.value
// Get draft text, without quotes
// let text = original_text.replace(/\[quote((?!\[\/quote\]).)*\[\/quote\]/gis, '')
// Replace stuffs?!
text = replace_stuffs(original_text, cache)
return text
}
// Change the preview
function emote_cooker(raw) {
const cache = get_local()
const command_template = /!emote\s+(\w+)\s+(\w+)\s+(["“„](\S+)["”])?/i
const composer = document.querySelector('textarea.d-editor-input') // Reply box
const command = composer.value.match(command_template)
// Do things if commands are present
if (command) process_command(command, composer, command_template, cache)
// Replace stuffs?!
raw = replace_stuffs(raw, cache)
// Update cache
set_local(cache)
console.log('Test 2:', localStorage.getItem('Emoter'));
return raw
}
// Handles commands
function process_command(command, composer, command_template, cache) {
const emotes = cache.emotes
let [_, word, name, __, value] = command
word = word.toLowerCase()
switch (word) {
case 'new': // :NAME:
if (value) emotes[name] = { url: value }
console.log('Test 1:', name, emotes[name], value);
break
case 'size': // :NAME:
if (value && !value.match(/\d+(x\d+)?/i)) break
if (name === 'default') cache.size = value
case 'url': // :NAME:
if (value && emotes[name]) emotes[name][word] = value
break
case 'remove': // :NAME:delete emotes[name]
break
case 'rename': // :NAME:
if (value && emotes[name]) delete Object.assign(emotes, { [value]: emotes[name] })[name]
break
}
if (value || word === 'remove') {
composer.value = composer.value.replace(command_template, ':$2:')
composer.dispatchEvent(new Event('change', { bubbles: true, cancelable: true })) // Let Discourse know
}
}
// Creates an image for the emote
function get_image(url, name, size) {
let w = (h = size)
if (size.match && size.match(/\d+x\d+/i)) [w, h] = size.split('x')
return `<abbr title="${name}"></abbr>`
}
// Replaces :emotes: with images and Image|Name
-|-
<abbr title="think"></abbr>|think
<abbr title="shocked"></abbr>|shocked
<abbr title="lain"></abbr>|lain
<abbr title="winko"></abbr>|winko
<abbr title="akkowoah"></abbr>|akkowoah
<abbr title="eyes2"></abbr>|eyes2
<abbr title="arage"></abbr>|arage
<abbr title="neat"></abbr>|neat
<abbr title="akko"></abbr>|akko
<abbr title="B"></abbr>|B
<abbr title="pout"></abbr>|pout
<abbr title="wave"></abbr>|wave
<abbr title="brofive"></abbr>|brofive
<abbr title="blobfive"></abbr>|blobfive
<abbr title="yui"></abbr>|yui
<abbr title="kms"></abbr>|kms
<abbr title="kannakms"></abbr>|kannakms
<abbr title="blobkms"></abbr>|blobkms
<abbr title="blobparty"></abbr>|blobparty
<abbr title="vegans1"></abbr>|vegans1
<abbr title="vegans2"></abbr>|vegans2
<abbr title="hehe"></abbr>|hehe</table> with the list
function replace_stuffs(text, cache) {
text = replace_emotes(text, cache)
text = replace_list(text, cache)
return text
}
// Replaces :emotes: with images
function replace_emotes(text, cache) {
return text.replace(/:(\w+):/g, (original, word) => {
const emote = cache.emotes[word]
return emote ? get_image(emote.url, word, emote?.size || cache.size) : original
})
}
// Create a table of the available emotes
function replace_list(raw, cache) {
const list = Object.entries(cache.emotes)
.map((e) => get_image(e[1].url, e[0], e[1].size || cache.size).replace('|', `\\|`) + `|` + e[0])
.join('\n')
const table = `Image|Name\n-|-\n${list}</table>`
return raw.replace(/Image|Name
-|-
<abbr title="think"></abbr>|think
<abbr title="shocked"></abbr>|shocked
<abbr title="lain"></abbr>|lain
<abbr title="winko"></abbr>|winko
<abbr title="akkowoah"></abbr>|akkowoah
<abbr title="eyes2"></abbr>|eyes2
<abbr title="arage"></abbr>|arage
<abbr title="neat"></abbr>|neat
<abbr title="akko"></abbr>|akko
<abbr title="B"></abbr>|B
<abbr title="pout"></abbr>|pout
<abbr title="wave"></abbr>|wave
<abbr title="brofive"></abbr>|brofive
<abbr title="blobfive"></abbr>|blobfive
<abbr title="yui"></abbr>|yui
<abbr title="kms"></abbr>|kms
<abbr title="kannakms"></abbr>|kannakms
<abbr title="blobkms"></abbr>|blobkms
<abbr title="blobparty"></abbr>|blobparty
<abbr title="vegans1"></abbr>|vegans1
<abbr title="vegans2"></abbr>|vegans2
<abbr title="hehe"></abbr>|hehe</table>/i, table)
}
// Fetch local storage cache
function get_local() {
const cache = JSON.parse(localStorage.getItem('Emoter') || '{}')
return Object.assign({ size: 40, emotes: {} }, cache)
}
// Saves to local storage
function set_local(cache) {
localStorage.setItem('Emoter', JSON.stringify(cache))
}
})()
Then go to the console tab and make sure to show all messages

Then add an emote, and take a screenshot of the logs