-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Adds Foursquare locator script. #1284
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# Description: | ||
# Get last checkin of your bot's friends | ||
# | ||
# Dependencies: | ||
# "node-foursquare": "0.2.0" | ||
# | ||
# Configuration: | ||
# FOURSQUARE_CLIENT_ID | ||
# FOURSQUARE_CLIENT_SECRET | ||
# FOURSQUARE_ACCESS_TOKEN | ||
# | ||
# Commands: | ||
# hubot foursquare approve - Approves the bot user's pending friend requests | ||
# hubot foursquare friends - Lists the friends of the bot | ||
# hubot foursquare register - Tells how to friend the bot | ||
# where is __? - Filters recent checkins to a particular subset of users. | ||
# | ||
# Notes: | ||
# To obtain/set the FOURSQUARE_ACCESS_TOKEN, you will need to go through the OAuth handshake manually with your bot's credentials | ||
# | ||
# Authors: | ||
# stephenyeargin, jfryman, brandonvalentine | ||
|
||
Util = require "util" | ||
moment = require "moment" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to add this to the Dependencies too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that was a later contribution. Oops. Tested to work with
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The nice thing about moving to npm packages is you can specify real dependencies instead of relying on people to read documentation 😁 |
||
|
||
module.exports = (robot) -> | ||
|
||
config = secrets: | ||
clientId: process.env.FOURSQUARE_CLIENT_ID | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll want to check that these are set at some point, and reply back with an message on how to fix it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preference for on-load or on-command? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on-command, because on-load is hidden in logs, but on-command is more visible to end-users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can I get away with it just on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'd want to apply it to anything that hits the API and needs those. Otherwise, you'll have silent failures. Using pagerduty.coffee as example again:
|
||
clientSecret: process.env.FOURSQUARE_CLIENT_SECRET | ||
accessToken: process.env.FOURSQUARE_ACCESS_TOKEN | ||
redirectUrl: "localhost" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not used AFAICT. I think I was just trying to keep the foursquare node module happy in case they ever try to check for those vars. |
||
|
||
foursquare = require('node-foursquare')(config); | ||
|
||
# Who are my friends? | ||
robot.respond /foursquare friends/i, (msg) -> | ||
params = {} | ||
foursquare.Users.getFriends 'self', params, config.secrets.accessToken, (error, response) -> | ||
|
||
# Loop through friends | ||
if response.friends.items.length > 0 | ||
list = [] | ||
for own key, friend of response.friends.items | ||
user_name = formatName friend | ||
list.push user_name | ||
|
||
msg.send list.join(", ") | ||
else | ||
msg.send "Your bot has no friends. :(" | ||
|
||
# Approve pending bot friend quests | ||
robot.respond /foursquare approve/i, (msg) -> | ||
foursquare.Users.getRequests config.secrets.accessToken, (error, response) -> | ||
|
||
# Loop through requests | ||
if response.requests.length > 0 | ||
|
||
for own key, friend of response.requests | ||
msg.http("https://api.foursquare.com/v2/users/#{friend.id}/approve?oauth_token=#{config.secrets.accessToken}").post() (err, res, body) -> | ||
user_name = formatName friend | ||
msg.send "Approved: #{user_name}" | ||
|
||
# Your bot is lonely | ||
else | ||
msg.send "No friend requests to approve." | ||
|
||
# Tell people how to friend the bot | ||
robot.respond /foursquare register/i, (msg) -> | ||
foursquare.Users.getUser 'self', config.secrets.accessToken, (error, response) -> | ||
profile_url = "https://foursquare.com/user/#{response.user.id}" | ||
user_name = response.user | ||
msg.send "Head to #{profile_url} and friend #{user_name}!" | ||
msg.send response.user.bio if response.user.bio? | ||
|
||
# Find your friends | ||
robot.hear /where[ ']i?s ([a-zA-Z0-9 ]+)(\?)?/i, (msg) -> | ||
searchterm = msg.match[1].toLowerCase() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if username doesn't match between chat and foursquare? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great question. We hit this problem as well. Foursquare doesn't emit the screen-name of the account either, and their There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One trick we use in pagerduty.coffee is a command like |
||
|
||
params = | ||
limit: 100 | ||
|
||
foursquare.Checkins.getRecentCheckins params, config.secrets.accessToken, (error, response) -> | ||
|
||
# Loop through friends | ||
found = 0 | ||
for own key, checkin of response.recent | ||
|
||
# Skip if no string match | ||
user_name = formatName checkin.user | ||
user_name = user_name.toLowerCase() | ||
if ~user_name.indexOf searchterm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also do Hilariously, I didn't even know ~ was a thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neither did I. Can't even remember how I came across it. ❇️ |
||
timeFormatted = moment(new Date(checkin.createdAt*1000)).fromNow() | ||
msg.send "#{checkin.user.firstName} #{checkin.user.lastName} was at #{checkin.venue.name} #{timeFormatted}" | ||
found++ | ||
|
||
# If loop failed to come up with a result, tell them | ||
if found is 0 | ||
msg.send "Could not find a recent checkin from #{searchterm}." | ||
|
||
# Format a name string | ||
formatName = (user) -> | ||
if user.lastName? | ||
return "#{user.firstName} #{user.lastName}" | ||
else if user.firstName? | ||
return user.firstName | ||
else | ||
return "(No Name)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For help commands, I usually use a convention like:
where is <user>?
. It's similar to the formatting used in man pages, bu t I have yet to find a name what that actually is.