[Extension] WICS - WaniKani Integrated Custom SRS - Now with deck exports!

This is super late but would it be possible to spoof the last non-level up item of a review session (if there is one)?

I know that some apps like flaming durtles let you do reviews offline and then you can sync them to WK later on. So hypothetically you would hijack the review session, and upon completing the last item, it either ignores the answer or resets the item to be incomplete. Then, you save the answer date/info and end the session, displaying the item as reviewed and the current review count at zero WK items. Then, the next time you start a session which contains a different WK item you sync the saved item with the earlier time and repeat. If the session contains no other WK items (it’s just Anki stuff), then skip the item when it comes up.

Also I guess you’d want to check if the WK item is a level up item too and only replace it if it isn’t.

It’d be a lot of effort though and I’m not completely sure if it’s actually doable, but it’s just an idea.

Tagging @Gorbit99 since they know their script the best.

I don’t recommend for now.
This script is quite unstable and doesn’t always load the extra reviews. Also, especially at level 10, you’re in the middle of getting your review stack finalised. Adding on top of that now would seriously undermine your efficiency.
Also, I am working on a rewrite of this (though I don’t have much time currently)

This is possible, though I don’t quite get the point. As long as you either catch the outgoing request or doesn’t even let it start, then you can do whatever with it.

1 Like

The point would be to make it seem to the user that the item has been answered and there’s no more reviews in the queue. Like I said, it’s a lot of effort and it’s not a suggestion, just a solution to the ‘not being able to do non-WK reviews when there are no WK items to review’ problem.

Reading your earlier reply (which I didn’t see before), I don’t entirely understand how your script is interacting with reviews or how review sessions are possible when the review queue is empty. As far as I’m aware, an item is removed from the review queue when answered fully, and so if all WK items are answered fully, the review queue will be empty and WK won’t let you start a new review session. Unless I’m completely misunderstanding something, which is likely.

Ah, I see the misunderstanding. The script hijacks jquery, and when wk queries the reviews, I inject mine in the response. So wk actually believes that there are reviews even when technically there aren’t any. The issue the script has is timing related. Catching the moment when jquery is already loaded, but the review queue isn’t is hard, especially if caching is involved

2 Likes

You might not want to do the same for this script, but what I do with Omega Self-Study is that I insert a dummy item into the empty jStorage queue when the script loads and WK realizes that the queue isn’t empty even though it was when the page loaded

1 Like

Time to revive this thread somewhat.
Why it was dead is somewhat detailed here, but let’s not dwell on the dead.

I started rewriting the script, now as an extension (I currently plan on supporting chrome and firefox, but the demand might change this).
Currently I’m in the midst of a big UI dev session, so I thought it would be great if I could share the current developments, and maybe have some feedback on it (I’m very much not a designer).

Sofar I’m working on the management ui for the custom decks, everything is subject to change.

Current progress

List of the decks showing completion using pie charts

Same thing, but I have light mode support

The individual deck screen with a list of items in that deck


And last screen for now, this will be used to add new items to the deck


I also finally worked out a method for injecting reviews reliably into the wanikani queue, so that’s a definite step forward.

The first version is expected to be somewhat simplistic, I want to get the deck creation and of course the integrated srs parts down, and that will be v0.1.0.
Afterwards the roadmap looks like this:

  • Make decks shareable
  • Use different APIs to autofill item values, making the process of adding new items a bit more bearable
  • Make audio, additional meanings/readings, etc etc work
  • Export to anki (TBD if actually a feature I want, but sounds nice)
  • Somehow interfacing with yomichan or a similar feature, to make mining more bearable
  • Very maybe: a site similar to ankiweb for sharing and searching for decks
5 Likes

I’m so thrilled to see that work is ongoing with this User Script. The timing is incredible, as I’ve been meaning to give this a start and was taking a look at this today!

I added the script earlier on, and wanted to start importing some vocab lists, but I’m facing a broken screen. I’m not sure if this is because of incompatibilities with other scripts I may have installed, or something else. I’m a Chrome user.

I’d be super happy to wait for the extension version of this development too – it seems so convenient to use and I’d love to try it!

1 Like

