# frozen_string_literal: true class ExternalAPIImage < ApplicationRecord class Error < StandardError; end CACHE_TIME = 2.days IGNORED_ARTISTS = %w[avoid_posting conditional_dnp sound_warning epilepsy_warning].freeze Site = Struct.new(:name, :value, :format) SITES = [ Site.new("E621", "e621", "https://e621.net/posts/%s"), Site.new("Femboy Fans", "femboyfans", "https://femboy.fan/posts/%s"), ].freeze belongs_to :api_image validates :site, inclusion: { in: SITES.map(&:value) } validate :not_deleted, on: :create enum site: SITES.to_h { |s| [s.value, s.value] } module DataMethods def url case site when "e621" "https://e621.net/posts/#{external_id}" when "femboyfans" "https://femboy.fan/posts/#{external_id}" else data_error("format url") end end def file_url return nil if is_deleted? case site when "e621", "femboyfans" cache.dig("file", "url") else data_error("format file_url") end end def width case site when "e621", "femboyfans" cache.dig("file", "width") else data_error("format width") end end def height case site when "e621", "femboyfans" cache.dig("file", "height") else data_error("format height") end end def size case site when "e621", "femboyfans" cache.dig("file", "size") else data_error("format size") end end def ext case site when "e621", "femboyfans" cache.dig("file", "ext") else data_error("format ext") end end def md5 case site when "e621", "femboyfans" cache.dig("file", "md5") else data_error("format md5") end end def image_changed? case site when "e621", "femboyfans" cached_data.try(:dig, "file", "md5") != cached_data_before_last_save.try(:dig, "file", "md5") else data_error("format image_changed?") end end def is_deleted? case site when "e621", "femboyfans" cache.dig("flags", "deleted") else false end end def artists case site when "e621", "femboyfans" cache.dig("tags", "artist") - IGNORED_ARTISTS else data_error("format artists") end end def sources case site when "e621", "femboyfans" [url] + cache["sources"].select { |s| s.start_with?("http") } else data_error("format sources") end end def report_url case site when "e621", "femboyfans" url end end def data_error(text) raise(Error, "Don't know how to #{text} for ExternalApiImage #{id}: #{site}") end end module CacheMethods def cache update_cache! if cached_data.blank? update_cache if cache_expired? cached_data end def cache_expired? cache_last_updated_at < CACHE_TIME.ago end def update_cache return if @cache_updated UpdateExternalCacheJob.perform_later(self) @cache_updated = true end def update_cache! case site when "e621" data = Requests::E621.get_post(id: external_id) when "femboyfans" data = Requests::FemboyFans.get_post(id: external_id) else data_error("update cache") end update(cached_data: data, cache_last_updated_at: Time.now) if is_deleted? api_image.remove_iqdb elsif image_changed? api_image.update_iqdb end api_image.update(is_viewable: !is_deleted?) end end include CacheMethods include DataMethods def not_deleted if is_deleted? errors.add(:external_id, "is deleted") throw(:abort) end end end