The 2022 Community Collab has begun! Join in for round six of our massive group collaboration image! Click here for more information

[Userscript] Bulk Tag Editor

Marker
My Little Pony - 1992 Edition
Wallet After Summer Sale -
Magnificent Metadata Maniac - #1 Assistant
Not a Llama - Happy April Fools Day!

Misanthrope
Bulk Tag Editor
 
Purpose  
Nobody’s perfect, that’s especially true when it comes to tagging. This script is for those times when you need to apply the same tag changes across a set of images, whether to refine the tags or fix mistakes. Because while adding one or two tags in bulk might be easy if you’re well versed in the keyboard shortcuts, removing existing tags is much more time consuming, requiring you to find and remove it via mouse click.
 
With the script installed, you can define a set of tags that can be added and removed in the editor with a single click. Or making edits directly from the search page.
 
Compatibility  
On Chrome:  
Works with Violentmonkey or Tampermonkey
 
On Firefox:  
Works with Tampermonkey.  
Works partially with Violentmonkey by installing alternate script version, with the limitation that the saved tags does not carry over across different domains.
 
Install  
Primary: Click here to install from Github  
Firefox Violentmonkey: Click here to install
 
Screenshot  
full
 
full
Background Pony #BFC6
Is there something like this (in combo with rate limiting I guess) that works from thumbnail pages? Because sometimes I come upon like 80% of a page of an artist’s works that are missing basic things like “solo” and I just wanna multi-select and apply all…
Marker
My Little Pony - 1992 Edition
Wallet After Summer Sale -
Magnificent Metadata Maniac - #1 Assistant
Not a Llama - Happy April Fools Day!

Misanthrope
@Background Pony #BFC6  
It’s done.  
Naturally, the rate limiting still applies, so you’ll need to wait a while until the edits are complete before closing the page, but I can personally attest that it really helps with the wrist strain when fixing tags on multiple images.  
Also, the script doesn’t interoperate with the Rate Limiter, so while it’s running don’t do something stupid like making tag edits on other pages.
Background Pony #BFC6
I’m having trouble with tag removal from the thumbnail UI. Adding tags seems to work fine. I have had removing tags work a few times, but more recently, it does count through the candidates (1/3….2/3…etc.) to Completed, but the tags aren’t changed. In particular, I’m trying to rearrange some alternate version tags and animated tags that got onto some (clearly nonanimated) JPEGs. Nothing in the messages on in the console. Any ideas what might lead to such a fail state?
Background Pony #BFC6
@Marker  
Windows Chrome Version 91.0.4472.124 (procrastinating updating due to many open, logged-in tabs), Violentmonkey 2.13.0, this script
 
Examples: try removing the tag “animated” from any of these images (which are mistagged as animated) via the thumbnail UI
 
––––––––
 
I had a look at the network requests, and found that the script is including all(?) of the aliases of tags that are present on an image in its tag change POST. Of course this doesn’t hinder adding tags, but for tags which have aliases it means removing just one (eg. the one that’s displayed among the image’s tags) will effectively nullify itself because those remaining aliases will resolve to the same thing.
 
So, the script can successfully remove a tag from the thumbnail UI only if all aliases of the tag to be removed are entered in the “Tags to remove:” field, rather than just the extant tag. For example, to remove animated, you have to put “animated, animation” in the “Tags to remove:” field.
 
It looks like this is a consequence of getting the tag list from the “data-image-tag-aliases” field. To get a resolved collection of tags, it looks like the options are parsing the child <a>’s “title” field for the text following “Tagged: ”, or getting the tags list from an additional call to the images API, or using the field “data-image-tags” and converting tag IDs to tag names via additional API calls (in order of what I suspect is easiest/preferable)
 
 
If I haven’t screwed this up and given certain assumptions about what information is in the “title” field and its format,  
the line:  
const tags = deserializeTags\(imageContainer.dataset.imageTagAliases\);  
could be replaced with:  
const tags = deserializeTags\($\('a', imageContainer\).getAttribute\('title'\).split\(/\\\| .+?: \(.+\)/\)\[1\]\);  
(this regex should continue to work if/when philomena boorus have other languages)
 
and the line:  
imageContainer.dataset.imageTagAliases = serializeTags\(tags\); [see footnote]  
could be replaced with:  
const newTitle = $\('a', imageContainer\).getAttribute\('title'\).split\(/\^\(.+? \\\| .+?: \).+/\)\[1\] + serializeTags\(newTags\);  
$\('a', imageContainer\).setAttribute\('title', newTitle\);  
$\('img', imageContainer\).setAttribute\('alt', newTitle\);
 
