Greasy Fork is available in English.

Wanikani: Hotkey for other voice actor

Binds the I key to play the audio from the other voice actor

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        Wanikani: Hotkey for other voice actor
// @description Binds the I key to play the audio from the other voice actor
// @match       https://www.wanikani.com/*
// @match       https://preview.wanikani.com/*
// @version     1.2.0
// @author      Kumirei
// @license     MIT; http://opensource.org/licenses/MIT
// @run-at      document-end
// @grant       none
// @namespace https://greasyfork.org/users/105717
// ==/UserScript==

;(async function (wkof) {
    // You can change this key to something else
    const key = 'i'

    // Script info
    const script_id = 'hotkey_for_other_va'
    const script_name = 'Hotkey For Other VA'

    // Init
    await confirm_wkof()
    wkof.include('ItemData')
    await wkof.ready('ItemData')
    let vocab // WKOF vocab items
    init()

    function confirm_wkof() {
        if (!wkof) {
            let response = confirm(
                `${script_name} requires WaniKani Open Framework.\nClick "OK" to be forwarded to installation instructions.`,
            )
            if (response) {
                window.location.href =
                    'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549'
            }
        }
    }

    async function init() {
        vocab = await wkof.ItemData.get_items({ wk_items: { filters: { item_type: 'voc' } } })
        window.addEventListener('keydown', onKeydown)
    }

    function onKeydown(event) {
        if (event.key !== key) return

        // Check if it's a quiz page
        const audio_elem = document.querySelector('.additional-content__item--audio')
        if (!audio_elem) return

        // Check if audio is ready to play
        let audio_disabled = !!audio_elem.classList.contains('additional-content__item--disabled')
        if (audio_disabled) return

        play_other_voice()
    }

    function play_other_voice() {
        // Get URL of current VA (if any)
        const defaultAudio = document.querySelector('audio.quiz-audio__audio source:first-child')?.src
        if (!defaultAudio) return // Do nothing if no audio

        const quizItem = document.querySelector('.character-header__characters')?.textContent
        if (!quizItem) return // Do nothing if no item

        const item = vocab.find((item) => item.data.characters === quizItem)
        if (!item) return // Do nothing if no wkof item

        const pronunciations = item.data.pronunciation_audios
        const defaultPronunciation = pronunciations.find((pronunciation) => pronunciation.url === defaultAudio)
        const defaultVA = defaultPronunciation?.metadata?.voice_actor_id

        pronunciations.sort((a, b) => {
            if (a.url === defaultAudio) return 1 // Send default audio to the back
            if (a.metadata.voice_actor_id === defaultVA && b.url !== defaultAudio) return 1 // Send default voice actor to the back
            return -1
        })

        const alternatePronunciation = pronunciations[0]
        const audio = new Audio(alternatePronunciation.url)
        audio.play()
    }
})(window.wkof)