interactive bots: Add FourSquare bot and documentation.
This commit is contained in:
		
							parent
							
								
									6972ce61c8
								
							
						
					
					
						commit
						75a9101f30
					
				
					 3 changed files with 177 additions and 0 deletions
				
			
		
							
								
								
									
										32
									
								
								contrib_bots/lib/FourSquareBot/doc.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								contrib_bots/lib/FourSquareBot/doc.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| # FourSquare Bot | ||||
| 
 | ||||
| * This is a bot that returns a list of restaurants from a user input of location, | ||||
| proximity and restaurant type in that exact order. The number of returned | ||||
| restaurants are capped at 3 per request. | ||||
| 
 | ||||
| * The list of restaurants are brought to Zulip using an API. The bot sends a GET | ||||
| request to https://api.foursquare.com/v2/. If the user does not correctly input | ||||
| a location, proximity and a restaurant type, the bot will return an error message. | ||||
| 
 | ||||
| * For example, if the user says "@foursquare 'Chicago, IL' 80000 seafood", the bot | ||||
| will return: | ||||
| 
 | ||||
| Food nearby 'Chicago, IL' coming right up: | ||||
| 
 | ||||
|     Dee's Seafood Co. | ||||
|     2723 S Poplar Ave, Chicago, IL 60608, United States | ||||
|     Fish Markets | ||||
| 
 | ||||
|     Seafood Harbor | ||||
|     2131 S Archer Ave (at Wentworth Ave), Chicago, IL 60616, United States | ||||
|     Seafood Restaurants | ||||
| 
 | ||||
|     Joe's Seafood, Prime Steak & Stone Crab | ||||
|     60 E Grand Ave (at N Rush St), Chicago, IL 60611, United States | ||||
|     Seafood Restaurants | ||||
| 
 | ||||
| * If the user enters a wrong word, like "@foursquare 80000 donuts" or "@foursquare", | ||||
| then an error message saying invalid input will be displayed. | ||||
| 
 | ||||
| * To get the required API Key, visit: https://developer.foursquare.com/overview/auth | ||||
| for more information. | ||||
							
								
								
									
										2
									
								
								contrib_bots/lib/FourSquareBot/settings.ini
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								contrib_bots/lib/FourSquareBot/settings.ini
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| [Foursquare] | ||||
| api_key = abcdefghijksm | ||||
							
								
								
									
										143
									
								
								contrib_bots/lib/foursquare.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								contrib_bots/lib/foursquare.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| from __future__ import print_function | ||||
| from __future__ import absolute_import | ||||
| 
 | ||||
| import datetime as dt | ||||
| import re | ||||
| import requests | ||||
| from os.path import expanduser | ||||
| from six.moves import configparser as cp | ||||
| from six.moves import range | ||||
| 
 | ||||
| home = expanduser('~') | ||||
| CONFIG_PATH = home + '/zulip/contrib_bots/lib/FourSquareBot/settings.ini' | ||||
| 
 | ||||
| def get_api_key(): | ||||
|     # settings.ini must have been moved from | ||||
|     # ~/zulip/contrib_bots/lib/FourSquareBot/settings.ini into | ||||
|     # ~/settings.ini for program to work | ||||
|     # see doc.md for more information | ||||
|     with open(CONFIG_PATH) as settings: | ||||
|         config = cp.ConfigParser() | ||||
|         config.readfp(settings) | ||||
|         return config.get('Foursquare', 'api_key') | ||||
| 
 | ||||
| class FoursquareHandler(object): | ||||
|     def __init__(self): | ||||
|         self.api_key = get_api_key() | ||||
| 
 | ||||
|     def usage(self): | ||||
|         return ''' | ||||
|             This plugin allows users to search for restaurants nearby an inputted | ||||
|             location to a limit of 3 venues for every location. The name, address | ||||
|             and description of the restaurant will be outputted. | ||||
|             It looks for messages starting with '@foursquare'. | ||||
|             If you need help, simply type: | ||||
|             @foursquare /help into the Compose Message box | ||||
| 
 | ||||
|             Sample input: | ||||
|             @foursquare Chicago, IL | ||||
|             @foursquare help | ||||
|             ''' | ||||
| 
 | ||||
