Compare commits
5 Commits
bbca0db010
...
5b67f2ad9a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b67f2ad9a | ||
|
|
dffdef51cd | ||
|
|
d86612ee2e | ||
|
|
0e92d9a7e1 | ||
|
|
211d5eb62c |
@@ -95,9 +95,3 @@ ENV PATH "/home/vscode/.exo/bin:$PATH"
|
||||
|
||||
# install just (command runner)
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin
|
||||
|
||||
# RUN source /usr/local/share/nvm/nvm.sh && nvm install 18 && nvm use 18 && npm install -g yarn 2>&1
|
||||
# ENV PATH /usr/local/share/nvm/current/bin:$PATH
|
||||
|
||||
# # install `backlog` tool
|
||||
# RUN npm i -g backlog.md
|
||||
|
||||
@@ -98,9 +98,18 @@ services:
|
||||
- WIREGUARD_ADDRESSES=10.165.87.232/32,fd7d:76ee:e68f:a993:4d1b:a77a:b471:a606/128
|
||||
- SERVER_CITIES="San Jose California, Fremont California"
|
||||
|
||||
tor:
|
||||
image: dockurr/tor
|
||||
volumes:
|
||||
- devcontainer-redux-tor-config:/etc/tor
|
||||
- devcontainer-redux-tor-data:/var/lib/tor
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
postgres-17-data:
|
||||
devcontainer-redux-gem-cache:
|
||||
devcontainer-redux-blob-files:
|
||||
devcontainer-redux-grafana-data:
|
||||
devcontainer-redux-prometheus-data:
|
||||
devcontainer-redux-tor-config:
|
||||
devcontainer-redux-tor-data:
|
||||
|
||||
@@ -24,4 +24,14 @@ function blob-files-stats
|
||||
set -l files_dir (blob-files-dir || return 1)
|
||||
printf "apparent size: %s\n" (du -sh --apparent-size $files_dir)
|
||||
printf "actual size: %s\n" (du -sh $files_dir)
|
||||
end
|
||||
end
|
||||
|
||||
function curl-fa-onion
|
||||
curl \
|
||||
--socks5-hostname tor:9050 \
|
||||
--compressed \
|
||||
-A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0" \
|
||||
-H "Accept-Encoding: gzip, deflate" \
|
||||
-H "Connection: keep-alive" \
|
||||
"http://g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion/$argv[1]"
|
||||
end
|
||||
|
||||
@@ -67,7 +67,7 @@ module Domain::PostsHelper
|
||||
def gallery_file_for_post(post)
|
||||
file = post.primary_file_for_view
|
||||
return nil unless file.present?
|
||||
return nil unless file.state_ok?
|
||||
return nil unless file.state_ok? || file.last_status_code == 200
|
||||
return nil unless file.log_entry_id.present?
|
||||
content_type = file.log_entry&.content_type
|
||||
return nil unless content_type.present?
|
||||
|
||||
@@ -13,6 +13,7 @@ module FaUriHelper
|
||||
const :original_file_posted, Integer
|
||||
const :latest_file_posted, Integer
|
||||
const :filename, String
|
||||
const :filename_with_ts, String
|
||||
|
||||
sig { returns(Time) }
|
||||
def original_file_posted_at
|
||||
@@ -35,7 +36,7 @@ module FaUriHelper
|
||||
path = uri.path
|
||||
match =
|
||||
path.match(
|
||||
%r{/art/(?<url_name>[^/]+)/(?<latest_ts>\d+)/(?<original_ts>\d+)\.(?<filename>.*)},
|
||||
%r{/art/(?<url_name>[^/]+)/(stories/)?(?<latest_ts>\d+)/(?<original_ts>\d+)\.(?<filename>.*)},
|
||||
)
|
||||
return nil unless match
|
||||
url_name = match[:url_name]
|
||||
@@ -47,6 +48,7 @@ module FaUriHelper
|
||||
original_file_posted: original_ts,
|
||||
latest_file_posted: latest_ts,
|
||||
filename:,
|
||||
filename_with_ts: path.split("/").last,
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class Domain::E621::Job::ScanPostFavsJob < Domain::E621::Job::Base
|
||||
breaker += 1
|
||||
end
|
||||
|
||||
post.scanned_post_favs_at = Time.now
|
||||
post.scanned_post_favs_at = Time.current
|
||||
post.save!
|
||||
end
|
||||
end
|
||||
|
||||
90
app/jobs/domain/fa/job/scan_fuzzysearch_job.rb
Normal file
90
app/jobs/domain/fa/job/scan_fuzzysearch_job.rb
Normal file
@@ -0,0 +1,90 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Domain::Fa::Job::ScanFuzzysearchJob < Domain::Fa::Job::Base
|
||||
queue_as :fuzzysearch
|
||||
|
||||
sig { override.returns(Symbol) }
|
||||
def self.http_factory_method
|
||||
:get_fuzzysearch_http_client
|
||||
end
|
||||
|
||||
sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform(args)
|
||||
post_file = T.let(nil, T.nilable(Domain::PostFile))
|
||||
post = post_from_args!
|
||||
fs_client = Scraper::FuzzysearchApiClient.new(http_client)
|
||||
|
||||
logger.tagged(make_arg_tag(post)) do
|
||||
if post.fuzzysearch_checked_at.present? && !force_scan?
|
||||
logger.warn("fuzzysearch already checked, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
fa_id = post.fa_id
|
||||
if fa_id.nil?
|
||||
logger.error("post has no fa_id, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
unless post.state_removed?
|
||||
logger.warn("post is not removed, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
response = fs_client.search_fa_id_info(fa_id)
|
||||
post.fuzzysearch_checked_at = Time.now
|
||||
if response.is_a?(HttpLogEntry)
|
||||
post.fuzzysearch_entry = response
|
||||
logger.error("fuzzysearch query failed")
|
||||
return
|
||||
end
|
||||
|
||||
post.fuzzysearch_entry = response.log_entry
|
||||
post.fuzzysearch_json = response.json
|
||||
|
||||
if creator = post.creator
|
||||
if creator.url_name != response.artist_url_name
|
||||
fatal_error(
|
||||
format_tags(
|
||||
make_tag("existing", creator.url_name),
|
||||
make_tag("fuzzysearch", response.artist_url_name),
|
||||
"fuzzysearch artist url name mismatch",
|
||||
),
|
||||
)
|
||||
end
|
||||
else
|
||||
url_name = response.artist_url_name
|
||||
creator =
|
||||
Domain::User::FaUser.find_or_initialize_by(url_name:) do |user|
|
||||
# TODO - bug in has_aux_table, attributes not initialized before
|
||||
# block is called
|
||||
user.name ||= response.artist_name
|
||||
user.full_name ||= response.artist_name
|
||||
end
|
||||
creator.save! if creator.new_record?
|
||||
post.creator = creator
|
||||
end
|
||||
|
||||
if post.keywords.blank? || post.keywords.empty?
|
||||
post.keywords = response.tags
|
||||
end
|
||||
|
||||
post_file = post.file
|
||||
post_file ||=
|
||||
post.build_file(url_str: response.file_url) do |post_file|
|
||||
post_file.last_status_code = 404
|
||||
post_file.state = "terminal_error"
|
||||
end
|
||||
if post_file.new_record?
|
||||
post_file.enqueue_job_after_save(
|
||||
Job::FaPostFurArchiverPostFileJob,
|
||||
{ post_file: },
|
||||
)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
post.save! if post
|
||||
post_file.save! if post_file
|
||||
end
|
||||
end
|
||||
@@ -2,8 +2,8 @@
|
||||
class Job::FaPostFurArchiverPostFileJob < Scraper::JobBase
|
||||
extend T::Sig
|
||||
include Domain::StaticFileJobHelper
|
||||
queue_as :fur_archiver
|
||||
|
||||
queue_as :static_file
|
||||
discard_on Scraper::JobBase::JobError, ActiveJob::DeserializationError
|
||||
|
||||
sig { override.returns(Symbol) }
|
||||
@@ -13,102 +13,95 @@ class Job::FaPostFurArchiverPostFileJob < Scraper::JobBase
|
||||
|
||||
sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform(args)
|
||||
post_file = T.cast(args[:post_file], Domain::PostFile)
|
||||
logger.tagged(make_arg_tag(post_file), make_arg_tag(post_file.post)) do
|
||||
handle(post_file)
|
||||
post = T.cast(args[:post], T.nilable(Domain::Post::FaPost))
|
||||
if post.nil?
|
||||
post_file = T.cast(args[:post_file], T.nilable(Domain::PostFile))
|
||||
fatal_error("no post or post file found, skipping") if post_file.nil?
|
||||
post = T.cast(post_file.post, T.nilable(Domain::Post::FaPost))
|
||||
fatal_error("no post found, skipping") if post.nil?
|
||||
end
|
||||
|
||||
# todo - try multiple post files?
|
||||
post_file =
|
||||
post
|
||||
.files
|
||||
.to_a
|
||||
.sort_by { |file| T.must(file.created_at) }
|
||||
.reverse
|
||||
.find do |file|
|
||||
url_str = file.url_str || next
|
||||
uri = Addressable::URI.parse(url_str)
|
||||
FaUriHelper.is_fa_cdn_host?(uri.host)
|
||||
end
|
||||
|
||||
fatal_error("no existing post file found, skipping") if post_file.nil?
|
||||
|
||||
logger.tagged(make_arg_tag(post), make_arg_tag(post_file)) do
|
||||
if post_file.state_ok? && post_file.last_status_code == 200
|
||||
logger.info("file already downloaded, skipping")
|
||||
return :ok
|
||||
end
|
||||
|
||||
unless post_file.last_status_code == 404
|
||||
logger.warn("last status code is not 404, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
unless post_file.state_terminal_error?
|
||||
logger.warn("post file not in terminal error state, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
file_url_str = post_file.url_str
|
||||
fatal_error("no file url str") unless file_url_str
|
||||
|
||||
url_parsed = FaUriHelper.parse_fa_media_url(file_url_str)
|
||||
fatal_error("failed to parse fa file url") unless url_parsed
|
||||
|
||||
creator_url_name = post.creator&.url_name
|
||||
fatal_error("no creator url name") unless creator_url_name
|
||||
|
||||
unless creator_url_name == url_parsed.url_name
|
||||
logger.tagged(
|
||||
make_tag("in_db", creator_url_name),
|
||||
make_tag("in_url", url_parsed.url_name),
|
||||
) { fatal_error("creator name mismatch") }
|
||||
end
|
||||
|
||||
next if try_from_furarchiver(post, url_parsed)
|
||||
try_from_tor(post, url_parsed)
|
||||
end
|
||||
end
|
||||
|
||||
FA_URL_PATTERN =
|
||||
%r{
|
||||
https://(d\.facdn\.net|d\.furaffinity\.net)/art/([^\/]+)/(\d+)/([^\/]+)
|
||||
}x
|
||||
|
||||
sig { params(post_file: Domain::PostFile).void }
|
||||
def handle(post_file)
|
||||
post = T.cast(post_file.post, Domain::Post::FaPost)
|
||||
|
||||
if post.file != post_file && post.file&.state_ok?
|
||||
logger.info("file already downloaded, deleting old file")
|
||||
post_file.destroy
|
||||
return
|
||||
end
|
||||
|
||||
if post_file.state_ok? && post_file.last_status_code == 200
|
||||
logger.info("file already downloaded, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
if post.tried_from_fur_archiver?
|
||||
logger.warn("already tried to download from fur archiver, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
unless post_file.last_status_code == 404
|
||||
logger.warn("last status code is not 404, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
unless post_file.state_terminal_error?
|
||||
logger.warn("post file not in terminal error state, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
user_url_name = post.creator&.url_name
|
||||
fatal_error("no user url name") unless user_url_name
|
||||
|
||||
fa_file_url_str = post_file.url_str
|
||||
fatal_error("no fa file url") unless fa_file_url_str
|
||||
|
||||
match = fa_file_url_str.match(FA_URL_PATTERN)
|
||||
unless match
|
||||
if fa_file_url_str.include?("#{user_url_name}/stories/")
|
||||
logger.warn("old stories URL, force rescan")
|
||||
post.reload
|
||||
Domain::Fa::Job::ScanPostJob.perform_now(
|
||||
{ post: post, force_scan: true },
|
||||
)
|
||||
post.reload
|
||||
unless post.state_ok?
|
||||
fatal_error("post not in ok state after rescan: #{post.state}")
|
||||
end
|
||||
return if post.file&.state_ok? || post.file&.state_pending?
|
||||
match = fa_file_url_str.match(FA_URL_PATTERN)
|
||||
unless match
|
||||
fatal_error("invalid fa file url after rescan: #{fa_file_url_str}")
|
||||
end
|
||||
else
|
||||
fatal_error("invalid fa file url: #{fa_file_url_str}")
|
||||
end
|
||||
end
|
||||
|
||||
unless url_user_url_name = match.captures[1]
|
||||
fatal_error("no user url name in url: #{fa_file_url_str}")
|
||||
end
|
||||
|
||||
unless url_file_name = match.captures[3]
|
||||
fatal_error("no file name in url: #{fa_file_url_str}")
|
||||
end
|
||||
|
||||
unless user_url_name == url_user_url_name
|
||||
logger.tagged(
|
||||
make_tag("in_db", user_url_name),
|
||||
make_tag("in_url", url_user_url_name),
|
||||
) { fatal_error("user name mismatch") }
|
||||
end
|
||||
|
||||
# returns true if the post file was found and downloaded
|
||||
sig do
|
||||
params(
|
||||
post: Domain::Post::FaPost,
|
||||
url_parsed: FaUriHelper::FaMediaUrlInfo,
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def try_from_furarchiver(post, url_parsed)
|
||||
fur_archiver_url_str =
|
||||
"https://furarchiver.net/File/View?artist=#{url_user_url_name}&filename=#{url_file_name}"
|
||||
"https://furarchiver.net/File/View?artist=#{url_parsed.url_name}&filename=#{url_parsed.filename_with_ts}"
|
||||
|
||||
post.tried_from_fur_archiver = true
|
||||
post_file = post.files.build(url_str: fur_archiver_url_str)
|
||||
archiver_post_file =
|
||||
post.files.find_or_create_by!(url_str: fur_archiver_url_str)
|
||||
|
||||
if archiver_post_file.state_ok?
|
||||
logger.warn("already downloaded from fur archiver, skipping")
|
||||
return true
|
||||
elsif archiver_post_file.state_terminal_error?
|
||||
logger.warn("previously failed to download from fur archiver, trying tor")
|
||||
return false
|
||||
end
|
||||
|
||||
begin
|
||||
response = http_client.get(fur_archiver_url_str)
|
||||
rescue Scraper::HttpClient::InvalidURLError,
|
||||
Curl::Err::HostResolutionError => e
|
||||
post_file.state_terminal_error!
|
||||
post_file.error_message = e.message
|
||||
archiver_post_file.state_terminal_error!
|
||||
archiver_post_file.error_message = e.message
|
||||
archiver_post_file.save!
|
||||
logger.error(
|
||||
format_tags(
|
||||
"invalid fur archiver url, terminal error state",
|
||||
@@ -116,14 +109,40 @@ class Job::FaPostFurArchiverPostFileJob < Scraper::JobBase
|
||||
make_tag("url", fur_archiver_url_str),
|
||||
),
|
||||
)
|
||||
return
|
||||
return false
|
||||
ensure
|
||||
post.save! if post
|
||||
post.tried_from_fur_archiver = true
|
||||
post.save!
|
||||
end
|
||||
|
||||
post_file.save!
|
||||
post.reload
|
||||
handle_file_download_response(archiver_post_file, response)
|
||||
return archiver_post_file.state_ok?
|
||||
end
|
||||
|
||||
handle_file_download_response(post_file, response)
|
||||
sig do
|
||||
params(
|
||||
post: Domain::Post::FaPost,
|
||||
url_parsed: FaUriHelper::FaMediaUrlInfo,
|
||||
).void
|
||||
end
|
||||
def try_from_tor(post, url_parsed)
|
||||
tor_path = "fa/#{url_parsed.url_name}/#{url_parsed.filename_with_ts}"
|
||||
tor_url_str =
|
||||
"http://g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion/#{tor_path}"
|
||||
|
||||
tor_post_file =
|
||||
post.files.find_by(url_str: tor_url_str) ||
|
||||
post.files.create!(url_str: tor_url_str)
|
||||
|
||||
if tor_post_file.state_ok?
|
||||
logger.warn("already downloaded from tor, skipping")
|
||||
return
|
||||
elsif tor_post_file.state_terminal_error?
|
||||
logger.warn("previously failed to download from tor, skipping")
|
||||
return
|
||||
end
|
||||
|
||||
response = tor_http_client.get(tor_url_str)
|
||||
handle_file_download_response(tor_post_file, response)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,12 +18,16 @@ class Scraper::JobBase < ApplicationJob
|
||||
@http_client = http_client
|
||||
end
|
||||
|
||||
sig { params(url: String).returns(Scraper::HttpClient::Response) }
|
||||
sig do
|
||||
params(url: T.any(String, Addressable::URI)).returns(
|
||||
Scraper::HttpClient::Response,
|
||||
)
|
||||
end
|
||||
def get(url)
|
||||
around_request(
|
||||
proc do
|
||||
@http_client.get(
|
||||
url,
|
||||
url.to_s,
|
||||
caused_by_entry: @job.causing_log_entry,
|
||||
use_http_cache: @job.use_http_cache?,
|
||||
)
|
||||
@@ -31,12 +35,16 @@ class Scraper::JobBase < ApplicationJob
|
||||
)
|
||||
end
|
||||
|
||||
sig { params(url: String).returns(Scraper::HttpClient::Response) }
|
||||
sig do
|
||||
params(url: T.any(String, Addressable::URI)).returns(
|
||||
Scraper::HttpClient::Response,
|
||||
)
|
||||
end
|
||||
def post(url)
|
||||
around_request(
|
||||
proc do
|
||||
@http_client.post(
|
||||
url,
|
||||
url.to_s,
|
||||
caused_by_entry: @job.causing_log_entry,
|
||||
use_http_cache: @job.use_http_cache?,
|
||||
)
|
||||
@@ -65,6 +73,7 @@ class Scraper::JobBase < ApplicationJob
|
||||
@deferred_jobs = T.let(Set.new, T::Set[DeferredJob])
|
||||
@suppressed_jobs = T.let(Set.new, T::Set[SuppressedJob])
|
||||
@http_client = T.let(nil, T.nilable(Scraper::HttpClient))
|
||||
@tor_http_client = T.let(nil, T.nilable(Scraper::HttpClient))
|
||||
@gallery_dl_client = T.let(nil, T.nilable(Scraper::GalleryDlClient))
|
||||
@first_log_entry = T.let(nil, T.nilable(HttpLogEntry))
|
||||
@last_log_entry = T.let(nil, T.nilable(HttpLogEntry))
|
||||
@@ -80,6 +89,12 @@ class Scraper::JobBase < ApplicationJob
|
||||
WrappedHttpClient.new(self, @http_client)
|
||||
end
|
||||
|
||||
sig { returns(WrappedHttpClient) }
|
||||
def tor_http_client
|
||||
@tor_http_client ||= Scraper::ClientFactory.get_tor_http_client
|
||||
WrappedHttpClient.new(self, @tor_http_client)
|
||||
end
|
||||
|
||||
sig { returns(Scraper::GalleryDlClient) }
|
||||
def gallery_dl_client
|
||||
@gallery_dl_client ||= Scraper::ClientFactory.get_gallery_dl_client
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# typed: true
|
||||
class Scraper::ClientFactory
|
||||
extend T::Sig
|
||||
|
||||
@http_clients = Concurrent::ThreadLocalVar.new() { {} }
|
||||
@gallery_dl_clients = Concurrent::ThreadLocalVar.new(nil)
|
||||
|
||||
@@ -48,6 +50,14 @@ class Scraper::ClientFactory
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_fuzzysearch_http_client
|
||||
if Rails.env.test?
|
||||
@http_client_mock || raise("no http client mock set")
|
||||
else
|
||||
_http_client_impl(:fuzzysearch, Scraper::FuzzysearchHttpClientConfig)
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_sofurry_http_client
|
||||
if Rails.env.test?
|
||||
@http_client_mock || raise("no http client mock set")
|
||||
@@ -80,6 +90,18 @@ class Scraper::ClientFactory
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_tor_http_client
|
||||
if Rails.env.test?
|
||||
@http_client_mock || raise("no http client mock set")
|
||||
else
|
||||
_http_client_impl(
|
||||
:tor,
|
||||
Scraper::TorHttpClientConfig,
|
||||
Scraper::TorCurlHttpPerformer,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def self._gallery_dl_client_impl
|
||||
@gallery_dl_clients.value ||=
|
||||
begin
|
||||
@@ -97,9 +119,20 @@ class Scraper::ClientFactory
|
||||
end
|
||||
end
|
||||
|
||||
def self._http_client_impl(key, config_klass)
|
||||
sig do
|
||||
params(
|
||||
key: Symbol,
|
||||
config_klass: T.class_of(Scraper::HttpClientConfig),
|
||||
performer_klass: T.class_of(Scraper::CurlHttpPerformer),
|
||||
).returns(Scraper::HttpClient)
|
||||
end
|
||||
def self._http_client_impl(
|
||||
key,
|
||||
config_klass,
|
||||
performer_klass = Scraper::CurlHttpPerformer
|
||||
)
|
||||
@http_clients.value[key] ||= begin
|
||||
Scraper::HttpClient.new(config_klass.new, Scraper::CurlHttpPerformer.new)
|
||||
Scraper::HttpClient.new(config_klass.new, performer_klass.new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,32 +38,33 @@ class Scraper::CurlHttpPerformer
|
||||
"direct"
|
||||
end
|
||||
|
||||
sig { params(request: Request).returns(Response) }
|
||||
sig(:final) { params(request: Request).returns(Response) }
|
||||
def do_request(request)
|
||||
do_request_impl(request)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(String) }
|
||||
def performed_by
|
||||
proxy_url = ENV["HTTP_PROXY_URL"]
|
||||
case proxy_url
|
||||
when nil
|
||||
"direct"
|
||||
when /airvpn-netherlands-proxy:(\d+)/
|
||||
"airvpn-1-netherlands"
|
||||
when /airvpn-san-jose-proxy:(\d+)/
|
||||
"airvpn-2-san-jose"
|
||||
else
|
||||
raise("Unknown proxy URL: #{proxy_url}")
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(request: Request).returns(Response) }
|
||||
def do_request_impl(request)
|
||||
curl = get_curl
|
||||
start_at = Time.now
|
||||
|
||||
proxy_url = ENV["HTTP_PROXY_URL"]
|
||||
performed_by =
|
||||
case proxy_url
|
||||
when nil
|
||||
"direct"
|
||||
when /airvpn-netherlands-proxy:(\d+)/
|
||||
"airvpn-1-netherlands"
|
||||
when /airvpn-san-jose-proxy:(\d+)/
|
||||
"airvpn-2-san-jose"
|
||||
else
|
||||
raise("Unknown proxy URL: #{proxy_url}")
|
||||
end
|
||||
|
||||
curl.proxy_url = proxy_url
|
||||
curl.timeout = 30
|
||||
curl.url = request.uri.normalize.to_s
|
||||
curl.follow_location = request.follow_redirects
|
||||
@@ -120,7 +121,7 @@ class Scraper::CurlHttpPerformer
|
||||
response_headers:,
|
||||
response_time_ms:,
|
||||
body: body_str,
|
||||
performed_by:,
|
||||
performed_by: performed_by,
|
||||
)
|
||||
end
|
||||
|
||||
@@ -131,6 +132,8 @@ class Scraper::CurlHttpPerformer
|
||||
t.thread_variable_set(:curl, Curl::Easy.new)
|
||||
end
|
||||
curl = t.thread_variable_get(:curl)
|
||||
proxy_url = ENV["HTTP_PROXY_URL"]
|
||||
curl.proxy_url = proxy_url
|
||||
curl.headers = {}
|
||||
curl
|
||||
end
|
||||
|
||||
89
app/lib/scraper/fuzzysearch_api_client.rb
Normal file
89
app/lib/scraper/fuzzysearch_api_client.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Scraper::FuzzysearchApiClient
|
||||
extend T::Sig
|
||||
include HasColorLogger
|
||||
|
||||
API_BASE_URL = "https://api-next.fuzzysearch.net"
|
||||
API_PATH_FA_ID_INFO = "/v1/file/furaffinity"
|
||||
|
||||
sig { params(http_client: Scraper::JobBase::WrappedHttpClient).void }
|
||||
def initialize(http_client)
|
||||
@http_client = http_client
|
||||
end
|
||||
|
||||
class FaIdInfo < T::ImmutableStruct
|
||||
include T::Struct::ActsAsComparable
|
||||
|
||||
const :log_entry, HttpLogEntry
|
||||
const :json, T::Hash[String, T.untyped]
|
||||
const :fa_id, Integer
|
||||
const :artist_url_name, String
|
||||
const :artist_name, String
|
||||
const :deleted, T::Boolean
|
||||
const :file_url, String
|
||||
const :file_sha256, String
|
||||
const :tags, T::Array[String]
|
||||
end
|
||||
|
||||
sig { params(fa_id: Integer).returns(T.any(HttpLogEntry, FaIdInfo)) }
|
||||
def search_fa_id_info(fa_id)
|
||||
url = Addressable::URI.parse("#{API_BASE_URL}#{API_PATH_FA_ID_INFO}")
|
||||
url.query_values = { search: fa_id.to_s }
|
||||
response = @http_client.get(url)
|
||||
if response.status_code != 200
|
||||
logger.error(
|
||||
format_tags(
|
||||
make_tag("status_code", response.status_code),
|
||||
make_tag("uri", url.to_s),
|
||||
"fuzzysearch query failed",
|
||||
),
|
||||
)
|
||||
return response.log_entry
|
||||
end
|
||||
|
||||
json = JSON.parse(response.body)
|
||||
unless json.is_a?(Array)
|
||||
logger.error("fuzzysearch response is not an array")
|
||||
return response.log_entry
|
||||
end
|
||||
if json.empty?
|
||||
logger.error("fuzzysearch response is empty")
|
||||
return response.log_entry
|
||||
end
|
||||
json = json.first
|
||||
unless json.is_a?(Hash)
|
||||
logger.error("fuzzysearch response is not a hash")
|
||||
return response.log_entry
|
||||
end
|
||||
|
||||
file_url = json["url"]
|
||||
if file_url.blank?
|
||||
logger.error("fuzzysearch response has no file url")
|
||||
return response.log_entry
|
||||
end
|
||||
|
||||
url_parsed = FaUriHelper.parse_fa_media_url(file_url)
|
||||
if url_parsed.blank?
|
||||
logger.error(
|
||||
format_tags(make_tag("file_url", file_url), "failed to parse file url"),
|
||||
)
|
||||
return response.log_entry
|
||||
end
|
||||
|
||||
FaIdInfo.new(
|
||||
log_entry: response.log_entry,
|
||||
json:,
|
||||
fa_id: json["id"],
|
||||
artist_url_name: url_parsed.url_name,
|
||||
artist_name: json["artist"],
|
||||
deleted: json["deleted"],
|
||||
file_url:,
|
||||
file_sha256: json["sha256"],
|
||||
tags: json["tags"],
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
end
|
||||
49
app/lib/scraper/fuzzysearch_http_client_config.rb
Normal file
49
app/lib/scraper/fuzzysearch_http_client_config.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Scraper::FuzzysearchHttpClientConfig < Scraper::HttpClientConfig
|
||||
API_KEY_STATE_KEY = "fuzzysearch-api-key"
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
api_key!
|
||||
end
|
||||
|
||||
sig { override.returns(T.nilable(T::Array[T.untyped])) }
|
||||
def cookies
|
||||
[]
|
||||
end
|
||||
sig { override.returns(T::Array[[String, Numeric]]) }
|
||||
def ratelimit
|
||||
[["api-next.fuzzysearch.net", 1.0]]
|
||||
end
|
||||
|
||||
sig { override.returns(Integer) }
|
||||
def redirect_limit
|
||||
2
|
||||
end
|
||||
|
||||
sig { override.returns(T::Array[String]) }
|
||||
def allowed_domains
|
||||
%w[api-next.fuzzysearch.net]
|
||||
end
|
||||
|
||||
sig do
|
||||
override
|
||||
.params(request: Scraper::CurlHttpPerformer::Request)
|
||||
.returns(Scraper::CurlHttpPerformer::Request)
|
||||
end
|
||||
def map_request(request)
|
||||
request.request_headers["X-Api-Key"] = api_key!
|
||||
request.request_headers["Accept"] = "application/json"
|
||||
request
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(String) }
|
||||
def api_key!
|
||||
GlobalState.get(API_KEY_STATE_KEY) ||
|
||||
raise("fuzzysearch api key is not set")
|
||||
end
|
||||
end
|
||||
28
app/lib/scraper/tor_curl_http_performer.rb
Normal file
28
app/lib/scraper/tor_curl_http_performer.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Scraper::TorCurlHttpPerformer < Scraper::CurlHttpPerformer
|
||||
extend T::Sig
|
||||
|
||||
sig { override.returns(String) }
|
||||
def performed_by
|
||||
"tor-1"
|
||||
end
|
||||
|
||||
sig { override.returns(Curl::Easy) }
|
||||
def get_curl
|
||||
t = Thread.current
|
||||
unless t.thread_variable?(:curl)
|
||||
t.thread_variable_set(:curl, Curl::Easy.new)
|
||||
end
|
||||
curl = T.cast(t.thread_variable_get(:curl), Curl::Easy)
|
||||
curl.proxy_url = "socks5h://tor:9050"
|
||||
curl.headers = {
|
||||
"User-Agent" =>
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0",
|
||||
"Accept-Encoding" => "gzip, deflate",
|
||||
"Connection" => "keep-alive",
|
||||
}
|
||||
curl
|
||||
end
|
||||
end
|
||||
29
app/lib/scraper/tor_http_client_config.rb
Normal file
29
app/lib/scraper/tor_http_client_config.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Scraper::TorHttpClientConfig < Scraper::HttpClientConfig
|
||||
TOR_ARCHIVE_HOST =
|
||||
"g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion"
|
||||
|
||||
extend T::Sig
|
||||
|
||||
sig { override.returns(T.nilable(T::Array[T::Hash[Symbol, T.untyped]])) }
|
||||
def cookies
|
||||
nil
|
||||
end
|
||||
|
||||
sig { override.returns(T::Array[[String, Numeric]]) }
|
||||
def ratelimit
|
||||
[[TOR_ARCHIVE_HOST, 1.0]]
|
||||
end
|
||||
|
||||
sig { override.returns(Integer) }
|
||||
def redirect_limit
|
||||
2
|
||||
end
|
||||
|
||||
sig { override.returns(T::Array[String]) }
|
||||
def allowed_domains
|
||||
[TOR_ARCHIVE_HOST]
|
||||
end
|
||||
end
|
||||
81
app/lib/tasks/fa/query_missing_posts_from_fuzzysearch.rb
Normal file
81
app/lib/tasks/fa/query_missing_posts_from_fuzzysearch.rb
Normal file
@@ -0,0 +1,81 @@
|
||||
# typed: strict
|
||||
class Tasks::Fa::QueryMissingPostsFromFuzzysearch < EnqueueJobBase
|
||||
extend T::Sig
|
||||
include Domain::Fa::HasCountFailedInQueue
|
||||
|
||||
sig { params(start_at: T.nilable(String), kwargs: T.untyped).void }
|
||||
def initialize(start_at: nil, **kwargs)
|
||||
super(**kwargs)
|
||||
@start_at = T.let(get_progress(start_at)&.to_i, T.nilable(Integer))
|
||||
end
|
||||
|
||||
sig { override.returns(String) }
|
||||
def progress_key
|
||||
"fa-query-missing-posts-from-fuzzysearch"
|
||||
end
|
||||
|
||||
sig { override.void }
|
||||
def start_enqueuing
|
||||
greatest_ok_post_fa_id =
|
||||
Domain::Post::FaPost.where(state: :ok).maximum(:fa_id)
|
||||
|
||||
query =
|
||||
Domain::Post::FaPost.where(state: :removed, fuzzysearch_checked_at: nil)
|
||||
# clamp to greatest ok post fa_id
|
||||
query =
|
||||
query.where(fa_id: ..greatest_ok_post_fa_id) if greatest_ok_post_fa_id
|
||||
query = query.where(fa_id: ..@start_at) if @start_at
|
||||
query = query.where.missing(:file).order(fa_id: :desc)
|
||||
|
||||
log("finding greatest qualifying fa_id...")
|
||||
greatest_post_fa_id = query.first&.fa_id
|
||||
|
||||
log("counting posts...")
|
||||
count = query.count
|
||||
puts "number of posts to process: #{count}"
|
||||
pb = create_progress_bar(count)
|
||||
|
||||
while greatest_post_fa_id
|
||||
posts = query.where(fa_id: ..greatest_post_fa_id).limit(32).to_a
|
||||
break if posts.empty?
|
||||
|
||||
posts.each do |post|
|
||||
break if interrupted?
|
||||
|
||||
enqueue do
|
||||
Domain::Fa::Job::ScanFuzzysearchJob.perform_later(
|
||||
{ fa_id: post.fa_id },
|
||||
)
|
||||
end
|
||||
|
||||
post_desc =
|
||||
"#{(post.creator&.to_param || "(none)").rjust(20)} / #{post.to_param}".ljust(
|
||||
40,
|
||||
)
|
||||
log("migrate post :: #{post_desc}") if pb.progress % 10 == 0
|
||||
rescue StandardError
|
||||
log("error processing post :: #{post_desc}")
|
||||
ensure
|
||||
pb.progress = [pb.progress + 1, pb.total].min
|
||||
end
|
||||
|
||||
last_processed_fa_id = posts.map(&:fa_id).compact.min
|
||||
if last_processed_fa_id
|
||||
save_progress(last_processed_fa_id.to_s)
|
||||
greatest_post_fa_id = last_processed_fa_id - 1
|
||||
else
|
||||
break
|
||||
end
|
||||
|
||||
# Check for interruption after processing batch
|
||||
break if interrupted?
|
||||
end
|
||||
|
||||
log("finished")
|
||||
end
|
||||
|
||||
sig { override.returns(Integer) }
|
||||
def queue_size
|
||||
count_failed_in_queue("fuzzysearch")
|
||||
end
|
||||
end
|
||||
@@ -34,7 +34,7 @@ module BelongsToWithCounterCache
|
||||
association(association_name).target,
|
||||
T.nilable(ActiveRecord::Base),
|
||||
)
|
||||
if target.send(counter_name_column).nil?
|
||||
if target.send(counter_name_column).nil? && !target.new_record?
|
||||
target.class.reset_counters(target.id, inverse_association_name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,14 +21,20 @@ class Domain::Post::FaPost < Domain::Post
|
||||
attr_json :first_gallery_page_id, :integer
|
||||
attr_json :first_seen_entry_id, :integer
|
||||
|
||||
attr_json :fuzzysearch_checked_at, ActiveModelUtcTimeValue.new
|
||||
attr_json :fuzzysearch_json, ActiveModel::Type::Value.new
|
||||
attr_json :fuzzysearch_entry_id, :integer
|
||||
|
||||
# TODO - convert `file` to Domain::PostFile::FaPostFile and
|
||||
# move this to Domain::PostFile::FaPostFile
|
||||
attr_json :tried_from_fur_archiver, :boolean, default: false
|
||||
attr_json :tried_from_tor, :boolean, default: false
|
||||
|
||||
belongs_to :last_user_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_browse_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_gallery_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_seen_entry, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :fuzzysearch_entry, class_name: "::HttpLogEntry", optional: true
|
||||
|
||||
has_single_file!
|
||||
has_single_creator! Domain::User::FaUser
|
||||
@@ -177,7 +183,7 @@ class Domain::Post::FaPost < Domain::Post
|
||||
pa = super
|
||||
return pa unless pa.nil?
|
||||
|
||||
if file_url_str = file&.url_str
|
||||
for file_url_str in files.map(&:url_str).compact
|
||||
parsed = FaUriHelper.parse_fa_media_url(file_url_str)
|
||||
return parsed.original_file_posted_at.in_time_zone("UTC") if parsed
|
||||
end
|
||||
@@ -199,4 +205,21 @@ class Domain::Post::FaPost < Domain::Post
|
||||
def tags_for_view
|
||||
keywords.map { |value| TagForView.new(category: :general, value:) }
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Domain::PostFile)) }
|
||||
def fur_archiver_post_file
|
||||
files.to_a.find do |file|
|
||||
uri = Addressable::URI.parse(file.url_str)
|
||||
uri.host == "furarchiver.net"
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Domain::PostFile)) }
|
||||
def tor_post_file
|
||||
files.to_a.find do |file|
|
||||
uri = Addressable::URI.parse(file.url_str)
|
||||
uri.host ==
|
||||
"g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,7 @@ class HttpLogEntry < ReduxApplicationRecord
|
||||
serverhost-1
|
||||
airvpn-1-netherlands
|
||||
airvpn-2-san-jose
|
||||
tor-1
|
||||
],
|
||||
prefix: true
|
||||
|
||||
|
||||
8
app/views/domain/posts/_title_stat.html.erb
Normal file
8
app/views/domain/posts/_title_stat.html.erb
Normal file
@@ -0,0 +1,8 @@
|
||||
<span>
|
||||
<i class="fa-solid <%= icon_class %> mr-1"></i>
|
||||
<%= label %>: <% if value.present? %>
|
||||
<%= value %>
|
||||
<% else %>
|
||||
<span class="text-slate-400"> - </span>
|
||||
<% end %>
|
||||
</span>
|
||||
@@ -1,18 +1,24 @@
|
||||
<span>
|
||||
<i class="fa-solid fa-eye mr-1"></i>
|
||||
Views: <%= post.num_views %>
|
||||
</span>
|
||||
<span>
|
||||
<i class="fa-solid fa-comment mr-1"></i>
|
||||
Comments: <%= post.num_comments %>
|
||||
</span>
|
||||
<span>
|
||||
<i class="fa-solid fa-calendar-days mr-1"></i>
|
||||
Status: <%= post.status_for_view %>
|
||||
</span>
|
||||
<% if policy(post).view_tried_from_fur_archiver? && post.tried_from_fur_archiver? %>
|
||||
<span>
|
||||
<i class="fa-solid fa-download mr-1"></i>
|
||||
FurArchiver
|
||||
</span>
|
||||
<%= render partial: "domain/posts/title_stat", locals: { label: "Views", value: post.num_views, icon_class: "fa-eye" } %>
|
||||
<%= render partial: "domain/posts/title_stat", locals: { label: "Comments", value: post.num_comments, icon_class: "fa-comment" } %>
|
||||
<%= render partial: "domain/posts/title_stat", locals: { label: "Status", value: post.status_for_view, icon_class: "fa-calendar-days" } %>
|
||||
<% if policy(post).view_tried_from_fur_archiver? %>
|
||||
<% if post.fuzzysearch_checked_at? %>
|
||||
<% hle = post.fuzzysearch_entry %>
|
||||
<span>
|
||||
<i class="fa-solid fa-search mr-1"></i>
|
||||
<%= link_to "FuzzySearch", log_entry_path(hle), title: post.fuzzysearch_checked_at&.strftime("%Y-%m-%d %H:%M:%S"), class: "text-blue-600" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if (hle = post.fur_archiver_post_file&.log_entry) %>
|
||||
<span>
|
||||
<i class="fa-solid fa-download mr-1"></i>
|
||||
<%= link_to "FurArchiver", log_entry_path(hle), title: hle.requested_at&.strftime("%Y-%m-%d %H:%M:%S"), class: "text-blue-600" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if (hle = post.tor_post_file&.log_entry) %>
|
||||
<span>
|
||||
<i class="fa-solid fa-mask mr-1"></i>
|
||||
<%= link_to "Tor", log_entry_path(hle), title: hle.requested_at&.strftime("%Y-%m-%d %H:%M:%S"), class: "text-blue-600" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: task-72
|
||||
title: Investigate removed PostFile records for terminal_error transition
|
||||
status: To Do
|
||||
assignee: []
|
||||
created_date: '2025-07-25'
|
||||
labels: []
|
||||
dependencies: []
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Analyze Domain::PostFile records currently in 'removed' state to determine if they should be transitioned to terminal_error state instead. This will help ensure proper state management and potentially improve job processing logic.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Analysis of all removed PostFile records is complete
|
||||
- [ ] Criteria for terminal_error transition is documented
|
||||
- [ ] Recommendation for state transition approach is provided
|
||||
- [ ] If applicable
|
||||
- [ ] migration strategy is outlined
|
||||
@@ -0,0 +1,10 @@
|
||||
class AddFuzzysearchCheckToFaPosts < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :domain_fa_posts_fa_aux, :fuzzysearch_checked_at, :datetime
|
||||
add_reference :domain_fa_posts_fa_aux,
|
||||
:fuzzysearch_log_entry,
|
||||
foreign_key: {
|
||||
to_table: :log_entries,
|
||||
}
|
||||
end
|
||||
end
|
||||
22
db/migrate/20250724213505_remove_unused_indexes.rb
Normal file
22
db/migrate/20250724213505_remove_unused_indexes.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RemoveUnusedIndexes < ActiveRecord::Migration[7.2]
|
||||
extend T::Sig
|
||||
|
||||
sig { void }
|
||||
def up
|
||||
remove_index :domain_user_post_favs,
|
||||
name: "idx_domain_user_post_favs_on_explicit_time"
|
||||
remove_index :domain_user_post_favs,
|
||||
name: "idx_domain_user_post_favs_on_inferred_time"
|
||||
remove_index :domain_post_files, column: :blob_sha256
|
||||
remove_index :http_log_entries, column: :response_headers_id
|
||||
remove_index :http_log_entries, column: :request_headers_id
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -3330,13 +3330,6 @@ CREATE UNIQUE INDEX idx_domain_post_groups_on_sofurry_id ON public.domain_post_g
|
||||
CREATE UNIQUE INDEX idx_domain_posts_on_sofurry_id ON public.domain_posts USING btree ((((json_attributes ->> 'sofurry_id'::text))::integer)) WHERE (type = 'Domain::Post::SofurryPost'::public.domain_post_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_user_post_favs_on_explicit_time; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx_domain_user_post_favs_on_explicit_time ON public.domain_user_post_favs USING btree ((((json_attributes ->> 'explicit_time'::text))::integer)) WHERE (type = 'Domain::UserPostFav::FaUserPostFav'::public.domain_user_post_fav_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_user_post_favs_on_fav_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3344,13 +3337,6 @@ CREATE INDEX idx_domain_user_post_favs_on_explicit_time ON public.domain_user_po
|
||||
CREATE UNIQUE INDEX idx_domain_user_post_favs_on_fav_id ON public.domain_user_post_favs USING btree ((((json_attributes ->> 'fav_id'::text))::integer)) WHERE (type = 'Domain::UserPostFav::FaUserPostFav'::public.domain_user_post_fav_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_user_post_favs_on_inferred_time; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx_domain_user_post_favs_on_inferred_time ON public.domain_user_post_favs USING btree ((((json_attributes ->> 'inferred_time'::text))::integer)) WHERE (type = 'Domain::UserPostFav::FaUserPostFav'::public.domain_user_post_fav_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_users_e621_on_name_lower; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3918,13 +3904,6 @@ CREATE INDEX index_domain_post_files_inkbunny_aux_on_base_table_id ON public.dom
|
||||
CREATE INDEX index_domain_post_files_inkbunny_aux_on_ib_id ON public.domain_post_files_inkbunny_aux USING btree (ib_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_post_files_on_blob_sha256; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_post_files_on_blob_sha256 ON public.domain_post_files USING btree (blob_sha256);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_post_files_on_log_entry_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -4443,20 +4422,6 @@ CREATE INDEX index_good_jobs_on_scheduled_at ON public.good_jobs USING btree (sc
|
||||
CREATE INDEX index_http_log_entries_on_caused_by_id ON public.http_log_entries USING btree (caused_by_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_http_log_entries_on_request_headers_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_http_log_entries_on_request_headers_id ON public.http_log_entries USING btree (request_headers_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_http_log_entries_on_response_headers_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_http_log_entries_on_response_headers_id ON public.http_log_entries USING btree (response_headers_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_http_log_entries_on_response_sha256; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5297,6 +5262,7 @@ ALTER TABLE ONLY public.domain_twitter_tweets
|
||||
SET search_path TO "$user", public;
|
||||
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20250724213505'),
|
||||
('20250723194407'),
|
||||
('20250723193659'),
|
||||
('20250722235434'),
|
||||
|
||||
10
rake/fa.rake
10
rake/fa.rake
@@ -96,6 +96,16 @@ namespace :fa do
|
||||
loop { sleep poll_duration if enqueuer.run_once == :sleep }
|
||||
end
|
||||
|
||||
desc "Pull missing post information from FuzzySearch"
|
||||
task pull_missing_post_info_from_fuzzysearch: %i[
|
||||
set_logger_stdout
|
||||
environment
|
||||
] do
|
||||
Tasks::Fa::QueryMissingPostsFromFuzzysearch.new(
|
||||
start_at: ENV["start_at"],
|
||||
).run
|
||||
end
|
||||
|
||||
desc "run a single browse page job"
|
||||
task browse_page_job: %i[set_logger_stdout environment] do
|
||||
Domain::Fa::Job::BrowsePageJob.set(
|
||||
|
||||
1
sorbet/rbi/dsl/application_controller.rbi
generated
1
sorbet/rbi/dsl/application_controller.rbi
generated
@@ -43,6 +43,7 @@ class ApplicationController
|
||||
include ::Domain::Users::FaUsersHelper
|
||||
include ::Domain::VisualSearchHelper
|
||||
include ::DomainSourceHelper
|
||||
include ::FaUriHelper
|
||||
include ::GoodJobHelper
|
||||
include ::IpAddressHelper
|
||||
include ::TimestampHelper
|
||||
|
||||
1
sorbet/rbi/dsl/devise_controller.rbi
generated
1
sorbet/rbi/dsl/devise_controller.rbi
generated
@@ -40,6 +40,7 @@ class DeviseController
|
||||
include ::Domain::Users::FaUsersHelper
|
||||
include ::Domain::VisualSearchHelper
|
||||
include ::DomainSourceHelper
|
||||
include ::FaUriHelper
|
||||
include ::GoodJobHelper
|
||||
include ::IpAddressHelper
|
||||
include ::TimestampHelper
|
||||
|
||||
27
sorbet/rbi/dsl/domain/fa/job/scan_fuzzysearch_job.rbi
generated
Normal file
27
sorbet/rbi/dsl/domain/fa/job/scan_fuzzysearch_job.rbi
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Domain::Fa::Job::ScanFuzzysearchJob`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Domain::Fa::Job::ScanFuzzysearchJob`.
|
||||
|
||||
|
||||
class Domain::Fa::Job::ScanFuzzysearchJob
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::Fa::Job::ScanFuzzysearchJob).void)
|
||||
).returns(T.any(Domain::Fa::Job::ScanFuzzysearchJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
@@ -632,61 +632,6 @@ class Domain::Factors::UserPostFavPostFactors
|
||||
end
|
||||
|
||||
module GeneratedAttributeMethods
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def created_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_was; end
|
||||
|
||||
sig { void }
|
||||
def created_at_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def embedding; end
|
||||
|
||||
@@ -822,9 +767,6 @@ class Domain::Factors::UserPostFavPostFactors
|
||||
sig { void }
|
||||
def post_id_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_created_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_embedding!; end
|
||||
|
||||
@@ -834,15 +776,6 @@ class Domain::Factors::UserPostFavPostFactors
|
||||
sig { void }
|
||||
def restore_post_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_updated_at!; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_created_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_created_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_embedding; end
|
||||
|
||||
@@ -861,70 +794,6 @@ class Domain::Factors::UserPostFavPostFactors
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_post_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def updated_at_will_change!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_created_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_embedding?; end
|
||||
|
||||
@@ -933,9 +802,6 @@ class Domain::Factors::UserPostFavPostFactors
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_post_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_updated_at?; end
|
||||
end
|
||||
|
||||
module GeneratedRelationMethods
|
||||
|
||||
@@ -632,61 +632,6 @@ class Domain::Factors::UserPostFavUserFactors
|
||||
end
|
||||
|
||||
module GeneratedAttributeMethods
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def created_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_was; end
|
||||
|
||||
sig { void }
|
||||
def created_at_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def embedding; end
|
||||
|
||||
@@ -777,27 +722,15 @@ class Domain::Factors::UserPostFavUserFactors
|
||||
sig { void }
|
||||
def id_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_created_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_embedding!; end
|
||||
|
||||
sig { void }
|
||||
def restore_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_updated_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_user_id!; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_created_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_created_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_embedding; end
|
||||
|
||||
@@ -810,73 +743,12 @@ class Domain::Factors::UserPostFavUserFactors
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_user_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_user_id?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def updated_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def user_id; end
|
||||
|
||||
@@ -922,18 +794,12 @@ class Domain::Factors::UserPostFavUserFactors
|
||||
sig { void }
|
||||
def user_id_will_change!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_created_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_embedding?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_user_id?; end
|
||||
end
|
||||
|
||||
@@ -632,61 +632,6 @@ class Domain::Factors::UserUserFollowFromFactors
|
||||
end
|
||||
|
||||
module GeneratedAttributeMethods
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def created_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_was; end
|
||||
|
||||
sig { void }
|
||||
def created_at_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def embedding; end
|
||||
|
||||
@@ -777,27 +722,15 @@ class Domain::Factors::UserUserFollowFromFactors
|
||||
sig { void }
|
||||
def id_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_created_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_embedding!; end
|
||||
|
||||
sig { void }
|
||||
def restore_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_updated_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_user_id!; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_created_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_created_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_embedding; end
|
||||
|
||||
@@ -810,73 +743,12 @@ class Domain::Factors::UserUserFollowFromFactors
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_user_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_user_id?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def updated_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def user_id; end
|
||||
|
||||
@@ -922,18 +794,12 @@ class Domain::Factors::UserUserFollowFromFactors
|
||||
sig { void }
|
||||
def user_id_will_change!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_created_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_embedding?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_user_id?; end
|
||||
end
|
||||
|
||||
@@ -632,61 +632,6 @@ class Domain::Factors::UserUserFollowToFactors
|
||||
end
|
||||
|
||||
module GeneratedAttributeMethods
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def created_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def created_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def created_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def created_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def created_at_was; end
|
||||
|
||||
sig { void }
|
||||
def created_at_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def embedding; end
|
||||
|
||||
@@ -777,27 +722,15 @@ class Domain::Factors::UserUserFollowToFactors
|
||||
sig { void }
|
||||
def id_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_created_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_embedding!; end
|
||||
|
||||
sig { void }
|
||||
def restore_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_updated_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_user_id!; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_created_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_created_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_embedding; end
|
||||
|
||||
@@ -810,73 +743,12 @@ class Domain::Factors::UserUserFollowToFactors
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_user_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_user_id?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def updated_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_change_to_be_saved; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def updated_at_previous_change; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
def updated_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def user_id; end
|
||||
|
||||
@@ -922,18 +794,12 @@ class Domain::Factors::UserUserFollowToFactors
|
||||
sig { void }
|
||||
def user_id_will_change!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_created_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_embedding?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_updated_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_user_id?; end
|
||||
end
|
||||
|
||||
89
sorbet/rbi/dsl/domain/post/e621_post.rbi
generated
89
sorbet/rbi/dsl/domain/post/e621_post.rbi
generated
@@ -446,6 +446,9 @@ class Domain::Post::E621Post
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_caused_by_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostsE621Aux) }
|
||||
def build_e621_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile) }
|
||||
def build_file(*args, &blk); end
|
||||
|
||||
@@ -485,6 +488,12 @@ class Domain::Post::E621Post
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_caused_by_entry!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostsE621Aux) }
|
||||
def create_e621_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostsE621Aux) }
|
||||
def create_e621_aux!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile) }
|
||||
def create_file(*args, &blk); end
|
||||
|
||||
@@ -527,6 +536,12 @@ class Domain::Post::E621Post
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::UserPostFav) }
|
||||
def create_user_post_fav!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::DomainPostsE621Aux)) }
|
||||
def e621_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainPostsE621Aux)).void }
|
||||
def e621_aux=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faving_user_ids; end
|
||||
|
||||
@@ -622,6 +637,9 @@ class Domain::Post::E621Post
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_caused_by_entry; end
|
||||
|
||||
sig { returns(T.nilable(::DomainPostsE621Aux)) }
|
||||
def reload_e621_aux; end
|
||||
|
||||
sig { returns(T.nilable(::Domain::PostFile)) }
|
||||
def reload_file; end
|
||||
|
||||
@@ -646,6 +664,9 @@ class Domain::Post::E621Post
|
||||
sig { void }
|
||||
def reset_caused_by_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_e621_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_file; end
|
||||
|
||||
@@ -1178,16 +1199,16 @@ class Domain::Post::E621Post
|
||||
sig { void }
|
||||
def e621_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at; end
|
||||
|
||||
sig { params(value: T.nilable(::Time)).returns(T.nilable(::Time)) }
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def e621_updated_at?; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
@@ -1196,28 +1217,38 @@ class Domain::Post::E621Post
|
||||
sig { returns(T::Boolean) }
|
||||
def e621_updated_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def e621_updated_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def e621_updated_at_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def e621_updated_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def e621_updated_at_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def e621_updated_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def e621_updated_at_was; end
|
||||
|
||||
sig { void }
|
||||
@@ -2046,7 +2077,7 @@ class Domain::Post::E621Post
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_e621_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_e621_updated_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
@@ -2154,7 +2185,7 @@ class Domain::Post::E621Post
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_scanned_post_favs_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
@@ -2304,16 +2335,16 @@ class Domain::Post::E621Post
|
||||
sig { void }
|
||||
def scan_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at; end
|
||||
|
||||
sig { params(value: T.nilable(::Time)).returns(T.nilable(::Time)) }
|
||||
sig { params(value: T.nilable(::ActiveSupport::TimeWithZone)).returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def scanned_post_favs_at?; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
@@ -2322,28 +2353,38 @@ class Domain::Post::E621Post
|
||||
sig { returns(T::Boolean) }
|
||||
def scanned_post_favs_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def scanned_post_favs_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def scanned_post_favs_at_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def scanned_post_favs_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def scanned_post_favs_at_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
sig do
|
||||
params(
|
||||
from: T.nilable(::ActiveSupport::TimeWithZone),
|
||||
to: T.nilable(::ActiveSupport::TimeWithZone)
|
||||
).returns(T::Boolean)
|
||||
end
|
||||
def scanned_post_favs_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
|
||||
def scanned_post_favs_at_was; end
|
||||
|
||||
sig { void }
|
||||
|
||||
255
sorbet/rbi/dsl/domain/post/fa_post.rbi
generated
255
sorbet/rbi/dsl/domain/post/fa_post.rbi
generated
@@ -488,6 +488,9 @@ class Domain::Post::FaPost
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_first_seen_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_fuzzysearch_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_last_submission_log_entry(*args, &blk); end
|
||||
|
||||
@@ -530,6 +533,12 @@ class Domain::Post::FaPost
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_first_seen_entry!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_fuzzysearch_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_fuzzysearch_entry!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_submission_log_entry(*args, &blk); end
|
||||
|
||||
@@ -630,6 +639,18 @@ class Domain::Post::FaPost
|
||||
sig { returns(T::Boolean) }
|
||||
def first_seen_entry_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def fuzzysearch_entry; end
|
||||
|
||||
sig { params(value: T.nilable(::HttpLogEntry)).void }
|
||||
def fuzzysearch_entry=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_entry_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_entry_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def last_submission_log_entry; end
|
||||
|
||||
@@ -669,6 +690,9 @@ class Domain::Post::FaPost
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_first_seen_entry; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_fuzzysearch_entry; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_last_submission_log_entry; end
|
||||
|
||||
@@ -696,6 +720,9 @@ class Domain::Post::FaPost
|
||||
sig { void }
|
||||
def reset_first_seen_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_fuzzysearch_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_last_submission_log_entry; end
|
||||
|
||||
@@ -1264,6 +1291,141 @@ class Domain::Post::FaPost
|
||||
sig { void }
|
||||
def first_seen_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at; end
|
||||
|
||||
sig { params(value: T.nilable(::Time)).returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_checked_at?; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_checked_at_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_checked_at_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
def fuzzysearch_checked_at_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
def fuzzysearch_checked_at_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
def fuzzysearch_checked_at_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
def fuzzysearch_checked_at_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Time), to: T.nilable(::Time)).returns(T::Boolean) }
|
||||
def fuzzysearch_checked_at_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def fuzzysearch_checked_at_was; end
|
||||
|
||||
sig { void }
|
||||
def fuzzysearch_checked_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_entry_id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_entry_id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def fuzzysearch_entry_id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def fuzzysearch_entry_id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def fuzzysearch_entry_id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def fuzzysearch_entry_id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def fuzzysearch_entry_id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def fuzzysearch_entry_id_was; end
|
||||
|
||||
sig { void }
|
||||
def fuzzysearch_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json; end
|
||||
|
||||
sig { params(value: T.untyped).returns(T.untyped) }
|
||||
def fuzzysearch_json=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_json?; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def fuzzysearch_json_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def fuzzysearch_json_change; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def fuzzysearch_json_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def fuzzysearch_json_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def fuzzysearch_json_previous_change; end
|
||||
|
||||
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
||||
def fuzzysearch_json_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json_previously_was; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def fuzzysearch_json_was; end
|
||||
|
||||
sig { void }
|
||||
def fuzzysearch_json_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def gender; end
|
||||
|
||||
@@ -1790,6 +1952,15 @@ class Domain::Post::FaPost
|
||||
sig { void }
|
||||
def restore_first_seen_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_fuzzysearch_checked_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_fuzzysearch_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_fuzzysearch_json!; end
|
||||
|
||||
sig { void }
|
||||
def restore_gender!; end
|
||||
|
||||
@@ -1844,6 +2015,9 @@ class Domain::Post::FaPost
|
||||
sig { void }
|
||||
def restore_tried_from_fur_archiver!; end
|
||||
|
||||
sig { void }
|
||||
def restore_tried_from_tor!; end
|
||||
|
||||
sig { void }
|
||||
def restore_type!; end
|
||||
|
||||
@@ -1892,6 +2066,24 @@ class Domain::Post::FaPost
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_first_seen_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
def saved_change_to_fuzzysearch_checked_at; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_fuzzysearch_checked_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_fuzzysearch_entry_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_fuzzysearch_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_fuzzysearch_json; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_fuzzysearch_json?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_gender; end
|
||||
|
||||
@@ -2000,6 +2192,12 @@ class Domain::Post::FaPost
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_tried_from_fur_archiver?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(T::Boolean), T.nilable(T::Boolean)])) }
|
||||
def saved_change_to_tried_from_tor; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_tried_from_tor?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_type; end
|
||||
|
||||
@@ -2337,6 +2535,51 @@ class Domain::Post::FaPost
|
||||
sig { void }
|
||||
def tried_from_fur_archiver_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor; end
|
||||
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def tried_from_tor?; end
|
||||
|
||||
sig { returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def tried_from_tor_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def tried_from_tor_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(T::Boolean), T.nilable(T::Boolean)])) }
|
||||
def tried_from_tor_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(T::Boolean), T.nilable(T::Boolean)])) }
|
||||
def tried_from_tor_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(T::Boolean), to: T.nilable(T::Boolean)).returns(T::Boolean) }
|
||||
def tried_from_tor_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(T::Boolean), T.nilable(T::Boolean)])) }
|
||||
def tried_from_tor_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(T::Boolean), to: T.nilable(T::Boolean)).returns(T::Boolean) }
|
||||
def tried_from_tor_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(T::Boolean)) }
|
||||
def tried_from_tor_was; end
|
||||
|
||||
sig { void }
|
||||
def tried_from_tor_will_change!; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def type; end
|
||||
|
||||
@@ -2458,6 +2701,15 @@ class Domain::Post::FaPost
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_first_seen_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_fuzzysearch_checked_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_fuzzysearch_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_fuzzysearch_json?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_gender?; end
|
||||
|
||||
@@ -2512,6 +2764,9 @@ class Domain::Post::FaPost
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_tried_from_fur_archiver?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_tried_from_tor?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_type?; end
|
||||
|
||||
|
||||
@@ -457,7 +457,7 @@ class Domain::PostFile::InkbunnyPostFile
|
||||
def build_blob(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostFilesInkbunnyAux) }
|
||||
def build_domain_post_files_inkbunny_aux(*args, &blk); end
|
||||
def build_inkbunny_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_log_entry(*args, &blk); end
|
||||
@@ -472,10 +472,10 @@ class Domain::PostFile::InkbunnyPostFile
|
||||
def create_blob!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostFilesInkbunnyAux) }
|
||||
def create_domain_post_files_inkbunny_aux(*args, &blk); end
|
||||
def create_inkbunny_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainPostFilesInkbunnyAux) }
|
||||
def create_domain_post_files_inkbunny_aux!(*args, &blk); end
|
||||
def create_inkbunny_aux!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_log_entry(*args, &blk); end
|
||||
@@ -490,10 +490,10 @@ class Domain::PostFile::InkbunnyPostFile
|
||||
def create_post!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::DomainPostFilesInkbunnyAux)) }
|
||||
def domain_post_files_inkbunny_aux; end
|
||||
def inkbunny_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainPostFilesInkbunnyAux)).void }
|
||||
def domain_post_files_inkbunny_aux=(value); end
|
||||
def inkbunny_aux=(value); end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def log_entry; end
|
||||
@@ -511,7 +511,7 @@ class Domain::PostFile::InkbunnyPostFile
|
||||
def reload_blob; end
|
||||
|
||||
sig { returns(T.nilable(::DomainPostFilesInkbunnyAux)) }
|
||||
def reload_domain_post_files_inkbunny_aux; end
|
||||
def reload_inkbunny_aux; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_log_entry; end
|
||||
@@ -523,7 +523,7 @@ class Domain::PostFile::InkbunnyPostFile
|
||||
def reset_blob; end
|
||||
|
||||
sig { void }
|
||||
def reset_domain_post_files_inkbunny_aux; end
|
||||
def reset_inkbunny_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_log_entry; end
|
||||
|
||||
14
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
14
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
@@ -508,7 +508,7 @@ class Domain::User::E621User
|
||||
def build_avatar(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersE621Aux) }
|
||||
def build_domain_users_e621_aux(*args, &blk); end
|
||||
def build_e621_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::UserAvatar) }
|
||||
def create_avatar(*args, &blk); end
|
||||
@@ -517,16 +517,16 @@ class Domain::User::E621User
|
||||
def create_avatar!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersE621Aux) }
|
||||
def create_domain_users_e621_aux(*args, &blk); end
|
||||
def create_e621_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersE621Aux) }
|
||||
def create_domain_users_e621_aux!(*args, &blk); end
|
||||
def create_e621_aux!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersE621Aux)) }
|
||||
def domain_users_e621_aux; end
|
||||
def e621_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainUsersE621Aux)).void }
|
||||
def domain_users_e621_aux=(value); end
|
||||
def e621_aux=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids; end
|
||||
@@ -602,13 +602,13 @@ class Domain::User::E621User
|
||||
def reload_avatar; end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersE621Aux)) }
|
||||
def reload_domain_users_e621_aux; end
|
||||
def reload_e621_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_avatar; end
|
||||
|
||||
sig { void }
|
||||
def reset_domain_users_e621_aux; end
|
||||
def reset_e621_aux; end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def uploaded_post_ids; end
|
||||
|
||||
14
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
14
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
@@ -529,7 +529,7 @@ class Domain::User::FaUser
|
||||
def build_avatar(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersFaAux) }
|
||||
def build_domain_users_fa_aux(*args, &blk); end
|
||||
def build_fa_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_last_gallery_page_log_entry(*args, &blk); end
|
||||
@@ -544,10 +544,10 @@ class Domain::User::FaUser
|
||||
def create_avatar!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersFaAux) }
|
||||
def create_domain_users_fa_aux(*args, &blk); end
|
||||
def create_fa_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersFaAux) }
|
||||
def create_domain_users_fa_aux!(*args, &blk); end
|
||||
def create_fa_aux!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_gallery_page_log_entry(*args, &blk); end
|
||||
@@ -562,10 +562,10 @@ class Domain::User::FaUser
|
||||
def create_last_user_page_log_entry!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersFaAux)) }
|
||||
def domain_users_fa_aux; end
|
||||
def fa_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainUsersFaAux)).void }
|
||||
def domain_users_fa_aux=(value); end
|
||||
def fa_aux=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids; end
|
||||
@@ -665,7 +665,7 @@ class Domain::User::FaUser
|
||||
def reload_avatar; end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersFaAux)) }
|
||||
def reload_domain_users_fa_aux; end
|
||||
def reload_fa_aux; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_last_gallery_page_log_entry; end
|
||||
@@ -677,7 +677,7 @@ class Domain::User::FaUser
|
||||
def reset_avatar; end
|
||||
|
||||
sig { void }
|
||||
def reset_domain_users_fa_aux; end
|
||||
def reset_fa_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_last_gallery_page_log_entry; end
|
||||
|
||||
22
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
22
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
@@ -498,7 +498,7 @@ class Domain::User::InkbunnyUser
|
||||
def build_deep_update_log_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersInkbunnyAux) }
|
||||
def build_domain_users_inkbunny_aux(*args, &blk); end
|
||||
def build_inkbunny_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_shallow_update_log_entry(*args, &blk); end
|
||||
@@ -516,10 +516,10 @@ class Domain::User::InkbunnyUser
|
||||
def create_deep_update_log_entry!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersInkbunnyAux) }
|
||||
def create_domain_users_inkbunny_aux(*args, &blk); end
|
||||
def create_inkbunny_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersInkbunnyAux) }
|
||||
def create_domain_users_inkbunny_aux!(*args, &blk); end
|
||||
def create_inkbunny_aux!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_shallow_update_log_entry(*args, &blk); end
|
||||
@@ -539,12 +539,6 @@ class Domain::User::InkbunnyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def deep_update_log_entry_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersInkbunnyAux)) }
|
||||
def domain_users_inkbunny_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainUsersInkbunnyAux)).void }
|
||||
def domain_users_inkbunny_aux=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids; end
|
||||
|
||||
@@ -601,6 +595,12 @@ class Domain::User::InkbunnyUser
|
||||
sig { params(value: T::Enumerable[::Domain::User]).void }
|
||||
def followed_users=(value); end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersInkbunnyAux)) }
|
||||
def inkbunny_aux; end
|
||||
|
||||
sig { params(value: T.nilable(::DomainUsersInkbunnyAux)).void }
|
||||
def inkbunny_aux=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def post_ids; end
|
||||
|
||||
@@ -622,7 +622,7 @@ class Domain::User::InkbunnyUser
|
||||
def reload_deep_update_log_entry; end
|
||||
|
||||
sig { returns(T.nilable(::DomainUsersInkbunnyAux)) }
|
||||
def reload_domain_users_inkbunny_aux; end
|
||||
def reload_inkbunny_aux; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_shallow_update_log_entry; end
|
||||
@@ -634,7 +634,7 @@ class Domain::User::InkbunnyUser
|
||||
def reset_deep_update_log_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_domain_users_inkbunny_aux; end
|
||||
def reset_inkbunny_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_shallow_update_log_entry; end
|
||||
|
||||
30
sorbet/rbi/dsl/domain_post_files_inkbunny_aux.rbi
generated
30
sorbet/rbi/dsl/domain_post_files_inkbunny_aux.rbi
generated
@@ -421,32 +421,32 @@ class DomainPostFilesInkbunnyAux
|
||||
end
|
||||
|
||||
module GeneratedAssociationMethods
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def build_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def create_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def create_main!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::Domain::PostFile::InkbunnyPostFile)) }
|
||||
def base_table; end
|
||||
def main; end
|
||||
|
||||
sig { params(value: T.nilable(::Domain::PostFile::InkbunnyPostFile)).void }
|
||||
def base_table=(value); end
|
||||
def main=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_changed?; end
|
||||
def main_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_previously_changed?; end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def build_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def create_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::PostFile::InkbunnyPostFile) }
|
||||
def create_base_table!(*args, &blk); end
|
||||
def main_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::Domain::PostFile::InkbunnyPostFile)) }
|
||||
def reload_base_table; end
|
||||
def reload_main; end
|
||||
|
||||
sig { void }
|
||||
def reset_base_table; end
|
||||
def reset_main; end
|
||||
end
|
||||
|
||||
module GeneratedAssociationRelationMethods
|
||||
|
||||
2587
sorbet/rbi/dsl/domain_posts_e621_aux.rbi
generated
Normal file
2587
sorbet/rbi/dsl/domain_posts_e621_aux.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
sorbet/rbi/dsl/domain_users_e621_aux.rbi
generated
30
sorbet/rbi/dsl/domain_users_e621_aux.rbi
generated
@@ -418,32 +418,32 @@ class DomainUsersE621Aux
|
||||
end
|
||||
|
||||
module GeneratedAssociationMethods
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def build_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def create_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def create_main!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::E621User)) }
|
||||
def base_table; end
|
||||
def main; end
|
||||
|
||||
sig { params(value: T.nilable(::Domain::User::E621User)).void }
|
||||
def base_table=(value); end
|
||||
def main=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_changed?; end
|
||||
def main_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_previously_changed?; end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def build_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def create_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::E621User) }
|
||||
def create_base_table!(*args, &blk); end
|
||||
def main_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::E621User)) }
|
||||
def reload_base_table; end
|
||||
def reload_main; end
|
||||
|
||||
sig { void }
|
||||
def reset_base_table; end
|
||||
def reset_main; end
|
||||
end
|
||||
|
||||
module GeneratedAssociationRelationMethods
|
||||
|
||||
30
sorbet/rbi/dsl/domain_users_fa_aux.rbi
generated
30
sorbet/rbi/dsl/domain_users_fa_aux.rbi
generated
@@ -408,32 +408,32 @@ class DomainUsersFaAux
|
||||
end
|
||||
|
||||
module GeneratedAssociationMethods
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def build_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def create_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def create_main!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::FaUser)) }
|
||||
def base_table; end
|
||||
def main; end
|
||||
|
||||
sig { params(value: T.nilable(::Domain::User::FaUser)).void }
|
||||
def base_table=(value); end
|
||||
def main=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_changed?; end
|
||||
def main_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_previously_changed?; end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def build_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def create_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::FaUser) }
|
||||
def create_base_table!(*args, &blk); end
|
||||
def main_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::FaUser)) }
|
||||
def reload_base_table; end
|
||||
def reload_main; end
|
||||
|
||||
sig { void }
|
||||
def reset_base_table; end
|
||||
def reset_main; end
|
||||
end
|
||||
|
||||
module GeneratedAssociationRelationMethods
|
||||
|
||||
30
sorbet/rbi/dsl/domain_users_inkbunny_aux.rbi
generated
30
sorbet/rbi/dsl/domain_users_inkbunny_aux.rbi
generated
@@ -416,32 +416,32 @@ class DomainUsersInkbunnyAux
|
||||
end
|
||||
|
||||
module GeneratedAssociationMethods
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def build_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def create_main(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def create_main!(*args, &blk); end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::InkbunnyUser)) }
|
||||
def base_table; end
|
||||
def main; end
|
||||
|
||||
sig { params(value: T.nilable(::Domain::User::InkbunnyUser)).void }
|
||||
def base_table=(value); end
|
||||
def main=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_changed?; end
|
||||
def main_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def base_table_previously_changed?; end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def build_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def create_base_table(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::User::InkbunnyUser) }
|
||||
def create_base_table!(*args, &blk); end
|
||||
def main_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::Domain::User::InkbunnyUser)) }
|
||||
def reload_base_table; end
|
||||
def reload_main; end
|
||||
|
||||
sig { void }
|
||||
def reset_base_table; end
|
||||
def reset_main; end
|
||||
end
|
||||
|
||||
module GeneratedAssociationRelationMethods
|
||||
|
||||
174
sorbet/rbi/dsl/flat_sst_entry.rbi
generated
174
sorbet/rbi/dsl/flat_sst_entry.rbi
generated
@@ -6,7 +6,6 @@
|
||||
|
||||
|
||||
class FlatSstEntry
|
||||
include GeneratedAttributeMethods
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
@@ -552,179 +551,6 @@ class FlatSstEntry
|
||||
def without_count; end
|
||||
end
|
||||
|
||||
module GeneratedAttributeMethods
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def contents; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def contents=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def contents?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def contents_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def contents_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def contents_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def contents_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def contents_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def contents_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def contents_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def contents_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def contents_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def contents_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def contents_was; end
|
||||
|
||||
sig { void }
|
||||
def contents_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def id; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def id?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def id_was; end
|
||||
|
||||
sig { void }
|
||||
def id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def key; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def key=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def key?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def key_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def key_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def key_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def key_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def key_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def key_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def key_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def key_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def key_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def key_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def key_was; end
|
||||
|
||||
sig { void }
|
||||
def key_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_contents!; end
|
||||
|
||||
sig { void }
|
||||
def restore_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_key!; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_contents; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_contents?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_key; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_key?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_contents?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_key?; end
|
||||
end
|
||||
|
||||
module GeneratedRelationMethods
|
||||
sig { returns(PrivateRelation) }
|
||||
def all; end
|
||||
|
||||
54
sorbet/rbi/dsl/http_log_entry.rbi
generated
54
sorbet/rbi/dsl/http_log_entry.rbi
generated
@@ -397,6 +397,18 @@ class HttpLogEntry
|
||||
end
|
||||
|
||||
module EnumMethodsModule
|
||||
sig { void }
|
||||
def performed_by_airvpn_1_netherlands!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def performed_by_airvpn_1_netherlands?; end
|
||||
|
||||
sig { void }
|
||||
def performed_by_airvpn_2_san_jose!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def performed_by_airvpn_2_san_jose?; end
|
||||
|
||||
sig { void }
|
||||
def performed_by_dedipath_1!; end
|
||||
|
||||
@@ -433,6 +445,12 @@ class HttpLogEntry
|
||||
sig { returns(T::Boolean) }
|
||||
def performed_by_serverhost_1?; end
|
||||
|
||||
sig { void }
|
||||
def performed_by_tor_1!; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def performed_by_tor_1?; end
|
||||
|
||||
sig { void }
|
||||
def verb_get!; end
|
||||
|
||||
@@ -643,6 +661,12 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def none(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_performed_by_airvpn_1_netherlands(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_performed_by_airvpn_2_san_jose(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_performed_by_dedipath_1(*args, &blk); end
|
||||
|
||||
@@ -661,6 +685,9 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_performed_by_serverhost_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_performed_by_tor_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def not_verb_get(*args, &blk); end
|
||||
|
||||
@@ -699,6 +726,12 @@ class HttpLogEntry
|
||||
end
|
||||
def per(num); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def performed_by_airvpn_1_netherlands(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def performed_by_airvpn_2_san_jose(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def performed_by_dedipath_1(*args, &blk); end
|
||||
|
||||
@@ -717,6 +750,9 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def performed_by_serverhost_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def performed_by_tor_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def preload(*args, &blk); end
|
||||
|
||||
@@ -1998,6 +2034,12 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def none(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_performed_by_airvpn_1_netherlands(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_performed_by_airvpn_2_san_jose(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_performed_by_dedipath_1(*args, &blk); end
|
||||
|
||||
@@ -2016,6 +2058,9 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_performed_by_serverhost_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_performed_by_tor_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def not_verb_get(*args, &blk); end
|
||||
|
||||
@@ -2054,6 +2099,12 @@ class HttpLogEntry
|
||||
end
|
||||
def per(num); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def performed_by_airvpn_1_netherlands(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def performed_by_airvpn_2_san_jose(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def performed_by_dedipath_1(*args, &blk); end
|
||||
|
||||
@@ -2072,6 +2123,9 @@ class HttpLogEntry
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def performed_by_serverhost_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def performed_by_tor_1(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def preload(*args, &blk); end
|
||||
|
||||
|
||||
1
sorbet/rbi/dsl/rails/application_controller.rbi
generated
1
sorbet/rbi/dsl/rails/application_controller.rbi
generated
@@ -43,6 +43,7 @@ class Rails::ApplicationController
|
||||
include ::Domain::Users::FaUsersHelper
|
||||
include ::Domain::VisualSearchHelper
|
||||
include ::DomainSourceHelper
|
||||
include ::FaUriHelper
|
||||
include ::GoodJobHelper
|
||||
include ::IpAddressHelper
|
||||
include ::TimestampHelper
|
||||
|
||||
@@ -43,6 +43,7 @@ class Rails::Conductor::BaseController
|
||||
include ::Domain::Users::FaUsersHelper
|
||||
include ::Domain::VisualSearchHelper
|
||||
include ::DomainSourceHelper
|
||||
include ::FaUriHelper
|
||||
include ::GoodJobHelper
|
||||
include ::IpAddressHelper
|
||||
include ::TimestampHelper
|
||||
|
||||
1
sorbet/rbi/dsl/rails/health_controller.rbi
generated
1
sorbet/rbi/dsl/rails/health_controller.rbi
generated
@@ -43,6 +43,7 @@ class Rails::HealthController
|
||||
include ::Domain::Users::FaUsersHelper
|
||||
include ::Domain::VisualSearchHelper
|
||||
include ::DomainSourceHelper
|
||||
include ::FaUriHelper
|
||||
include ::GoodJobHelper
|
||||
include ::IpAddressHelper
|
||||
include ::TimestampHelper
|
||||
|
||||
16
sorbet/rbi/dsl/scraper/fuzzysearch_api_client.rbi
generated
Normal file
16
sorbet/rbi/dsl/scraper/fuzzysearch_api_client.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Scraper::FuzzysearchApiClient`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Scraper::FuzzysearchApiClient`.
|
||||
|
||||
|
||||
class Scraper::FuzzysearchApiClient
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
16
sorbet/rbi/dsl/scraper/fuzzysearch_http_client_config.rbi
generated
Normal file
16
sorbet/rbi/dsl/scraper/fuzzysearch_http_client_config.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Scraper::FuzzysearchHttpClientConfig`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Scraper::FuzzysearchHttpClientConfig`.
|
||||
|
||||
|
||||
class Scraper::FuzzysearchHttpClientConfig
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
16
sorbet/rbi/dsl/scraper/tor_http_client_config.rbi
generated
Normal file
16
sorbet/rbi/dsl/scraper/tor_http_client_config.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Scraper::TorHttpClientConfig`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Scraper::TorHttpClientConfig`.
|
||||
|
||||
|
||||
class Scraper::TorHttpClientConfig
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
16
sorbet/rbi/dsl/tasks/fa/query_missing_posts_from_fuzzysearch.rbi
generated
Normal file
16
sorbet/rbi/dsl/tasks/fa/query_missing_posts_from_fuzzysearch.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Tasks::Fa::QueryMissingPostsFromFuzzysearch`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Tasks::Fa::QueryMissingPostsFromFuzzysearch`.
|
||||
|
||||
|
||||
class Tasks::Fa::QueryMissingPostsFromFuzzysearch
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
@@ -16,7 +16,7 @@ FactoryBot.define do
|
||||
post_file.log_entry =
|
||||
create(
|
||||
:http_log_entry,
|
||||
url_str: post_file.url_str,
|
||||
uri_str: post_file.url_str,
|
||||
status_code: post_file.last_status_code,
|
||||
)
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@ RSpec.describe FaUriHelper do
|
||||
original_file_posted: 1_740_700_581,
|
||||
latest_file_posted: 1_740_700_581,
|
||||
filename: "zzreg_stippling-crop.jpg",
|
||||
filename_with_ts: "1740700581.zzreg_stippling-crop.jpg",
|
||||
),
|
||||
)
|
||||
expect(parsed.original_file_posted_at).to eq(Time.at(1_740_700_581))
|
||||
@@ -29,10 +30,27 @@ RSpec.describe FaUriHelper do
|
||||
original_file_posted: 1_740_700_581,
|
||||
latest_file_posted: 1_753_374_875,
|
||||
filename: "zzreg_stippling-crop.jpg",
|
||||
filename_with_ts: "1740700581.zzreg_stippling-crop.jpg",
|
||||
),
|
||||
)
|
||||
expect(parsed.original_file_posted_at).to eq(Time.at(1_740_700_581))
|
||||
expect(parsed.latest_file_posted_at).to eq(Time.at(1_753_374_875))
|
||||
end
|
||||
|
||||
it "parses story uris" do
|
||||
url =
|
||||
"https://d.furaffinity.net/art/irontankris/stories/1753207806/1753207806.thumbnail.irontankris_royal_rivalry_gains.rtf.jpg"
|
||||
parsed = described_class.parse_fa_media_url(url)
|
||||
expect(parsed).to eq(
|
||||
FaUriHelper::FaMediaUrlInfo.new(
|
||||
url_name: "irontankris",
|
||||
original_file_posted: 1_753_207_806,
|
||||
latest_file_posted: 1_753_207_806,
|
||||
filename: "thumbnail.irontankris_royal_rivalry_gains.rtf.jpg",
|
||||
filename_with_ts:
|
||||
"1753207806.thumbnail.irontankris_royal_rivalry_gains.rtf.jpg",
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
198
spec/jobs/domain/fa/job/scan_fuzzysearch_job_spec.rb
Normal file
198
spec/jobs/domain/fa/job/scan_fuzzysearch_job_spec.rb
Normal file
@@ -0,0 +1,198 @@
|
||||
# typed: false
|
||||
require "rails_helper"
|
||||
|
||||
describe Domain::Fa::Job::ScanFuzzysearchJob do
|
||||
let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
|
||||
before { Scraper::ClientFactory.http_client_mock = http_client_mock }
|
||||
|
||||
let(:client_mock_config) { [] }
|
||||
let!(:log_entries) do
|
||||
HttpClientMockHelpers.init_http_client_mock(
|
||||
http_client_mock,
|
||||
client_mock_config,
|
||||
)
|
||||
end
|
||||
|
||||
let(:fuzzysearch_response_51015903) do
|
||||
JSON.parse(File.read("test/fixtures/files/fuzzysearch/51015903.json"))
|
||||
end
|
||||
|
||||
let(:fuzzysearch_response_21275696) do
|
||||
JSON.parse(File.read("test/fixtures/files/fuzzysearch/21275696.json"))
|
||||
end
|
||||
|
||||
let(:fuzzysearch_response_53068507) do
|
||||
JSON.parse(File.read("test/fixtures/files/fuzzysearch/53068507.json"))
|
||||
end
|
||||
|
||||
let(:fuzzysearch_response_61665194) do
|
||||
JSON.parse(File.read("test/fixtures/files/fuzzysearch/61665194.json"))
|
||||
end
|
||||
|
||||
describe "post was marked removed" do
|
||||
let(:post) do
|
||||
create(
|
||||
:domain_post_fa_post,
|
||||
state: "removed",
|
||||
keywords: nil,
|
||||
fa_id: fa_id,
|
||||
)
|
||||
end
|
||||
|
||||
context "and fuzzysearch has post info" do
|
||||
let(:fa_id) { 51_015_903 }
|
||||
let(:client_mock_config) do
|
||||
[
|
||||
{
|
||||
uri:
|
||||
"https://api-next.fuzzysearch.net/v1/file/furaffinity?search=#{fa_id}",
|
||||
status_code: 200,
|
||||
content_type: "application/json",
|
||||
contents: fuzzysearch_response_51015903.to_json,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
it "updates the post" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.fuzzysearch_checked_at).to be_present
|
||||
expect(post.fuzzysearch_entry).to be_present
|
||||
expect(post.fuzzysearch_json).to be_present
|
||||
end
|
||||
|
||||
it "sets tags" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.keywords).to eq(%w[some_tag another_tag])
|
||||
end
|
||||
|
||||
it "sets file" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.file).to be_present
|
||||
expect(post.file.url_str).to eq(
|
||||
"https://d.furaffinity.net/art/crimetxt/1676417528/1676417528.crimetxt_2023-02-15_00_18_48.png",
|
||||
)
|
||||
end
|
||||
|
||||
it "sets the creator" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.creator).to be_present
|
||||
expect(post.creator.url_name).to eq("crimetxt")
|
||||
end
|
||||
|
||||
it "enqueues a fur archiver post file job" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
job_args = SpecUtil.enqueued_job_args(Job::FaPostFurArchiverPostFileJob)
|
||||
expect(job_args).to match(
|
||||
[{ post_file: post.file, caused_by_entry: post.fuzzysearch_entry }],
|
||||
)
|
||||
end
|
||||
|
||||
context "the post file is already downloaded" do
|
||||
before do
|
||||
post.file = create(:domain_post_file, :has_file)
|
||||
post.save!
|
||||
end
|
||||
|
||||
it "does not enqueue a fur archiver post file job" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
job_args =
|
||||
SpecUtil.enqueued_job_args(Job::FaPostFurArchiverPostFileJob)
|
||||
expect(job_args).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "and fuzzysearch has no post info" do
|
||||
let(:fa_id) { 21_275_696 }
|
||||
let(:client_mock_config) do
|
||||
[
|
||||
{
|
||||
uri:
|
||||
"https://api-next.fuzzysearch.net/v1/file/furaffinity?search=#{fa_id}",
|
||||
status_code: 200,
|
||||
content_type: "application/json",
|
||||
contents: fuzzysearch_response_21275696.to_json,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
it "does not set the creator" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.creator).to be_nil
|
||||
end
|
||||
|
||||
it "does not create a file" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.file).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "and the artist name has capitalizations" do
|
||||
let(:fa_id) { 53_068_507 }
|
||||
let(:client_mock_config) do
|
||||
[
|
||||
{
|
||||
uri:
|
||||
"https://api-next.fuzzysearch.net/v1/file/furaffinity?search=#{fa_id}",
|
||||
status_code: 200,
|
||||
content_type: "application/json",
|
||||
contents: fuzzysearch_response_53068507.to_json,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
it "sets the creator" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.creator).to be_present
|
||||
expect(post.creator.url_name).to eq("meesh")
|
||||
expect(post.creator.name).to eq("Meesh")
|
||||
expect(post.creator.full_name).to eq("Meesh")
|
||||
end
|
||||
end
|
||||
|
||||
context "and the post has a story url" do
|
||||
let(:fa_id) { 61_665_194 }
|
||||
let(:client_mock_config) do
|
||||
[
|
||||
{
|
||||
uri:
|
||||
"https://api-next.fuzzysearch.net/v1/file/furaffinity?search=#{fa_id}",
|
||||
status_code: 200,
|
||||
content_type: "application/json",
|
||||
contents: fuzzysearch_response_61665194.to_json,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
it "does not change the post state" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.state).to eq("removed")
|
||||
end
|
||||
|
||||
it "sets the artist" do
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.creator).to be_present
|
||||
expect(post.creator.url_name).to eq("irontankris")
|
||||
end
|
||||
|
||||
it "updates keywords", quiet: false do
|
||||
post.keywords = []
|
||||
post.save!
|
||||
perform_now({ post: })
|
||||
post.reload
|
||||
expect(post.keywords).to include("female", "mlp", "little", "anthro")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -78,7 +78,7 @@ RSpec.describe Job::FaPostFurArchiverPostFileJob do
|
||||
|
||||
it "downloads the file from fur archiver" do
|
||||
expect do
|
||||
perform_now({ post_file: post_file })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
end.to change { post.file&.log_entry }.from(old_log_entry).to(
|
||||
have_attributes(uri: have_attributes(to_s: fur_archiver_url_str)),
|
||||
@@ -87,7 +87,7 @@ RSpec.describe Job::FaPostFurArchiverPostFileJob do
|
||||
|
||||
it "updates the post_file blob" do
|
||||
expect do
|
||||
perform_now({ post_file: post_file })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
end.to change { post.file&.blob }.from(old_log_entry.response).to(
|
||||
@log_entries[0].response,
|
||||
@@ -96,17 +96,24 @@ RSpec.describe Job::FaPostFurArchiverPostFileJob do
|
||||
|
||||
it "sets the last status code" do
|
||||
expect do
|
||||
perform_now({ post_file: post_file })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
end.to change { post.file&.last_status_code }.from(404).to(200)
|
||||
end
|
||||
|
||||
it "sets the post_file state to ok" do
|
||||
expect do
|
||||
perform_now({ post_file: post_file })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
end.to change { post.file&.state }.from("terminal_error").to("ok")
|
||||
end
|
||||
|
||||
it "does not perform the request twice" do
|
||||
perform_now({ post: post })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
expect(post.files.length).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a d.facdn.net url" do
|
||||
@@ -122,5 +129,58 @@ RSpec.describe Job::FaPostFurArchiverPostFileJob do
|
||||
end
|
||||
include_examples "correct behavior"
|
||||
end
|
||||
|
||||
context "when furarchiver returns 404" do
|
||||
let(:client_mock_config) do
|
||||
[
|
||||
{
|
||||
uri: fur_archiver_url_str,
|
||||
status_code: 404,
|
||||
content_type: "text/html",
|
||||
contents: "not found",
|
||||
},
|
||||
{
|
||||
uri:
|
||||
"http://g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion/fa/wolfsparta/1496842943.wolfsparta_caught_pt2.png",
|
||||
status_code: 200,
|
||||
content_type: "image/png",
|
||||
contents: image_data,
|
||||
caused_by_entry_idx: 0,
|
||||
},
|
||||
]
|
||||
end
|
||||
let(:file_url_str) do
|
||||
"https://d.facdn.net/art/wolfsparta/1496842943/1496842943.wolfsparta_caught_pt2.png"
|
||||
end
|
||||
|
||||
it "creates a tor post file" do
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
# should have original post file, the fur archiver post file, and the tor post file
|
||||
expect(post.files.count).to eq(3)
|
||||
original, furarchiver, tor = post.files.sort_by(&:id)
|
||||
expect(original.state).to eq("terminal_error")
|
||||
expect(furarchiver.state).to eq("terminal_error")
|
||||
expect(tor.state).to eq("ok")
|
||||
expect(tor.url_str).to eq(
|
||||
"http://g6jy5jkx466lrqojcngbnksugrcfxsl562bzuikrka5rv7srgguqbjid.onion/fa/wolfsparta/1496842943.wolfsparta_caught_pt2.png",
|
||||
)
|
||||
end
|
||||
|
||||
it "does not perform the request twice" do
|
||||
perform_now({ post: post })
|
||||
perform_now({ post: post })
|
||||
post.reload
|
||||
expect(post.files.length).to eq(3)
|
||||
end
|
||||
|
||||
it "enqueues the thumbnail job" do
|
||||
perform_now({ post: post })
|
||||
job_args = SpecUtil.enqueued_job_args(Domain::PostFileThumbnailJob)
|
||||
expect(job_args).to eq(
|
||||
[{ post_file: post.files.last, caused_by_entry: @log_entries[0] }],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
18
test/fixtures/files/fuzzysearch/21275696.json
vendored
Normal file
18
test/fixtures/files/fuzzysearch/21275696.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"id": 21275696,
|
||||
"file_id": null,
|
||||
"artist": null,
|
||||
"hash": null,
|
||||
"hash_str": null,
|
||||
"url": null,
|
||||
"filename": null,
|
||||
"rating": null,
|
||||
"posted_at": null,
|
||||
"file_size": null,
|
||||
"sha256": null,
|
||||
"updated_at": "2023-08-16T08:02:27.746944Z",
|
||||
"deleted": true,
|
||||
"tags": []
|
||||
}
|
||||
]
|
||||
18
test/fixtures/files/fuzzysearch/51015903.json
vendored
Normal file
18
test/fixtures/files/fuzzysearch/51015903.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"id": 51015903,
|
||||
"file_id": 1676417528,
|
||||
"artist": "crimetxt",
|
||||
"hash": 2367248181756250600,
|
||||
"hash_str": "2367248181756250660",
|
||||
"url": "https://d.furaffinity.net/art/crimetxt/1676417528/1676417528.crimetxt_2023-02-15_00_18_48.png",
|
||||
"filename": "1676417528.crimetxt_2023-02-15_00_18_48.png",
|
||||
"rating": "adult",
|
||||
"posted_at": "2023-02-14T23:32:00Z",
|
||||
"file_size": 2188273,
|
||||
"sha256": "d488dabd8eb22398a228fb662eb520bb4daaac3a9ab0dc9be8b8c5e1b9522efb",
|
||||
"updated_at": null,
|
||||
"deleted": false,
|
||||
"tags": ["some_tag", "another_tag"]
|
||||
}
|
||||
]
|
||||
25
test/fixtures/files/fuzzysearch/53068507.json
vendored
Normal file
25
test/fixtures/files/fuzzysearch/53068507.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
[
|
||||
{
|
||||
"id": 53068507,
|
||||
"file_id": 1690504099,
|
||||
"artist": "Meesh",
|
||||
"hash": -5278701664616650000,
|
||||
"hash_str": "-5278701664616649812",
|
||||
"url": "https://d.furaffinity.net/art/meesh/1690504135/1690504099.meesh_pamperingjack3_crop.png",
|
||||
"filename": "1690504099.meesh_pamperingjack3_crop.png",
|
||||
"rating": "adult",
|
||||
"posted_at": "2023-07-28T00:28:00Z",
|
||||
"file_size": 555926,
|
||||
"sha256": "f47e974ef7e72c53fce5a52b28b7c34576eb26af04299155d1cc3912379b0dea",
|
||||
"updated_at": null,
|
||||
"deleted": false,
|
||||
"tags": [
|
||||
"advertisement",
|
||||
"patreon",
|
||||
"female",
|
||||
"preview_limited",
|
||||
"beastars",
|
||||
"juno"
|
||||
]
|
||||
}
|
||||
]
|
||||
34
test/fixtures/files/fuzzysearch/61665194.json
vendored
Normal file
34
test/fixtures/files/fuzzysearch/61665194.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"id": 61665194,
|
||||
"file_id": 1753207806,
|
||||
"artist": "irontankris",
|
||||
"hash": 3088256223167493600,
|
||||
"hash_str": "3088256223167493676",
|
||||
"url": "https://d.furaffinity.net/art/irontankris/stories/1753207806/1753207806.thumbnail.irontankris_royal_rivalry_gains.rtf.jpg",
|
||||
"filename": "1753207806.thumbnail.irontankris_royal_rivalry_gains.rtf.jpg",
|
||||
"rating": "adult",
|
||||
"posted_at": "2025-07-22T18:10:00Z",
|
||||
"file_size": 10283,
|
||||
"sha256": "3809e988c41506211bd2885061646432e021b3810afc9080d244dd63a84a783e",
|
||||
"updated_at": null,
|
||||
"deleted": false,
|
||||
"tags": [
|
||||
"female",
|
||||
"mlp",
|
||||
"little",
|
||||
"pony",
|
||||
"sex",
|
||||
"lesbian",
|
||||
"weight",
|
||||
"gain",
|
||||
"wg",
|
||||
"incest",
|
||||
"princess_celestia",
|
||||
"princess_luna",
|
||||
"celestia",
|
||||
"luna",
|
||||
"anthro"
|
||||
]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user