Duolingo mods

Duolingo keyboard shortcuts

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

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.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Duolingo mods
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Duolingo keyboard shortcuts
// @author       You
// @require      https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.2/babel.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js
// @match        https://www.duolingo.com/*
// ==/UserScript==
// constants
const home_class = '_2QyU5'
const strengthen_class = '_1_mnP _3QG2_ _1vaUe _3IS_q'
const practice_class = '_1A_Px oNqWF _3hso2 _2vmUZ _2Zh2S _1X3l0 eJd0I _3yrdh _2wXoR _1AM95 _2PUh7 H7AnT'
const discuss_class = 'uRLFE _11g-P _2yH8S _3j92s'
const untimed_class = '_3_pD1 _2ESN4 _2arQ0 _2vmUZ _2Zh2S _1X3l0 eJd0I _3yrdh _2wXoR _1AM95 _1dlWz _2gnHr _2L5kw _3Ry1f'
const test_out_class = 'cVLwd _2arQ0 _2vmUZ _2Zh2S _1X3l0 eJd0I _3yrdh _2wXoR _1AM95 _1dlWz _2gnHr _3Ry1f _2VaJD _23-CV _2arQ0 _2vmUZ _2Zh2S _1X3l0 eJd0I _3yrdh _2wXoR _1AM95 _1dlWz _2gnHr'
const start_lesson_class = 'TZE8O'
const hint_class = '_1FxPb _3RFcO _3kmYT _2vmUZ _2Zh2S _1X3l0 eJd0I _3yrdh _2wXoR _1AM95 _3lAD6 H7AnT'
const test_class = '_3Gihx'
const textarea_class = '_2MGCg _1py6s _1e69E _3_NyK _1Juqt'
const replay_audio_class = '_2GN1p _1ZlfW _2cIrv'
const choice_class = 'iNLw3'
const mouseover_character_class = '_2KZ79'
const asdfg_arr = ['a','s','d','f','g']
const qwert_arr = ['q','w','e','r','t']
const hjkl_arr  = ['h','j','k','l',';']
// variables
let last_selected_index = -1
let mouseover_active = false
// helpers
const getEls = class_name => document.getElementsByClassName(class_name)
function clickIndex(class_name, idx) {
  const els = getEls(class_name)
  if (els.length > idx) {
    els[idx].click()
    return true
  }
  return false
}
const clickFirst = class_name => clickIndex(class_name, 0)
function mouseoverCharacter(idx) {
  const mouseover_els = getEls(mouseover_character_class)
  if (idx < 0) {
    idx = mouseover_els.length - 1
  } else if (idx >= mouseover_els.length) {
    idx = 0
  }
  for (let i = 0; i < mouseover_els.length; ++i) {
    const el = mouseover_els[i]
    if (el.className == mouseover_character_class || i == idx) {
      el.click()
    }
  }
  mouseover_active = (idx !== last_selected_index)
  last_selected_index = idx
}
// core functionality
function onKey(e) {
  console.warn(e)
  const key = e.key.toLowerCase()
  if (key == '`') {
    clickFirst(textarea_class)
  } else if (key == ' ' && e.ctrlKey && !e.shiftKey) {
    clickFirst(replay_audio_class)
  } else if (key == 's') {
    clickFirst(strengthen_class) || clickFirst(practice_class) || clickFirst(untimed_class)
  } else if (key == 't') {
      clickFirst(test_class)
  } else if (key == 'h') {
      clickFirst(hint_class)
  } else if (key == 'd') {
    getEls('OzTZU')[1].click()
  } else if (key == 'r' && e.altKey) {
    clickFirst(home_class)
  } else if (key == 'tab') {
    if (e.shiftKey) {
      mouseoverCharacter(last_selected_index - 1)
    } else {
      mouseoverCharacter(last_selected_index + 1)
    }
    e.preventDefault()
  } else if (key == 'escape') {
    mouseoverCharacter(last_selected_index)
  } else if (e.keyCode >= 112 && e.keyCode <= 121) { // Fn
    const idx = e.keyCode - 112
    mouseoverCharacter(idx)
    e.preventDefault()
  } else if (e.keyCode >= 49 && e.keyCode <= 53) {
    const idx = (Number(key) + 10 - 1) % 10
    clickIndex(start_lesson_class, idx) || clickIndex(choice_class, idx)
  } else if (asdfg_arr.indexOf(key) != -1) {
    clickIndex(choice_class, asdfg_arr.indexOf(key))
  } else if (qwert_arr.indexOf(key) != -1) {
    clickIndex(choice_class, qwert_arr.indexOf(key) + 5)
  } else if (hjkl_arr.indexOf(key) != -1) {
    clickIndex(choice_class, hjkl_arr.indexOf(key) + 5)
  } else if (key == 'enter') {
      last_selected_index = -1
  } else {
      if (mouseover_active) {
        mouseoverCharacter(last_selected_index)
      }
  }
}
function startUntimed() {
  clickFirst(untimed_class)
  const els = getEls(test_out_class)
  if (els.length && els[0].innerText.includes('TEST OUT'))
      els[0].click()
}
setInterval(startUntimed, 100)
document.addEventListener('keydown', onKey)
window.localStorage["duo.session.coach_duo.last_shown_big_right_streak"] =
    window.localStorage["duo.session.coach_duo.last_shown_small_right_streak"] =
    window.localStorage["duo.session.coach_duo.last_shown_wrong_streak"] =
    Math.floor(new Date().valueOf() / 1000);