The script is as old as time, the user interface and the way the active queue works was changed enough to break it. I recommend waiting, I’m not very good at estimates, but if everything goes to plan, I should have a version 0.1.0 up either by the end of the week or a bit after that.

3 Likes

I’m down to wait. Thank you very much for your work on this!

1 Like

Looking great! And thank you for including a dark mode.

I’m wondering whether there’ll be any way to include the custom SRS in pages such as this WaniKani stats website - I don’t suppose your extension will save custom item review times in a way that would be accessible by a website such as that one? If so I could write some code for it to include it in the stats if the extension is installed. Understandable if not though - I imagine you might not even save the review times! :slight_smile:

Looking forward to trying out the extension once it’s ready!

2 Likes

Huh, that’s actually a completely new idea, haven’t thought of that yet. I’ll put this onto the “cool idea, needs planning” list, and I’ll see what I can do. If I do it, I won’t include it in the official stats, just to keep them separate, but I myself might have a go at writing some code to display it.

2 Likes

New UI updates coming up.
Besides finally trying to pull myself kicking and screaming through a furigana-less manga, I also had time to develop the UI further. Wonderful how life works, huh.

Some new changes

Finally the progress wheel is actually fully functional, and not just fake


It’s hard to show in a picture (so I won’t), but you can now add items to the decks, and they get validated (which I can show, so I will)

I also made the whole window movable. This is somewhat of a nice feature, because if you’re trying to copy some text from the middle of the screen, you can just move the whole dialog and it won’t be hidden.

And finally, you can now edit already added items (though deleting them is still impossible)

Once I’m ready with the basic deck management ui, I will probably make a github repository and upload the source code for ridicule scrutiny.

I also need to go through the code and collect similar elements into one place. I define how a button should look like in about 102 different places.

Afterwards I should be ready to just plop the data into the wk queue and that should be v0.1.0

We’ll see how that goes

5 Likes

Another update, just so I can share my slow decent into madness with all of you people. some people have a study log, I have a going crazy log

I have lessons in an… acceptable state!

Said acceptable state


image

So my next incoherent rambling will be about why it took me about 5 hours to get them working. I recommend it for those that love programmer horror for some reason

Stuff

So the issue simply was that didn’t matter how hard I tried, I couldn’t get the lessons to load up reliably. This is of course because chrome is a programming masterpiece that doesn’t like fun. It’s just way too fast and I couldn’t catch the requests made to wanikani in time. So I tried quite a few ways.

  1. Making sure the script I’m injecting to take hack the requests into pieces was the very first thing on the page. Literally the first two elements of it, even above the head element. This didn’t work, chrome too good.
  2. Ok, if that isn’t enough, I need to make sure the requests that wanikani makes for the lesson items don’t get loaded from cache, so cache busting it is. This also didn’t work, chrome too good (though this makes sense in retrospect).
  3. Ok, let’s make sure that the lesson script is the very last thing that loads in, this can be theoretically be done with the “defer” attribute on the script element, so time to catch it when it gets added (which I luckily enough can), and just set it to defer. Didn’t work, chrome too good
  4. Ok, making it run as late as I can didn’t work, so let’s just not let it run until I’m ready, so time to take it out of the document and let’s put in once everything works. This didn’t work because chrome doesn’t just let extensions put in random pieces of code into the document, chrome too safe.
  5. Finally probably one of the simpler options worked, the issue is that chrome is very good at caching that freaking script, so let’s just not let it do that. Good old cache busting.

But now I can reliably load up lesson items without an issue… though this isn’t the first time I thought that. Several times over I thought I had it, then I refreshed the page for the 31st time while testing and it suddenly broke again. So I’m expecting the worst, but seems fine for now.

Time to do some reviews, some final touchups and that should be v0.1.0

6 Likes


reviews are complete as well, including the additional data thingy.
Time to get this thing production ready

5 Likes

Wow, you‘re really going strong here! That‘s an incredibly fast pace.

I‘m really excited for the release of v0.1.0!

That would be really interesting! If the same data was saved as WaniKani itself does it would most likely be possible. And if not all of it, there could be just an extra section for custom items. But I‘m just spitballing here, sorry if the ideas are just way too impractical to do :sweat_smile:

2 Likes

Small progress update, I have an options panel now. I always liked this tabbed look, so tried real hard to make it (and make it somewhat look nice). The options for now are very limited for now (as in what you see is what you get, with the other panel literally being a coming soon sign).


I ought to learn some proper web design and stuff. This is a ton of fun.

2 Likes

I sent in version 0.1.0 for review on chrome!
The firefox version will take a second, because I need to handle the different APIs where the firefox and chrome ones don’t match up, but I’ll give it a try tomorrow.

4 Likes

Looking forward to testing it, it looks pretty good so far!

1 Like

Finally got around to updating the thread, though I kept around the old one.

I also made a github page, so if someone doesn’t want to wait to be the first one to find all the bugs that are surely in there somewhere, then it can be built from source: GitHub - gorbit99/wics-extension (I already have a few bug fixes, that won’t be there in the chrome v0.1.0, but are on the github repo)

4 Likes

Excellent work with this extension @Gorbit99 , also thanks a lot for mentioning Tangochou in your main post!

I see in the roadmap that you would like to integrate Jotoba to simplify item creation, these type definitions I wrote for Tangochou might be of help to you!

Jotoba API Definitions
export namespace JotobaAPIDefinitions {
  export interface Error {
    /**
     * Error code
     */
    code: number
    /**
     * Error description
     */
    error: string
    /**
     * Error informations
     */
    message: string
  }

  export interface Kanji {
    chinese: string[]
    frequency: number
    grade: number
    jlpt: number
    /**
     * Korean reading(s) in hangul
     */
    korean_h: string[]
    /**
     * Korean reading romanized
     */
    korean_r: string[]
    kunyomi?: string[]
    literal: string
    meanings: string[]
    onyomi?: string[]
    /**
     * Parts used to construct the kanji. (only available in kanji search)
     */
    parts: string[]
    /**
     * (only available in kanji search)
     */
    radical: string
    stroke_count: number
    /**
     * Path to the stroke order svg image. (only available in kanji search)
     */
    stroke_frames: string
  }

  export type Language = 'English' | 'German' | 'Spanish' | 'Russain' | 'Swedish' | 'French' | 'Dutch' | 'Hungarian' | 'Slovenian'

  export interface Name {
    kana: string
    kanji: string
    name_type: NameType[]
    transcription: string
  }

  export type NameType =
    | 'Company'
    | 'Female'
    | 'Male'
    | 'Place'
    | 'Given'
    | 'Organization'
    | 'Person'
    | 'Product'
    | 'RailwayStation'
    | 'Surname'
    | 'Unclassified'
    | 'Work'

  export interface SearchWordsRequestBody {
    language?: Language
    /**
     * Does not return english results if the provided language differs from english
     */
    no_english?: boolean
    /**
     * The search query
     */
    query: string
  }

  export interface SearchWordsResponseData {
    /**
     * Kanji used to write words found in search
     */
    kanji: Kanji[]
    /**
     * Words found in search
     */
    words: Word[]
  }

  export interface Sentence {
    content: string
    furigana: string
    language: string
    translation: string
  }

  export interface Word {
    /**
     * Path of the audio file for the given word. Only provided if audio file exists
     */
    audio?: string
    /**
     * Whether the word is a common word or not
     */
    common: boolean
    /**
     * Pitch accent of the word ⮕ [ A part of a Japanese word with the same pitch ]
     */
    pitch: WordPitch[]
    reading: WordReading
    senses: WordSense[]
  }

  export interface WordReading {
    /**
     * An encoded string representing the furigana parts of the kanji reading
     */
    furigana: string
    /**
     * The kana reading
     */
    kana: string
    /**
     * The kanji reading (if available)
     */
    kanji?: string
  }

  export interface WordSense {
    /**
     * Equal meanings of the japanese word in the specified other language
     */
    glosses: string[]
    language: Language
    /**
     * Part of speech of the provided glosses
     */
    pos: string[]
  }

  export interface WordPitch {
    /**
     * Whether its a high or low pitch
     */
    high: boolean
    /**
     * A part of the kana reading with the same pitch
     */
    part: string
  }
}
3 Likes