|     help_info = ''' | ||||
| The Foursquare bot can receive keyword limiters that specify the location, distance (meters) and | ||||
| cusine of a restaurant in that exact order. | ||||
| Please note the required use of quotes in the search location. | ||||
| 
 | ||||
| Example Inputs: | ||||
| @foursquare 'Millenium Park' 8000 donuts | ||||
| @foursquare 'Melbourne, Australia' 40000 seafood | ||||
|                 ''' | ||||
| 
 | ||||
|     def triage_message(self, message, client): | ||||
|         callers = ['@FourSquare', '@Foursquare', '@foursquare', '@4square', '@4sq'] | ||||
|         for call in callers: | ||||
|             if call in message['content']: | ||||
|                 return True | ||||
|                 break | ||||
|         return False | ||||
| 
 | ||||
|     def format_json(self, venues): | ||||
|         def format_venue(venue): | ||||
|             name = venue['name'] | ||||
|             address = ', '.join(venue['location']['formattedAddress']) | ||||
|             keyword = venue['categories'][0]['pluralName'] | ||||
|             blurb = '\n'.join([name, address, keyword]) | ||||
|             return blurb | ||||
| 
 | ||||
|         return '\n'.join(format_venue(venue) for venue in venues) | ||||
| 
 | ||||
|     def send_info(self, message, letter, client): | ||||
|         if message['type'] == 'private': | ||||
|             client.send_message(dict( | ||||
|                 type='private', | ||||
|                 to=message['sender_email'], | ||||
|                 content=letter, | ||||
|             )) | ||||
|         else: | ||||
|             client.send_message(dict( | ||||
|                 type='stream', | ||||
|                 subject=message['subject'], | ||||
|                 to=message['display_recipient'], | ||||
|                 content=letter, | ||||
|                 )) | ||||
| 
 | ||||
|     def handle_message(self, message, client, state_handler): | ||||
|         words = message['content'].split() | ||||
|         if "/help" in words: | ||||
|             self.send_info(message, self.help_info, client) | ||||
|             return | ||||
| 
 | ||||
|         # These are required inputs for the HTTP request. | ||||
|         try: | ||||
|             params = {'limit': '3'} | ||||
|             params['near']  = re.search('\'[A-Za-z]\w+[,]?[\s\w+]+?\'', message['content']).group(0) | ||||
|             params['v'] = 20170108 | ||||
|             params['oauth_token'] = self.api_key | ||||
|         except AttributeError: | ||||
|             pass | ||||
| 
 | ||||
|         # Optional params for HTTP request. | ||||
|         if len(words) >= 2: | ||||
|             try: | ||||
|                 params['radius'] = re.search('([0-9]){3,}', message['content']).group(0) | ||||
|             except AttributeError: | ||||
|                 pass | ||||
|             try: | ||||
|                 params['query'] = re.search('\s([A-Za-z]+)$', message['content']).group(0)[1:] | ||||
|             except AttributeError: | ||||
|                 params['query'] = 'food' | ||||
| 
 | ||||
|         response = requests.get('https://api.foursquare.com/v2/venues/search?', | ||||
|                                 params=params) | ||||
|         print(response.url) | ||||
|         if response.status_code == 200: | ||||
|             received_json = response.json() | ||||
|         else: | ||||
|             self.send_info(message, | ||||
|                            "Invalid Request\nIf stuck, try '@foursquare help'.", | ||||
|                            client) | ||||
|             return | ||||
| 
 | ||||
|         if received_json['meta']['code'] == 200: | ||||
|             response_msg = ('Food nearby ' + params['near'] | ||||
|                             + ' coming right up:\n' | ||||
|                             + self.format_json(received_json['response']['venues'])) | ||||
|             self.send_info(message, response_msg, client) | ||||
|             return | ||||
| 
 | ||||
|         self.send_info(message, | ||||
|                        "Invalid Request\nIf stuck, try '@foursquare help'.", | ||||
|                        client) | ||||
|         return | ||||
| 
 | ||||
| handler_class = FoursquareHandler | ||||
| 
 | ||||
| def test_get_api_key(): | ||||
|     # must change to your own api key for test to work | ||||
|     result = get_api_key() | ||||
|     assert result == 'abcdefghijksm' | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     test_get_api_key() | ||||
|     print('Success') | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jackson
						Jackson