Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
141 lines (134 sloc) 5.41 KB
#! ========================================
#! Pokémon
Discord = require 'discord.js'
request = require 'request'
r = (options) ->
new Promise (resolve, reject) ->
request options, (err, response, body) ->
if (
(not err) and
(200 <= response?.statusCode <= 400) and
(not JSON.parse(body).error)
resolve JSON.parse body
# Don't do JSON.body, pokeapi likes to return
# HTML-formatted 404s instead of error messages.
# This is the reason Haruka was crashing.
reject [err, response, body]
#! String utils
capitalize = (txt) ->
txt.charAt(0).toUpperCase() + txt.substr(1)
dasherize = (str) ->
.replace(/[^A-Za-z0-9\s]/g, '')
.replace(/\s+/g, '-')
undasherize = (str) ->
str.split('-').map((s) -> capitalize s).join(' ')
toDexNumber = (n) ->
'#' + n.toString().padStart 3, '0'
#! ========================================
#! Message handler
handler = (msg, match, Haruka) ->
pokeRequest = dasherize match.input.tokenize()[1]
if not pokeRequest then return msg.reply [
"Use `-h pkmn` followed by the Pokémon you want me to look up."
"I can look for Pokémon in my Pokédex if you use `-h pkmn`
followed by a Pokémon's name or its National Dex number."
"You’re missing an argument. Try `-h help pkmn` if
you forgot this command’s syntax."
[P, species, pkmn] = [{}, null, null]
pokeRequest = pokeRequest.replace(/0/g, '')
#! Fetch pkmn
r "{pokeRequest}/"
.then (s) ->
species = s
PPromise = r "{}/" = species.names
.filter((n) -> is "en")
P.dexNumber = toDexNumber
P.description = species.flavor_text_entries
.filter((f) -> is "en")
.replace(/\s+/g, ' ')
# Replace multiple occurrences of whitespace with just one space.
P.category = species.genera
.filter((genus) -> is "en")
return PPromise
.then (p) ->
pkmn = p
P.abilities = pkmn.abilities
.map((a) -> undasherize
.join(', ')
P.sprite = pkmn.sprites.front_default
P.types = -> capitalize
P.movepool = pkmn.moves.length + " moves"
P.stats = (s) ->
switch (
when "hp" then {pos: 0, txt: "HP: #{s.base_stat}"}
when "attack" then {pos: 1, txt: "Atk: #{s.base_stat}"}
when "defense" then {pos: 2, txt: "Def: #{s.base_stat}"}
when "special-attack" then {pos: 3, txt: "SpA: #{s.base_stat}"}
when "special-defense" then {pos: 4, txt: "SpD: #{s.base_stat}"}
when "speed" then {pos: 5, txt: "Spd: #{s.base_stat}"}
P.stats = P.stats
.sort((a, b) -> a.pos - b.pos)
.map((x) -> x.txt).join('; ')
.then ->
#! Create the embed object
embed = new Discord.RichEmbed()
.setColor '#448aff'
.setURL "{}/"
.setThumbnail P.sprite
.setTitle "#{capitalize}#{P.dexNumber}"
.setDescription P.description
.addField "National Dex \#", P.dexNumber, yes
.addField "Typing", P.types.join("/"), yes
.addField "Category", P.category, yes
.addField "Movepool", P.movepool, yes
.addField "Abilities", P.abilities
.addField "Base stats", P.stats embed
.catch (err) ->
[err, response, body] = err
body = JSON.parse(body)
if not (200 <= response?.statusCode <= 400)
msg.reply [
"Sorry, but I couldn't find that Pokémon.
Did you spell its name right?"
"I’m not finding that Pokémon in my Pokédex.
Perhaps try entering a Pokédex number instead?"
msg.reply [
"An unexpected error occurred while fetching the Pokémon.
This shouldn’t typically happen,
try again in a few seconds."
"A wild, unrecoverable error occurred!
Errors like this shouldn’t typically happen,
try again in a few seconds."
module.exports = {
name: "Pokémon"
regex: /^(pkmn|pokemon|pokémon|poke|poké)(\s+|$)/i
handler: handler
#! coffeelint: disable=max_line_length
short: "-h pkmn <...> ::
Get information regarding a Pokémon (See -h help pkmn)"
long: """
=== Help for Pokémon ===
*Aliases*: pkmn, pokemon, pokémon, poke, poké
-h pkmn <nameOrId> :: Given a Pokémon’s name or National Pokédex Number,
this command returns information on a specific Pokémon.
""" #! coffeelint: enable=max_line_length
You can’t perform that action at this time.