[footnote] Unless I have misinterpreted this line’s purpose, shouldn’t:  
imageContainer.dataset.imageTagAliases = serializeTags\(tags\);  
have been:  
imageContainer.dataset.imageTagAliases = serializeTags\(newTags\);  
Operating on that assumption, the suggestion above includes this change.
 
 
I would Github but I don’t know how to Github  
Marker
My Little Pony - 1992 Edition
Wallet After Summer Sale -
Magnificent Metadata Maniac - #1 Assistant
Not a Llama - Happy April Fools Day!

Misanthrope
@Background Pony #BFC6  
Thanks for the detailed reply! That was incredibly helpful.  
You’re right regarding the footnote, that was an error on my part, good catch. Although in the end I elected to use the API method as it feels less prone to failure then parsing the title attribute, and easier to maintain compatibility with Twibooru.  
The script has been updated, I hope this resolves your issue.
Background Pony #BFC6
@Marker  
Yes, at least upon first try, the update resolves the removing-aliases issue. Thanks!
 
Always glad when I can help. Using the API at the moment of submitting also means the tag list will be the most up-to-date, in case other users had made changes since loading the page, so that was probably the right decision in the end, even if it’s (a tiny bit) more network traffic.
 
I’m a little concerned what the script would do in case the fetch of the image API has a non-promise-rejecting error like a 500 - a condition you check in submitEdit but not getTagsFromId. Would one of the other lines, like if “image” or “post” objects are absent from the response, throw an error to catch? That’s getting out of my depth as an amateur. Is there any chance this could lead to inadvertently blanking an image’s tags? I guess that would be rejected for not having a required tag such as a rating. Or maybe, that’s why the POST data takes old tags as well as new tags, to take the difference on the server side…
 
Anyway…
 
I might have also left in the parts finding imageContainer, in order to update the title and alt so the tooltip reflects the changes without reloading the page, but that gets back into parsing and is just a nicety.
Marker
My Little Pony - 1992 Edition
Wallet After Summer Sale -
Magnificent Metadata Maniac - #1 Assistant
Not a Llama - Happy April Fools Day!

Misanthrope
even if it’s (a tiny bit) more network traffic
 
It doubles the amount of requests, in fact. :)  
But, because the tag fetching happens in the interim while waiting for the 5 seconds cooldown, with the exception of the first request, users will not be affected by any additional delays caused by these requests.
 
what the script would do in case the fetch of the image API has a non-promise-rejecting error
 
In most cases, a SyntaxError will be thrown by .then(resp => resp.json()) when it tries to parse the response. I know that querying a deleted image will get back a json response, but it’s unlikely that those images will be reachable from the search page.
 
in order to update the title and alt […] but that gets back into parsing and is just a nicety
 
Basically this. It’s cumbersome and just not something I particularly want to deal with, sorry.
rautamiekka
Preenhub - We all know what you were up to this evening~
Twinkling Balloon - Took part in the 2021 community collab.
My Little Pony - 1992 Edition
Artist -

  • Windows 10 21H1 Enterprise x64
  • Google Chrome 95.0.4638.69 (Official Build) (64-bit).
  • Tampermonkey 4.13
  • Script version 1.1.1 from the primary install link in the OP.
Doesn’t seem to work properly for me:
On the search page with the Everything filter enabled, I click ‘Tag Edit’ in top right corner, add “oc name needed” to the ‘Tags to add’ and click ‘Apply’. It immediately says ‘Completed’ below the ‘Tags to add’ box, and redoing the search after 5mins and clicking any of the results shows the change wasn’t made.
I honestly dunno how to help, as I found no useful logs under C:\Users\REDACTED\AppData\Local\Google\Chrome\User Data\ even after enabling ‘Collect errors’ for Tampermonkey in Chrome extension settings and setting Tampermonkey’s own logging as Debug in its settings, which ain’t helped by Tampermonkey’s own docs being 1 of the most useless I’ve seen, if I didn’t miss anything.
Marker
My Little Pony - 1992 Edition
Wallet After Summer Sale -
Magnificent Metadata Maniac - #1 Assistant
Not a Llama - Happy April Fools Day!

Misanthrope
@rautamiekka
If you want a quicker way of selecting every image, you can paste document.querySelectorAll('.media-box__header').forEach(ele => ele.classList.add('media-box__header--selected')) into the console.
Background Pony #BFC6
@rautamiekka
It can be done - I tweaked the script for myself with a “Select All” button - but I worry that’d make the script dangerously easy to misuse (maliciously or accidentally) so I was hesitant to suggest it be included normally…
Interested in advertising on Derpibooru? Click here for information!
Ministry of Image - Fanfiction Printing

Derpibooru costs over $25 a day to operate - help support us financially!

Syntax quick reference: **bold** *italic* ||hide text|| `code` __underline__ ~~strike~~ ^sup^ %sub%

Detailed syntax guide