SamSuka
Touhou-Project.com
Touhou-Project.com

patreon


And the Beat Goes On

Hey everyone, I hope you’ve been doing well. Personally, I’ve been really busy with little time for myself since the last one of these posts. That said, I’ve still managed to plug away at various things that I’ve been meaning to do. While the changes and features I’ll be talking about aren’t live yet, I hope that they will be very soon pending finding the time to finish some implementation and quash some more bugs.

I want to start off with something that might seem inconsequential: I’ve added AVIF support. Yes, it’s yet another image format and, if I’m honest, I very much doubt it’s going to become popular anytime soon despite a few larger sites adopting it. So then, why add it? Partly, because I could! It is supported in newer versions of PHP natively and many of the I made in the last year have made THP’s code base compatible with the latest stable releases. With the exception of a few edge cases that I catch every now and again, things are working just fine with the newer PHP.

I believe I’ve mentioned here and there how there’s a few things I’d like to modernize with regards to how images are handled by the site software. Part of the original design for the board software saw boards more or less autonomous of each other, with possibly their own types (text, image, oekaki but there were two more), their own board-specific moderators, and with their own allowed content and file types. I’ve mostly consolidated those kinds of distinctions—which were often undercooked feature-wise and had poor underlying code—so that universal moderators, pretty much just one board type etc have been a fact of life for some time.

One of the last holdouts was image types being specific to boards. There was a separate table in the database which specified which board ids had which image type ids. This meant that an additional lookup was needed in most image-related operations to fetch all the relevant data and determine if things could proceed. That has been eliminated in the code as every board already had the same permissions and so it was just a waste of space and processing power, as minuscule as it might be in practice. Untangling that was theoretically easy but, in practice, some of the most difficult-to-parse code lives in the image-handling parts of the software. For example, there was a single line that used a lot of shorthand for SQL joins, tables, and even a conditional alongside compound variable names that resulted in the longest line of code that I’ve seen in THP’s code base. Even just trying to break it up into smaller pieces to help keep track of what it was doing was time-intensive. Naturally, no one had bothered to add comments the unintelligible code for posterity’s sake.

While I was at it, I cleaned up the excessive if/else statements and a few minor things that were related to thumbnailing, making their generation ever-so-slightly quicker while adding explicit AVIF support. If I wanted to add more image formats in the future it would be easier. More importantly, and circling back to why I bothered doing all this the first place, it’s a necessary step in something I have thought about adding down the line: the ability to add multiple images/files to posts. That particular feature will require more work, especially on the database and storage side of things, but we’re at least some ground has been prepared.

Some of the work I’ve done always involves tools and interfaces for moderation. While most of that is mostly only interesting to me, and so I won’t talk about it, I will mention improvements in managing users in general. Changing user names or setting a new password for someone who forgot theirs required direct database interaction previously. I extended the management interface that dealt with adding new users to accommodate that and more. Seeing as one of the main goals of the upcoming updates is to improve the story list and tagging (details forthcoming in a later post) I figured that it would be good to have an easier way to deal with user accounts. It’s certainly not vital nor glamorous work but as I hope to attract more people to contribute to the story list it is nonetheless a nice quality-of-life improvement.

Clever little hobbitses may notice that things like removing your own privileges or deleting your own account is not possible

In that same vein, something which had been on my to-do list was making sure threads got their last “bumped” or “update” time set consistently. As you might imagine, that information gets set whenever a post is made. It wasn’t, however, when a post was deleted (or deleted by a moderator, which is another code path … or deleted by a moderator from within the moderator’s panel….) Ensuring that that information gets changed successfully on deletion or during manual generation (eg forcing archiving) wasn’t particularly difficult but it did require some rather strict definitions of parameters. Like, you could have cases where a thread has no replies but the OP after a deletion or doesn’t have an update at all anymore. Optimizing everything into a reusable chunk of code that’s easy to understand while being concise was the real trick. It’s fair to say that I prefer to take my time to implement things as well as I am able to and that’s why even relatively small tasks like these take me a while to make sure I’ve covered all my bases.

Sometimes I’m forced to hold off on features because of that. As mentioned, the code base modernization is something that’s eternally ongoing but, at times, I’m also at the mercy of the developers of the few external libraries that THP uses. A bug reported by a user a little while ago turned out to be an issue with how associative arrays are returned by the database library. I had to do a hacky workaround while I wait for upstream to fix their issue. Some of the simplification of the older THP code has been put on hold because of the same library, so that I can ensure that the behavior of the program won’t change.

I figured I ought to mention the above because a lot of the work I do relates to planning and understanding how I can accomplish the things that I want to. I usually then write a little bit of test code to try out an idea and, if I’m satisfied with the general premise, I iterate until I have something that does what I need to. Then comes testing, rewriting to fix bugs or because I figured that there’s something I ought to add, more testing, and, finally, optimization passes. Often enough I go back a step or decide to come back to it and, from time to time, I decide to restart entirely with another approach. I don’t think that even failures are time wasted as I usually learn something.

Still, the fluidity of my process makes it so I sometimes decide to put a pin into some of the things I have planned and focus on other areas. When the external library is fixed or when I get a better idea it’s easier to restart. It does make the going slow at times.

That’s also why despite nominally aiming to improve the story list and tagging I’ve spent so much time on all that other stuff and why I’ll spend time cleaning up items from my to-do list; a small fix here and there to the CSS, reworking how reported posts are handled internally, fine-tuning how staff power levels work, seeing to Matrix stuff that needs attention (I swear I’ll get around to talking about that eventually).

And there’s also the never-ending security and spam concerns: tweaking filters, patterns to catch likely abuse attempts, and managing the server-side firewall (on a slow day somewhere around 20 IP addresses may be automatically blocked). I do periodic reviews and manually trawl through logs to identify areas where things need adjustments as being too lenient or too zealous can invite trouble either way. A helpful byproduct of this is that sometimes I can find broken pages because bots will request malformed links or things that aren’t there anymore but are nonetheless referenced on older pages. It seems at times that this kind of work that I’m briefly mentioning in this paragraph is what I actually spend most of my time on.

I’ll have another post up in a couple of days if all goes well—at the end or just after the long weekend—detailing the work done on the story list. The vast majority of the work on that is done and the real blockers are elsewhere in other systems. I have to finish that other work before I can give the story list stuff another pass—as they interact in places. And I still haven’t made a final decision on a few small details or, rather, flourishes that I may add to the story list at the end. I know that’s annoyingly mysterious, sorry!

As I think my blathering has overstayed its welcome, it’s time to bid you all the best until next time. Take it easy!


More Creators