Skip to content

Commit

Permalink
Switch from graphql-client to http.rb for Anilist import
Browse files Browse the repository at this point in the history
(Fixes SERVER-FHD)
  • Loading branch information
NuckChorris committed Oct 24, 2024
1 parent 36d6dbd commit 5b28786
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 111 deletions.
107 changes: 51 additions & 56 deletions app/models/list_import/anilist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,8 @@

class ListImport
class Anilist < ListImport
# accepts a username as input
validates :input_text, length: {
minimum: 3,
maximum: 20
}, presence: true
# does not accept file uploads
validates :input_file_data, absence: true
validate :ensure_user_exists, on: :create

def ensure_user_exists
return false if input_text.blank?
return true if user_exists?

errors.add(:input_text, "AniList user not found - #{input_text}")
end

def count
@count ||= anime_list.count + manga_list.count
end

def each
%w[anime manga].each do |type|
send(:"#{type}_list").each do |media|
row = Row.new(media, type)

yield row.media, row.data
end
end
end

private

def anime_list
media_lists.data.anime.lists.map(&:entries).flatten
end

def manga_list
media_lists.data.manga.lists.map(&:entries).flatten
end

def user_exists?
@user_exists ||= media_lists&.errors&.detect { |error| error.last.include?('404') }.blank?
end

def media_lists
@media_lists ||= AnilistApiWrapper::Client.query(
self.class.media_list_query,
variables: {
user_name: input_text
}
)
end

def self.media_list_query
@media_list_query ||= AnilistApiWrapper::Client.parse <<-GRAPHQL
ANILIST_API = 'https://graphql.anilist.co'
MEDIA_LIST_QUERY = <<-GRAPHQL
query($user_name: String) {
anime: MediaListCollection(userName: $user_name, type: ANIME) {
lists {
Expand Down Expand Up @@ -129,7 +76,55 @@ def self.media_list_query
}
}
}
GRAPHQL
GRAPHQL

# accepts a username as input
validates :input_text, length: {
minimum: 3,
maximum: 20
}, presence: true
# does not accept file uploads
validates :input_file_data, absence: true
validate :ensure_user_exists, on: :create

def ensure_user_exists
return false if input_text.blank?
return true if user_exists?

errors.add(:input_text, "AniList user not found - #{input_text}")
end

def count
@count ||= list('anime').count + list('manga').count
end

def each
%w[anime manga].each do |type|
list(type).each do |media|
row = Row.new(media, type)

yield row.media, row.data
end
end
end

private

def list(type)
media_lists.dig('data', type, 'lists').flat_map { |list| list['entries'] }
end

def user_exists?
@user_exists ||= media_lists['errors']&.detect { |error| error.last.include?('404') }.blank?
end

def media_lists
@media_lists ||= Oj.load(HTTP.post(ANILIST_API, json: {
query: MEDIA_LIST_QUERY,
variables: {
user_name: input_text
}
}).body)
end

rescue StandardError => e
Expand Down
47 changes: 22 additions & 25 deletions app/models/list_import/anilist/row.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def media
end

def data
fields.map { |field| [field, send(field)] }.to_h.compact
fields.index_with { |field| send(field) }.compact
end

private
Expand All @@ -42,23 +42,23 @@ def fields
# For mapping guess
def media_info
{
title: title,
title:,
subtype: type,
episode_count: media_data.episodes,
chapter_count: media_data.chapters
episode_count: media_data['episodes'],
chapter_count: media_data['chapters']
}.compact
end

# 100-point scale to 20-point scale (raw)
# rating -> score
def rating
return nil if node.score.zero?
return nil if node['score'].zero?

[(node.score.to_f / 5).ceil, 2].max
[(node['score'].to_f / 5).ceil, 2].max
end

def status
case node.status.downcase
case node['status'].downcase
when 'completed' then :completed
when 'current' then :current
when 'planning' then :planned
Expand All @@ -69,41 +69,38 @@ def status

# reconsume_count -> repeat
def reconsume_count
node.repeat
node['repeat']
end

def progress
node.progress
node['progress']
end

def notes
node.notes
node['notes']
end

# 2020-05-19 -> yyyy-mm-dd
def started_at
return if node.started_at.to_h.compact.blank?

# will properly convert to include 0 before days/months
formatted_date(node.started_at)
formatted_date(node['startedAt'])
end

# finished_at -> completed_at
def finished_at
return if node.completed_at.to_h.compact.blank?

# will properly convert to include 0 before days/months
formatted_date(node.completed_at)
formatted_date(node['completedAt'])
end

def formatted_date(date_node)
date_node.to_h.symbolize_keys.values_at(:year, :month, :day).join('-').to_date.to_s
return if date_node.compact.blank?
date_node.values_at('year', 'month', 'day').join('-').to_date.to_s
end

def volumes_owned
return unless type == 'manga'

node.progress_volumes.presence || 0
node['progressVolumes'].presence || 0
end

def anilist_key
Expand All @@ -115,22 +112,22 @@ def mal_key
end

def media_data
node.media
node['media']
end

def mal_id
media_data.id_mal
media_data['idMal']
end

def titles
media_data.title
media_data['title']
end

def title
titles.romaji.presence ||
titles.english.presence ||
titles.native.presence ||
titles.user_preferred
titles['romaji'].presence ||
titles['english'].presence ||
titles['native'].presence ||
titles['userPreferred']
end

def anilist_mapping
Expand Down
22 changes: 0 additions & 22 deletions lib/anilist_api_wrapper.rb

This file was deleted.

10 changes: 2 additions & 8 deletions spec/models/list_import/anilist_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,9 @@
)
end

let(:media_lists) do
JSON.parse(fixture('list_import/anilist/toyhammered_full_list.json'))
.deep_transform_keys(&:underscore)
end

before do
allow(AnilistApiWrapper::Client).to receive(:query) {
JSON.parse(media_lists.to_json, object_class: OpenStruct)
}
stub_request(:post, 'https://graphql.anilist.co')
.to_return(body: fixture('list_import/anilist/toyhammered_full_list.json'))
end

describe 'validations' do
Expand Down

0 comments on commit 5b28786

Please sign in to comment.