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!)
Code
// ==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
Could you possibly have more than one instance of the script running?
Can we include mine (details over at WaniKani Discord Bot (Unaffiliated)) after we begin releasing versions?
This is just a list of the scripts that I made. I think you are looking for this list
You should be able to add to it yourself, once you are ready
!emote url tj3starsing “https://i.imgur.com/NfvOTBy.png”
Sorry for only just now trying this, but I still can’t get it to work ):
I’m having trouble with the !emote script no longer displaying my emotes. 
I’ve had increasing issues these past days and today Firefox upgraded to a new version that changes stuff around more than usual. I’ve had all scrips reset to default 3 times in 3 days, but hoped that would be the end of it. I couldn’t log on today without deleting my wanikani cookies. (rip my regular counter status)
But this latest bout of problems just puzzles me…what’s going on here??
testing 
- testing
0 voters
not to mention my durtle emoticons don’t work it seems.
Sorry if the break off point doesn’t check out but I just wanted to catch the last messages on my console
What do I need to do to fix the emoticons? 
I’m sorry, what are you testing in your post?
Also, if you deleted your cache your saved emotes are also gone
!emote new tj3starexcite “https://i.imgur.com/0oDOQrn.png”
!emote new tj3starlaser “https://i.imgur.com/siAA26a.png”
You can’t even add new ones though
I see…rip T_T
I don’t know which topic should I ask. So my best bet should be here.
Is there any script that prevent me from entering Wanikani community webboard if I still not finish all the review?
That would be the best motivation to finish all the review lol
Can we get an Other Voice Actor update plz. It broke. I got used to pressing I but now no Kyoko 
Of course! I’ll look into it next week!
This should be fixed now!
Omg thanks
but I found bugs…
I did my reviews and it was fine except one thing, I got “tomorrow” and answered あす but Kyoko said みょうにち (I don’t remember how previous version of script behaved when multiple answers) I expected her to say あす too, or first item あした .
Then I decided to check if lessons worked, get whichever lvl16 vocab but Kyoko says しょうひん from latest review item 商品. Page refresh not helping, script reinstall not helping. Fix pls? 
Does this work? Can I just copy paste this and update the greasyfork script?

