Module: PokePaste
- Defined in:
- lib/pokepaste.rb,
lib/pokepaste/team.rb,
lib/pokepaste/pokemon.rb
Defined Under Namespace
Class Method Summary collapse
Class Method Details
.fetch(str) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/pokepaste.rb', line 90 def self.fetch(str) input_url = URI.parse(str) unless [nil, "pokepast.es"].include? input_url.host raise ArgumentError, "invalid URL; must be valid pokepast.es URL or path, received '#{str}'" end path = (input_url.host ? input_url.path : str).gsub /^\//, "" if path.empty? raise ArgumentError, "invalid URL; no paste ID found in '#{str}'" end # The paste is in <article> tags paste_content = URI.open("https://pokepast.es/#{path}").read. slice(/(?<=\<article\>)[\S\s]*(?=\<\/article\>)/) unless paste_content raise OpenURI::HTTPError.new "no paste found at '#{str}'", 404 end # Removing all HTML tags is sufficient to pass the string to the parser parse paste_content.gsub(/\<\/?[^\>]+\>/, "") end |
.parse(paste) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/pokepaste.rb', line 7 def self.parse(paste) # Each paragraph is a Pokémon (separated by 1 or more blank lines) paragraphs = paste.strip.split(/\n\s*\n/).map { |p| p.split("\n").map &:strip } team = PokePaste::Team.new paragraphs.each do |paragraph| # Line 1 can contain species, nickname, gender, and item in format like: # Bud (Bulbasaur) (M) @ Life Orb # Only the species is required, however line1 = paragraph.shift before_at, item = line1.split /\s+@\s+/ # Now work from right to left, parsing off the parts in parens # Set the gender to nil, :male, or :female if gender = before_at.slice!(/\s*\((m(ale)?|f(emale)?)\)$/i) # Get rid of the parens [/^\s*\(/, /\)$/].each { |regex| gender.slice! regex } gender = PokePaste::Pokemon.gender_abbrs[gender.downcase[0].to_sym] end # This regex requires a space between the nickname and opening paren if species = before_at.slice!(/\s+\([^\)]+\)$/i) # We found the species inside parens, which means a nickname is present [/^\s*\(/, /\)$/].each { |regex| species.slice! regex } nickname = before_at else # Otherwise all that remains is the species, and there is no nickname species = before_at nickname = nil end pkmn = PokePaste::Pokemon.new species: species, nickname: nickname, item: item, gender: gender # Pull the moves out pkmn.moves, paragraph = paragraph.partition { |line| line =~ /^\s*-/ } if pkmn.moves.any? pkmn.moves.map! do |line| move_slot = line.sub /^\s*-\s*/, "" move_slot.include?("/") ? move_slot.split(/\s*\/\s*/) : move_slot end end # Pull the nature out. If there are multiple, the first is used nature_line, paragraph = paragraph.partition { |line| line =~ /nature\s*$/i } if nature_line.any? pkmn.nature = nature_line.first.sub(/\s*nature\s*$/i, "").downcase.to_sym end # All that we're left with at this point are attributes that are denoted with # the syntax "Attribute: Value". Let's loop over them and parse the attribute paragraph.each do |line| attribute, value = line.split /\s*:\s*/, 2 attribute = attribute.downcase.gsub(/\s+/, "_").to_sym # At this point attribute will be a symbol with the snake_case approximation # of whatever was before the first ":" in the string. If we know what it does, # we can manipulate it as desired, otherwise just let it through as a string. # This is intended to be a flexible format. if i[evs ivs].include?(attribute) data = value.split /\s*\/\s*/ data.map { |d| d.split /\s+/, 2 }.each do |value, stat| current_value = pkmn.send attribute current_value[stat.downcase.to_sym] = value.to_i pkmn.send "#{attribute}=", current_value end elsif i[level happiness].include?(attribute) pkmn.send "#{attribute}=", value.to_i elsif attribute == :shiny pkmn.shiny = %w[yes true].include?(value.downcase) else pkmn.send "#{attribute}=", value end end team << pkmn end team end |