* When a tag's category is changed, also change the category of any aliases pointing to it. For
example, if "ff7" is aliased to "final_fantasy_vii", and "final_fantasy_vii" is changed to a
copyright tag, then change the empty "ff7" tag to be a copyright tag too.
* Don't allow changing the category of an aliased tag. For example, if "ff7" is aliased to
"final_fantasy_vii", then don't allow changing the "ff7" tag to be a non-copyright tag.
This ensures that the categories of aliased tags stay in sync with that of their parent tags. This
way aliased tags are colored correctly in wikis and other places.
When regenerating thumbnails for a media asset, don't redistribute the original file. This is
unnecessary and also slow if it's a large file on remote storage.
Fix placeholder names like weibo_1234, bilibili_1234, nijie1234, and nicoseiga1234 being suggested
as Other Names when creating new artist entries. These are meant to be placeholders for the tag
name, not used as other names.
Hide the "Formatting help" link for single-line DText fields in dialog boxes, such as after the
"Reason" field in the flag, appeal, and report dialog boxes.
The `date:` metatag depends on the current user's time zone, so the post count for `date:` searches
needs to be cached separately for different users, otherwise it could lead to incorrect page counts
if two users with different time zones search for the same `date:` metatag at the same time.
Fix the email deliverability check to return undeliverable when the MX lookup returns a domain or IP
address that is invalid or that refuses connections. For example, `yeah.com` returns the invalid IP
address 0.0.0.0 for its MX record.
Don't allow favgroup names that:
* Start or end with underscores.
* Contain multiple underscores in a row.
* Contain asterisks or non-printable characters.
* Consist of only underscores.
* Consist of only digits (conflicts with `favgroup:1234` syntax).
Add a fix script that fixes favgroups that violate these rules and notifies the user.
Fix the ban! and unban! methods to:
* Lock the artist while it is being banned or unbanned.
* Perform the edits as a mass update, so that the posts are updated in parallel.
* Edit the artist as the banner rather than as the current user.
* Soft delete the banned_artist implication when an artist is unbanned instead of hard deleting it.
* Ignore the banned_artist implication if it's deleted.
When a user is banned, send them a "You have been banned" dmail instead of a "Your user record has
been updated" dmail.
When a user loses approver status due to inactivity, don't seen them a "Your user record has been
updated" dmail for the "Lost approver privileges" neutral feedback they receive.
Fix a bug where, if you were uploading an entire 4chan thread, then the source of each post would
get set to the 4chan thread, rather than to the individual 4chan post.
Fix API calls returning HTTP 412 (Precondition Failed) errors. It seems we need to spoof the Referer as
`https://bilibili.com` for API calls to succeed.
Allow uploading .zip, .rar, and .7z files from disk. The archive will be extracted and the images
inside will be uploaded.
This only works for archive files uploaded from disk, not from a source URL.
Post source URLs will look something like this: "file://foo.zip/1.jpg", "file://foo.zip/2.jpg", etc.
Sometimes artists uses Shift JIS or other encodings instead of UTF-8 for filenames. In these cases
we just assume the filename is UTF-8 and replace invalid characters with '?', so filenames might be
wrong in some cases.
There are various protections to prevent uploading malicious archive files:
* Archives with more than 100 files aren't allowed.
* Archives that decompress to more than 100MB aren't allowed.
* Archives with filenames containing '..' components aren't allowed (e.g. '../../../../../etc/passwd').
* Archives with filenames containing absolute paths aren't allowed (e.g. '/etc/passwd').
* Archives containing symlinks aren't allowed (e.g. 'foo -> /etc/passwd').
* Archive types other than .zip, .rar, and .7z aren't allowed (e.g. .tar.gz, .cpio).
* File permissions, owners, and other metadata are ignored.
Partial fix for #5340: Add support for extracting archive attachments from certain sources
Fix /posts/random?tags=touhou to redirect to /posts/1234?q=touhou instead of /posts/1234?tags=touhou.
Fixes the search bar on random posts not containing the current search.
Fix temp files generated during the upload process not being cleaned up quickly enough. This included
downloaded files, generated preview images, and Ugoira video conversions.
Before we relied on `Tempfile` cleaning up files automatically. But this only happened when the
Tempfile object was garbage collected, which could take a long time. In the meantime we could have
hundreds of megabytes of temp files hanging around.
The fix is to explicitly close temp files when we're done with them. But the standard `Tempfile`
class doesn't immediately delete the file when it's closed. So we also have to introduce a
Danbooru::Tempfile wrapper that deletes the tempfile as soon as it's closed.
The `pry` gem was removed in e698bf91 because we replaced `pry-byebug` with the standard debugger.
Add it back because `pry` is better than `irb` and we still can use the standard debugger with it.
* Call it "Changes" when referring to the global list of changes (pool changes, artist changes, etc).
* Call it "History" when referring to the history of a single item (pool history, artist history, etc).
* Put the artist history search form on the /artist_versions page, and remove the /artist_versions/search endpoint.
Fix external HTTP requests not working when the HTTP proxy was enabled. Caused by the `public_only`
option (which prevents SSRF attacks by validating that the URL doesn't resolve to a local IP) being
incompatible with the `proxy` option.
Don't log a mod action when a user deletes their own account. This isn't a moderator action, so it
doesn't belong here. Account deletions are still logged on the /user_events page (visible to mods only).
A mod action is still logged when the Owner-level user deletes someone else's account.
Add media_asset_id and old_media_asset_id columns for associating replacements with media assets.
This way we can easily tell which replacements don't have a media asset (with the md5 alone we can't
tell whether the media asset actually exists).
Add a fix script to download images from Gelbooru for old replacements where we deleted the original
image. For archival purposes, we want to try to find the original file for every replacement.
These images will be uploaded as unposted assets under DanbooruBot's name.
Add a fix script that imports the md5 for old post replacements from the corresponding DanbooruBot
replacement comment, then deletes all replacement comments.
There are about 250 replacements left that still have a null md5 because they don't have a matching
comment. This is because if a post was replaced but the file didn't change, it didn't leave a comment.
Fix `Relation passed to #and must be structurally compatible. Incompatible values: [:joins] (ArgumentError)`
exception in `ordfav:evazion ratio:4:3` search. Broken by e849d8f1c.
We were effectively doing this:
q1 = Post.joins(:favorites, :media_asset).where("favorites.user_id = ?", 52664).order("favorites.id DESC")
q2 = Post.joins(:media_asset, :favorites).where("ROUND(media_assets.image_width::numeric / media_assets.image_height::numeric, 2) = 1.33")
q3 = q1.and(q2)
This failed because Rails didn't like the fact that the joins were in a different order when the
queries were `and`-ed together.
Don't allow users to choose names that conflict with search syntax, like `any` or `none`, or names
that impersonate user levels, like `Admin`, `Moderator`, `Anonymous`, etc.
Fix three exploits that allowed one to keep using their account after it was deleted:
* It was possible to use session cookies from another computer to login after you deleted your account.
* It was possible to use API keys to make API requests after you deleted your account.
* It was possible to request a password reset, delete your account, then use the password reset link
to change your password and login to your deleted account.
* Don't delete the user's favorites unless private favorites are enabled. The general rule is that
public account activity is kept and private account activity is deleted.
* Delete the user's API keys, forum topics visits, private favgroups, downvotes, and upvotes (if
privacy is enabled).
* Reset all of the user's account settings to default. This means custom CSS is deleted, where it
wasn't before.
* Delete everything but the user's name and password asynchronously.
* Don't log the current user out if it's the owner deleting another user's account.
* Fix#5067 (Mod actions sometimes not created for user deletions) by wrapping the deletion process
in a transaction.
Move the account deletion endpoint from /maintenance/users/deletion to either:
* https://danbooru.donmai.us/users/deactivate
* https://danbooru.donmai.us/users/:id/deactivate
This incidentally allows the Owner-level user to deactivate accounts belonging to other users. This
is meant for things like deactivating inactive accounts with invalid or abusive names. This is
limited to accounts below Gold level for security.
Automatically add the `sound` tag if the post has sound. Remove the tag if the post doesn't have sound.
A video is considered to have sound if its peak loudness is greater than -70 dB. The current quietest post
on Danbooru has a peak loudness of -62 dB (post #3470668), but it's possible to have audible sound at
-80 dB or possibly even lower. It's hard to draw a clear line between "silent" and "barely audible".
At first we rounded loudness values to 4 decimal places to make them
easier to compare. This meant the lowest level was 0.0001, or -80 dB,
but it's possible for volume levels to go even lower than that.
For videos with sound, save information about audio volume levels in the
media asset's metadata. These values are stored:
* FFmpeg:AudioPeakLoudness The peak loudness of the audio track, from 0.0 (silent) to 1.0 (max volume)
* FFmpeg:AudioAverageLoudness The average loudness of the audio track, from 0.0 (silent) to 1.0 (max volume).
* FFmpeg:AudioLoudnessRange The difference between the quietest and loudest sounds in the audio track (in decibels).
* FFmpeg:AudioSilencePercentage The percentage of the video that is silent (1.0 is completely silent, 0.5 is 50% silence, 0.0 is no silence).
These values are calculated based on the EBU R 128 standard, using the ffmpeg command below:
ffmpeg -i file.mp4 -af silencedetect=duration=0.05:noise=0.0001,ebur128=metadata=1:peak=true:dualmono=true -f null /dev/null
See the links below for details:
* https://en.wikipedia.org/wiki/EBU_R_128
* https://www.ffmpeg.org/ffmpeg-filters.html#ebur128-1
* https://tech.ebu.ch/loudness
* https://tech.ebu.ch/docs/tech/tech3341.pdf
Fix .webm files not including the `FFmpeg:VideoBitRate` and `FFmpeg:AudioBitRate`
fields in the media_metadata table. This was because the .webm format
doesn't include the video or audio bit rates in the metadata, and
ffprobe doesn't calculate them either, so we have to calculate them
ourselves by hand.
Fixup for 523d7afdd.
Fix exception when `MediaFile::Image#dimensions` calls `metadata.width`.
Caused by the `ExifTool::Metadata#merge` method returning a Hash instead
of a new `ExifTool::Metadata` instance.
Include the following metadata tags for videos:
* FFmpeg:MajorBrand (e.g. mp42)
* FFmpeg:PixFmt (e.g. yuv420p. Indicates bit depth and color subsampling mode)
* FFmpeg:FrameCount (e.g. total number of frames in the video)
* FFmpeg:VideoCodec (e.g. h264)
* FFmpeg:VideoProfile (e.g. Main)
* FFmpeg:AudioCodec (e.g. AAC)
* FFmpeg:AudioProfile (e.g. LC)
* FFmpeg:AudioLayout (e.g. stereo)
* FFmpeg:AudioBitRate (e.g. 128kb/s)
If a media asset is corrupt, include the error message from libvips or
ffmpeg in the "Vips:Error" or "FFmpeg:Error" fields in the media
metadata table.
Corrupt files can't be uploaded nowadays, but they could be in the past,
so we have some old corrupted files that we can't generate thumbnails
for. This lets us mark these files in the metadata so they're findable
with the tag search `exif:Vips:Error`.
Known bug: Vips has a single global error buffer that is shared between
threads and that isn't cleared between operations. So we can't reliably
get the actual error message because it may pick up errors from other
threads, or from previous operations in the same thread.
When searching posts by width, height, file size, or file extension, use the
values from the media_assets table rather than the posts table.
This makes filetype: searches faster because the file_ext is indexed on
the media assets table, but not on the posts table.
This paves the way for getting rid of the width, height, file_size, and
file_ext indexes on the posts table in the future. It's wasteful to
index these columns on both the posts table and the media assets table.