# frozen_string_literal: true require 'httparty' # GranblueWiki fetches and parses data from gbf.wiki module Granblue module Parsers class Wiki class_attribute :base_uri class_attribute :proficiencies class_attribute :elements class_attribute :rarities class_attribute :genders class_attribute :races class_attribute :bullets class_attribute :boolean class_attribute :character_series class_attribute :character_seasons self.base_uri = 'https://gbf.wiki/api.php' self.proficiencies = { 'Sabre' => 1, 'Dagger' => 2, 'Axe' => 3, 'Spear' => 4, 'Bow' => 5, 'Staff' => 6, 'Melee' => 7, 'Harp' => 8, 'Gun' => 9, 'Katana' => 10 }.freeze self.elements = { 'Wind' => 1, 'Fire' => 2, 'Water' => 3, 'Earth' => 4, 'Dark' => 5, 'Light' => 6 }.freeze self.rarities = { 'R' => 1, 'SR' => 2, 'SSR' => 3 }.freeze self.races = { 'Other' => 0, 'Human' => 1, 'Erune' => 2, 'Draph' => 3, 'Harvin' => 4, 'Primal' => 5 }.freeze self.genders = { 'o' => 0, 'm' => 1, 'f' => 2, 'mf' => 3 }.freeze self.bullets = { 'cartridge' => 1, 'rifle' => 2, 'parabellum' => 3, 'aetherial' => 4 }.freeze self.boolean = { 'yes' => true, 'no' => false }.freeze # Maps wiki |series= values to CHARACTER_SERIES enum values # Wiki uses lowercase, single values like "grand", "zodiac", etc. self.character_series = { 'grand' => 1, # Grand 'zodiac' => 2, # Zodiac 'promo' => 3, # Promo 'collab' => 4, # Collab 'eternal' => 5, # Eternal 'evoker' => 6, # Evoker 'archangel' => 7, # Saint (Archangels) 'fantasy' => 8, # Fantasy 'summer' => 9, # Summer 'yukata' => 10, # Yukata 'valentine' => 11, # Valentine 'halloween' => 12, # Halloween 'formal' => 13, # Formal 'holiday' => 14, # Holiday 'event' => 15 # Event }.freeze # Maps wiki seasonal indicators to CHARACTER_SEASONS enum values # Used for display disambiguation (e.g., "Vane [Halloween]") # If no season matches, value should be nil self.character_seasons = { 'valentine' => 1, # Valentine 'formal' => 2, # Formal 'summer' => 3, # Summer (includes Yukata) 'halloween' => 4, # Halloween 'holiday' => 5 # Holiday }.freeze # Maps wiki |obtain= values to PROMOTIONS enum values for weapons/summons # Wiki uses comma-separated values like "premium,gala,flash" def self.promotions { 'premium' => 1, # Premium 'classic' => 2, # Classic 'classic2' => 3, # Classic II 'gala' => 4, # Flash (wiki uses "gala" for Flash Gala) 'flash' => 4, # Flash (alternate) 'legend' => 5, # Legend 'valentine' => 6, # Valentine 'summer' => 7, # Summer 'halloween' => 8, # Halloween 'holiday' => 9, # Holiday 'collab' => 10, # Collab 'formal' => 11 # Formal }.freeze end def initialize(props: ['wikitext'], debug: false) @debug = debug @props = props.join('|') end def fetch(page) query_params = params(page).map do |key, value| "#{key}=#{value}" end.join('&') destination = "#{base_uri}?#{query_params}" ap "--> Fetching #{destination}" if @debug response = HTTParty.get(destination, headers: { 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' }) handle_response(response, page) end private def handle_response(response, page) case response.code when 200 if response.key?('error') raise WikiError.new(code: response['error']['code'], message: response['error']['info'], page: page) end response['parse']['wikitext']['*'] when 404 raise WikiError.new(code: 404, message: 'Page not found', page: page) when 500...600 raise WikiError.new(code: response.code, message: 'Server error', page: page) else raise WikiError.new(code: response.code, message: 'Unexpected response', page: page) end end def params(page) { action: 'parse', format: 'json', page: page, prop: @props } end end end end