Fetching contributors…
Cannot retrieve contributors at this time
131 lines (119 sloc) 4.87 KB
# Description:
# A way to interact with the Google Images API.
# Configuration
# HUBOT_GOOGLE_CSE_KEY - Your Google developer API key
# HUBOT_GOOGLE_CSE_ID - The ID of your Custom Search Engine
# HUBOT_MUSTACHIFY_URL - Optional. Allow you to use your own mustachify instance.
# HUBOT_GOOGLE_IMAGES_HEAR - Optional. If set, bot will respond to any line that begins with "image me" or "animate me" without needing to address the bot directly
# HUBOT_GOOGLE_SAFE_SEARCH - Optional. Search safety level.
# HUBOT_GOOGLE_IMAGES_FALLBACK - The URL to use when API fails. `{q}` will be replaced with the query string.
# Commands:
# hubot image me <query> - The Original. Queries Google Images for <query> and returns a random top result.
# hubot animate me <query> - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead.
# hubot mustache me <url|query> - Adds a mustache to the specified URL or query result.
module.exports = (robot) ->
robot.respond /(image|img)( me)? (.+)/i, (msg) ->
imageMe msg, msg.match[3], (url) ->
msg.send url
robot.respond /animate( me)? (.+)/i, (msg) ->
imageMe msg, msg.match[2], true, (url) ->
msg.send url
# pro feature, not added to docs since you can't conditionally document commands
robot.hear /^(image|img) me (.+)/i, (msg) ->
imageMe msg, msg.match[2], (url) ->
msg.send url
robot.hear /^animate me (.+)/i, (msg) ->
imageMe msg, msg.match[1], true, (url) ->
msg.send url
robot.respond /(?:mo?u)?sta(?:s|c)h(?:e|ify)?(?: me)? (.+)/i, (msg) ->
if not process.env.HUBOT_MUSTACHIFY_URL?
msg.send "Sorry, the Mustachify server is not configured."
, ""
mustacheBaseUrl =
process.env.HUBOT_MUSTACHIFY_URL?.replace(/\/$/, '')
mustachify = "#{mustacheBaseUrl}/rand?src="
imagery = msg.match[1]
if imagery.match /^https?:\/\//i
encodedUrl = encodeURIComponent imagery
msg.send "#{mustachify}#{encodedUrl}"
imageMe msg, imagery, false, true, (url) ->
encodedUrl = encodeURIComponent url
msg.send "#{mustachify}#{encodedUrl}"
imageMe = (msg, query, animated, faces, cb) ->
cb = animated if typeof animated == 'function'
cb = faces if typeof faces == 'function'
googleCseId = process.env.HUBOT_GOOGLE_CSE_ID
if googleCseId
# Using Google Custom Search API
googleApiKey = process.env.HUBOT_GOOGLE_CSE_KEY
if !googleApiKey
msg.robot.logger.error "Missing environment variable HUBOT_GOOGLE_CSE_KEY"
msg.send "Missing server environment variable HUBOT_GOOGLE_CSE_KEY."
q =
q: query,
safe: process.env.HUBOT_GOOGLE_SAFE_SEARCH || 'high',
cx: googleCseId,
key: googleApiKey
if animated is true
q.fileType = 'gif'
q.hq = 'animated'
q.tbs = 'itp:animated'
if faces is true
q.imgType = 'face'
url = ''
.get() (err, res, body) ->
if err
if res.statusCode is 403
msg.send "Daily image quota exceeded, using alternate source."
deprecatedImage(msg, query, animated, faces, cb)
msg.send "Encountered an error :( #{err}"
if res.statusCode isnt 200
msg.send "Bad HTTP response :( #{res.statusCode}"
response = JSON.parse(body)
if response?.items
image = msg.random response.items
cb ensureResult(, animated)
msg.send "Oops. I had trouble searching '#{query}'. Try later."
((error) ->
msg.robot.logger.error error.message
.error "(see #{error.extendedHelp})" if error.extendedHelp
) error for error in response.error.errors if response.error?.errors
msg.send "Google Image Search API is no longer available. " +
"Please [setup up Custom Search Engine API]("
deprecatedImage(msg, query, animated, faces, cb)
deprecatedImage = (msg, query, animated, faces, cb) ->
# Show a fallback image
imgUrl = process.env.HUBOT_GOOGLE_IMAGES_FALLBACK ||
imgUrl = imgUrl.replace(/\{q\}/, encodeURIComponent(query))
cb ensureResult(imgUrl, animated)
# Forces giphy result to use animated version
ensureResult = (url, animated) ->
if animated is true
ensureImageExtension url.replace(
ensureImageExtension url
# Forces the URL look like an image URL by adding `#.png`
ensureImageExtension = (url) ->
if /(png|jpe?g|gif)$/i.test(url)