I tried to create a small app using LLM. Here is what happened.
I usually use an LLM as an interactive help system. And sometimes, I use it to review code. It’s very good at finding mistakes. This time, I decided to try writing code through a prompt. I didn’t use anything special. Just the usual chat. And… it works!
The task is very simple. I read manga on my tablet using the Mihon App. It downloads chapters into its cache. I needed to move these chapters to my Kindle Scribe. Copying the files is not a problem - Calibre works great for that. You just need to tell it not to change the images in the conversion settings. Otherwise, the file size gets much bigger. But if I transfer them as they are, I end up with a pile of files. I wanted to combine the chapters into volumes.
I split the task into two steps: split the chapters into volumes, and then create new CBZ files. For those who don’t know: a CBZ file is just a regular ZIP archive with images. What’s more, you can not only store a list of images inside, but also organize them into folders. This makes our task much easier.
So, today I’m an analyst and a tester. First, let’s see what we have. My first idea was to take the volume and chapter numbers from the file name. If they weren’t there, I would have to set them manually. That didn’t sound good. Luckily, Mihon App adds an XML file to each downloaded chapter. Inside, in the <title> tag, there is a proper chapter name with the volume number. It turns out, the format of this string depends on the source where the chapter was downloaded. I don’t use many sources, so that makes the task easier (even if it makes the app less universal).
Okay. I got the following prompt:
There is a folder. In it, there are *.cbz files (ZIP archives).
We need to open each archive. Read the file ComicInfo.xml. And save the data into a
Dictionary<String, ???>, where: file name = a structure. This structure contains: volume number (an integer), chapter number (a decimal), and chapter name.Here are possible examples of the XML file:
(Examples of different XML files are here)
We need the
<title>tag.This tag contains the chapter name and the volume. We need to parse this tag to understand the volume number, the chapter number, and the chapter name. So far, I’ve only seen files like this:
(Here are examples like: (original string) -> what we get from it)
So, I ended up with a class that seems to work. Since it was something like a mini-script, I didn’t bother with unit tests.
Now I realize it would have been better to make the AI write unit tests for it and see how it handles them. Why? Because there was a problem with the titles. Not all of them were parsed correctly. I had to change the code interactively, sometimes even writing code by hand.
For a clean experiment, I think a better approach would be: take a very large number of chapter titles, and ask the AI to create unit tests and the code based on them. I should try that approach when I have some free time.
The second part of the task — combining chapters into volumes — had no problems at all. The code was written correctly from the start.
The prompt is:
Using the obtained
ConcurrentDictionary<string, ComicInfo?>we need to:Create an archive named Vol {xxx}, where xxx is the volume number, with leading zeros. The number of zeros should be the same for all numbers: 01, 02.. 10 or 001, 002, 100 (because we know the highest volume number).
Inside this archive, add folders: (folder) (chapter number and name) and extract all files from the original archive there. The number of folders equals the number of files for that volume.
Then I added a check for the correctness of the input data:
ConcurrentDictionary<string, ComicInfo?>If the file is not found, print a message to the console in red color.
Here, just out of interest, I manually changed the format of the chapter names. I wanted them to have leading zeros for even sorting. But again, I did this with the help of the LLM.
To make sure it wasn’t write-only code, I added a feature. It splits a volume into sub-volumes if the file size reaches a set limit. This way, the final files don’t get too large.
I simply integrated this addition into the existing algorithm by hand. I didn’t do a full refactor.
What’s my conclusion? In my opinion, LLMs are very suitable for solving everyday tasks. (And remember, I did all this in a regular chat!).
This works if you act as an analyst and a tester. You need to know how to set the task correctly and how to check the results of the algorithms afterward.
Happy coding!
P.S. I forgot to share the link to the repository with the resulting code: MangaRePacker. The description was generated by an LLM, based on the work results and, surprisingly, on the source code link — although here, it’s clearly being lazy.