Make all forum post votes visible to everyone.
When forum votes were first introduced, it was technically possible to
vote on any forum post, including on posts in mod-only threads.
Accordingly, forum post votes were only visible if the forum post itself
was visible. However, there doesn't actually exist any votes on private
forum posts, and trying to filter them out makes the /user_actions page
much slower, so just make them visible to everyone.
Allow moderators to see all events on the /user_events page. Before only
admins could see when a user changed their email, changed their
password, or had a failed login attempt. Now moderators can see these
events too.
Filtering these events out made the /user_actions page slower, and it
wasn't really necessary since merely knowing that a user changed their
email or password isn't that much more sensitive than knowing when they
logged in or out.
Add a /user_actions page. This page shows you a global timeline of
(almost) all activity on the site, including uploads, comments, votes,
edits, forum posts, and so on.
The main things it doesn't include are post edits, pool edits, and
favorites (posts and pools live in a separate database, and favorites
don't have the timestamps we need for ordering).
This page is useful for moderation purposes because it lets you see a
history of almost all of a user's activity on a single page.
Currently this page is mod-only. In the future it will be open to all
users, so you can view the history of your own site activity, or the
activity of others.
Add a user_actions view. This view unions together a bunch of tables to
produce an event log of every action taken by a user.
Also add a bunch of indexes to make queries on this table efficient.
Even though the view is an enormous query combining together about 30
different tables, queries are very efficient as long as every table has
`created_at` and `(user_id, created)` indexes.
Change ID columns from `bigint` (64-bits) to `integer` (32-bits) on various tables.
Rails 6.0 switched the default from bigint to integer for IDs on new
tables, so now we have a mix of tables with integer IDs and bigint IDs.
Switch back to integer IDs on certain tables because we're going to
build a view that unions a bunch of tables together to build a user
activity timeline, and for this purpose all the tables need to have IDs
of the same type in order for Postgres to optimize the query effectively.
Remove the IP address search option from the /moderator/dashboard page.
This was an obsolete way of searching for sockpuppet accounts by IP.
The /user_events page should be used instead.
Unlike other models, notes had a special rule where if you deleted or
undeleted a note, it would always create a new version instead of
merging it into the previous version. Remove this rule since it didn't
have a purpose and it was inconsistent with other versioned models.
Fix a nil reference exception in the sidebar when a wiki page doesn't
belong to a tag.
Also hide the options sidebar on the new wiki page since none of the
options are relevant when creating a new wiki.
Automatically retire artist aliases after they're more than 2 years old.
Before the rule was that artist aliases were only retired if they didn't
have any new posts in the last 2 years.
Replace the "Edit | History | Related | Similar" links on the /tags
index with a popup menu containing more actions, including links to the
tag's version history, links to the tag's aliases and implications,
links to comments and forum discussions mentioning the tag, and links to
find untagged and mistagged posts using AI tags.
Track the history of the tag `category` and `is_deprecated` fields in
the `tag_versions` table.
Adds generic Versionable and VersionFor concerns that encapsulate most
of the history tracking logic. These concerns are designed to make it
easy to add history to any model.
There are a couple notable differences between tag versions and other versions:
* There is no 1 hour edit merge window. All changes to the `category`
and `is_deprecated` fields produce a new version in the tag history.
* New versions aren't created when a tag is created. Versions are only
created when a tag is edited for the first time. The tag's initial
version isn't created until *after* the tag is edited for the first time.
For example, if you change the category of a tag that was last updated
10 years ago, that will create an initial version of the tag backdated
to 10 years ago, plus a new version for your edit.
This is for a few reasons:
* So that we don't have to create new tag versions every time a new tag
is created. This would be wasteful because most tags never have their
category or deprecation status change.
* So that if you make a typo tag, your name isn't recorded in the tag's
history forever.
* So that we can create new tags in various places without having to know
who created the tag (which may be unknown if the current user isn't set).
* Because we don't know the full history of most tags, so we have to
deal with incomplete histories anyway.
This has a few important consequences:
* Most tags won't have any tag versions. They only gain tag versions if
they're edited.
* You can't track /tag_versions to see newly created tags. It only
shows changes to already existing tags.
* Tag version IDs won't be in strict chronological order. Higher IDs may
have created_at timestamps before lower IDs. For example, if you
change the category of a tag that is 10 years old, that will create an
initial version with a high ID, but with a created_at timestamp dated
to 10 years ago.
Fixes#4402: Track tag category changes
Add a tag_versions table for tracking the history of tags.
A couple notable differences from other version tables:
* There is a previous_version_id column that points to the previous
version. This allows finding the first, last, previous, or next
version efficiently in SQL.
* There is a `version` column that tracks the revision number (1, 2, 3, etc).
Post versions and note versions have this, but other version tables don't.
* The `updater_id` column is optional. This is because we don't know who
the last updater was before we started tracking the history of tags,
so the initial updater will be NULL in the first version of the tag.
Fixup for 015c6dc7d. Show a warning about failure to add a tag instead
of raising an exception when trying to tag a post with `char:copy:foo`.
This tries to create a tag named `copy:foo` then set the category to
character, which doesn't work because `copy:foo` isn't a valid tag name.
Drop the ability to write e.g. `create alias foo -> char:bar` in a BUR
to change the tag's type as a side effect. You can only use these
tag type prefixes in tag edits now.
This feature was only intended to be used in tag edits. The fact it
worked elsewhere was unintended behavior.
This feature was problematic because it relied on `Tag.find_or_create_by_name`
automagically changing the tag's category when the tag name contained a
tag category prefix, e.g. `char:hatsune_miku`. This meant that merely
looking up a tag could have the side effect of changing its category.
It was also bad because `find_or_create_by_name` had a hidden dependency
on the current user, which may not be set or available in all contexts.
Fix a bug where searching for `sakana~` ranked `sakana~_(meme)` beneath
random artist tags containing the word `sakana`. Now, if the search contains
punctuation, we rank exact matches first, even for small tags. Before we
ranked exact matches for small tags lower than inexact matches for large
tags. If the search contains punctuation, it's a strong signal the user
is looking for an exact match.
Fix tags like `short_shorts` or `hunter_x_hunter` being highlighted
incorrectly. Typing `short_sh` would highlight it as SHort_SHorts
instead of as SHORT_SHorts.
Fix an exception when trying to fetch source data for URLs like
https://va.media.tumblr.com/tumblr_pgohk0TjhS1u7mrsl.mp4.
For these URLs it's not possible to use the trick where we try to open
the URL as a HTML page and scrape the post id from the HTML. Instead we
get the raw video if we try to to this.
Lowercase searches clientside before sending them to the server. This is
to improve cache hit rates when users accidentally type in uppercase,
especially on mobile where the first letter often gets capitalized.
Fix usernames not being highlighted when completing @mentions.
This also changes it so the autocomplete results don't include the '@'
in front of the name.
Minor breaking change to the /autocomplete.json API. Autocomplete
results for mentions now have the type `mention` instead of `user`.
Fix /autocomplete.json returning results like this:
[
{
"table": {
"type": "tag-word",
"label": "long hair",
"value": "long_hair",
"category": 0,
"post_count": 2818211,
"antecedent": null
}
},
]
instead of like this:
[
{
"type": "tag-word",
"label": "long hair",
"value": "long_hair",
"category": 0,
"post_count": 2818211,
},
]
Also change it so that optional attributes like `antecedent` aren't
returned if they're null. This could be a minor breaking change if users
rely on these attributes always being present.
Lastly change XML results to look like this:
<autocomplete-service-results type="array">
<autocomplete-service-result>
<type>tag-word</type>
<label>long hair</label>
<value>long_hair</value>
<category type="integer">0</category>
<post-count type="integer">2801117</post-count>
</autocomplete-service-result>
</autocomplete-service-results>
instead of like this:
<objects type="array">
<object>
<type>tag</type>
<label>hair ornament</label>
<value>hair_ornament</value>
<category type="integer">0</category>
<post-count type="integer">883340</post-count>
<antecedent nil="true"/>
</object>
</objects>
Fix a bug where the word `lazy` wasn't highlighted in `don't_say_"lazy"`
when searching for `lazy`. The bug was that punctuation surrounding
words wasn't properly split from the word.
When completing a static metatag, such as rating: or order:,
don't include the metatag name in the autocomplete menu.
For example, when completing `rating:g`, show `general` in the
autocomplete menu, not `rating:general`.
This makes static metatags consistent with other metatags.
Remove the `data-autocomplete-antecedent`, `data-autocomplete-category`,
and `data-autocomplete-post-count` data attributes from the autocomplete
menu. These weren't used by Danbooru itself and they bloat the HTML.
Limit the width of the autocomplete menu to 480px. This is so that
stupidly long isekai titles don't blow out the size of the menu when
searching for common words.
For example, when searching for "look", one of the results is:
no_matter_how_you_look_at_it_it's_your_fault_that_i'm_not_popular! -> watashi_ga_motenai_no_wa_dou_kangaetemo_omaera_ga_warui!
The new autocomplete system tends to return more results, so increase
the number of tags shown from 10 to 20. This is useful so you can do things
like search for 'skirt' during tagging to find all skirt-related tags.