def getFitroomResults(chat_id, context): """ Call fitroom search api with url of image to search for then send results """ image_url = context['user_img_url'] chat_id = context['chat_id'] from_user = context['from_user'] # NOTE: this donwloads the image anytime the user is on Facebook # really we only need to download if the user sent us the picture (we don't need to download images from textseach results or other preloaded queries) if context['platform'] == 'FB': img2 = requests.get(image_url).content img64 = base64.b64encode(img2) api_url = "http://mongodb-dev.us-west-1.elasticbeanstalk.com/api/B64Search/" payload = {"DataString": 'data:image/jpeg;base64,' + img64} elif context['platform'] == 'KIK': api_url = "http://mongodb-dev.us-west-1.elasticbeanstalk.com/api/UrlSearch/" payload = {'url': image_url} r = requests.post(api_url, json=payload) responseFromAPI = r.json() if r.status_code != 200: # Something went wrong with fitroom API! say( chat_id, context, canned_responses.error_message() + "Ouch, that hurt my brain. You almost blew my circuts!") return Response(status=500) # Show the fitroom results, and clean out the bad images from the json context['image_query_result_index'] = 0 context['image_query_result'] = responseFromAPI showFitRoomResults(chat_id, from_user, context) return Response(status=200)
def getFitroomResults(chat_id,context): """ Call fitroom search api with url of image to search for then send results """ image_url = context['user_img_url'] chat_id = context['chat_id'] from_user = context['from_user'] # NOTE: this donwloads the image anytime the user is on Facebook # really we only need to download if the user sent us the picture (we don't need to download images from textseach results or other preloaded queries) if context['platform'] == 'FB': img2 = requests.get(image_url).content img64 = base64.b64encode(img2) api_url = "http://mongodb-dev.us-west-1.elasticbeanstalk.com/api/B64Search/" payload = {"DataString": 'data:image/jpeg;base64,'+img64} elif context['platform'] == 'KIK': api_url = "http://mongodb-dev.us-west-1.elasticbeanstalk.com/api/UrlSearch/" payload = {'url':image_url} r = requests.post(api_url,json=payload) responseFromAPI = r.json() if r.status_code != 200: # Something went wrong with fitroom API! say(chat_id,context,canned_responses.error_message()+"Ouch, that hurt my brain. You almost blew my circuts!") return Response(status=500) # Show the fitroom results, and clean out the bad images from the json context['image_query_result_index'] = 0 context['image_query_result'] = responseFromAPI showFitRoomResults(chat_id,from_user,context) return Response(status=200)
def searchAgain(chat_id, context): """ User has selected a picture she likes and would like to run a visual search agaist this picture. This fn collects the url of the liked picture and sends it to doSearchEncounter """ from_user = context['from_user'] prev_context = retrieveContext(chat_id, from_user) print prev_context.keys() if 'image_query_result' not in prev_context and 'text_query_result' not in prev_context: say(chat_id, context, canned_responses.error_message()) return Response(status=200) elif 'selected_outfit' not in prev_context: say(chat_id, context, canned_responses.error_message()) return Response(status=200) else: i = int(prev_context['selected_outfit']) - 1 if prev_context['search_type'] == 'image': i = i + int( prev_context['image_query_result_index']) - SHOW_THIS_MANY user_img_url = prev_context['image_query_result']['images'][i][ 'imageUrl'] elif prev_context['search_type'] == 'text': i = i + int( prev_context['text_query_result_index']) - SHOW_THIS_MANY user_img_url = prev_context['text_query_result']['products'][i][ 'image']['sizes']['Best']['url'] prev_context['user_img_url'] = user_img_url prev_context['search_type'] = 'image' storeContext(chat_id, from_user, prev_context, action='searchAgain') doSearchEncounter(chat_id, prev_context) return Response(status=200)
def searchAgain(chat_id,context): """ User has selected a picture she likes and would like to run a visual search agaist this picture. This fn collects the url of the liked picture and sends it to doSearchEncounter """ from_user = context['from_user'] prev_context = retrieveContext(chat_id,from_user) print prev_context.keys() if 'image_query_result' not in prev_context and 'text_query_result' not in prev_context: say(chat_id,context,canned_responses.error_message()) return Response(status=200) elif 'selected_outfit' not in prev_context: say(chat_id,context,canned_responses.error_message()) return Response(status=200) else: i = int(prev_context['selected_outfit'])-1 if prev_context['search_type'] == 'image': i = i+ int(prev_context['image_query_result_index'])- SHOW_THIS_MANY user_img_url = prev_context['image_query_result']['images'][i]['imageUrl'] elif prev_context['search_type'] == 'text': i = i+ int(prev_context['text_query_result_index'])- SHOW_THIS_MANY user_img_url = prev_context['text_query_result']['products'][i]['image']['sizes']['Best']['url'] prev_context['user_img_url'] = user_img_url prev_context['search_type'] = 'image' storeContext(chat_id,from_user,prev_context,action='searchAgain') doSearchEncounter(chat_id, prev_context) return Response(status=200)
def seeMoreResults(chat_id, context): from_user = context['from_user'] context = retrieveContext(chat_id, from_user) say(chat_id, context, canned_responses.see_more()) if context['search_type'] == 'image': showFitRoomResults(chat_id, from_user, context) else: showShopStyleResults(chat_id, from_user, context)
def seeMoreResults(chat_id,context): from_user = context['from_user'] context = retrieveContext(chat_id,from_user) say(chat_id,context,canned_responses.see_more()) if context['search_type'] == 'image': showFitRoomResults(chat_id,from_user,context) else: showShopStyleResults(chat_id,from_user,context)
def showFitRoomResults(chat_id, from_user, context): """ Sends picture messages through kik using results from Fitroom args: chat_id from_user responseFromAPI: json from fitroom returns: responseFromAPI: removed dead image links """ responseFromAPI = context['image_query_result'] # clean up resuts, lots of duplicates in results.... result_image_urls = [ value['imageUrl'] for value in responseFromAPI['images'] ] image_query_result_index = int(context['image_query_result_index']) i = 0 if image_query_result_index + SHOW_THIS_MANY >= len(result_image_urls): say( chat_id, context, "Well, maybe not. Gosh, you're hard to please :/ Try sending me back a pic of something I've showed you already to keep looking." ) return responseFromAPI urls = [] titles = [] for an_image in result_image_urls[image_query_result_index:]: if i >= SHOW_THIS_MANY: break # some images are blank, they have exactly 5086 or 3084 bytes. This hack # skips any images that size. Hacky fix until they fix it on the backend. is_blank = requests.head(an_image, headers={'Accept-Encoding': 'identity'}) if is_blank.status_code != 200 or is_blank.headers[ 'content-length'] in ('5086', '3084'): responseFromAPI['images'].pop(i) continue urls.append(an_image) titles.append(responseFromAPI['images'][i]['title']) print an_image, responseFromAPI['images'][i]['pageUrl'] i += 1 dispatchMessage(context, 'image', chat_id, from_user, urls, suggested_responses=titles) context[ 'image_query_result_index'] = i + image_query_result_index # remember which results we've showed context['image_query_result'] = responseFromAPI storeContext(chat_id, from_user, context, action='showFitroomResults') if context['platform'] == 'KIK': selectAnImageMsg(chat_id, context) return responseFromAPI
def index_kik(): """ Main entry point for Kik POSTing to us. Get messages in batches an iter through each message, deciding what to do """ # Make sure it's Kik sending us messages if not kik.verify_signature(request.headers.get('X-Kik-Signature'), request.get_data()): return Response(status=403) messages = messages_from_json(request.json['messages']) for message in messages: context0 = {'from_user': message.from_user, 'chat_id': message.chat_id} # Respond to mentions: we must send only one batch of messages if message.mention is not None: say( message.chat_id, context0, "Whoah Whoah Whoah! One at a time please. Are you trying to overload my circuts?!" ) continue # check to see if we've seen this user before, collect their previous context if retrieveContext(message.chat_id, message.from_user): context0 = retrieveContext(message.chat_id, message.from_user) context0['platform'] = 'KIK' if isinstance(message, TextMessage): storeContext(message.chat_id, message.from_user, context0, msg=message.body) selectActionFromText(message.chat_id, message.from_user, message.body, context0) elif isinstance(message, PictureMessage): # Always do a fitroom search when we get a picture message context0['user_img_url'] = message.pic_url context0['search_type'] = 'image' storeContext(message.chat_id, message.from_user, context0) doSearchEncounter(message.chat_id, context0) elif isinstance(message, StartChattingMessage): # User has started a chart for the first time; this is sent only once every for each user sendWelcomeMessage(message.chat_id, context0) else: # don't know how to respond to other messages e.g. videos say( message.chat_id, context0, "I'm new here. I'll be learning as I'm going. Try sending me a pic of a dress you'd like to search for" ) return Response( status=200 ) # If we return anything besides 200, Kik will try 3 more time to send the message
def doSearchEncounter(chat_id, context): """ This fn is used to run through a search encounter The user has either sent a pic to search with or used a text query by typing 'find me a xxxx', in that case Wit calls doTextSearchEncounter which inturn calls doSearchEncounter. doSearchEncounter is called directly when a user sends a pic """ search_type = context['search_type'] say(chat_id, context, canned_responses.lookup()) if search_type == 'image': getFitroomResults(chat_id, context) elif search_type == 'text': getShopStyleResults(chat_id, context)
def doSearchEncounter(chat_id,context): """ This fn is used to run through a search encounter The user has either sent a pic to search with or used a text query by typing 'find me a xxxx', in that case Wit calls doTextSearchEncounter which inturn calls doSearchEncounter. doSearchEncounter is called directly when a user sends a pic """ search_type = context['search_type'] say(chat_id,context,canned_responses.lookup()) if search_type == 'image': getFitroomResults(chat_id,context) elif search_type == 'text': getShopStyleResults(chat_id,context)
def showFitRoomResults(chat_id,from_user,context): """ Sends picture messages through kik using results from Fitroom args: chat_id from_user responseFromAPI: json from fitroom returns: responseFromAPI: removed dead image links """ responseFromAPI = context['image_query_result'] # clean up resuts, lots of duplicates in results.... result_image_urls = [value['imageUrl'] for value in responseFromAPI['images']] image_query_result_index = int(context['image_query_result_index']) i=0 if image_query_result_index+SHOW_THIS_MANY >= len(result_image_urls): say(chat_id,context,"Well, maybe not. Gosh, you're hard to please :/ Try sending me back a pic of something I've showed you already to keep looking.") return responseFromAPI urls=[] titles=[] for an_image in result_image_urls[image_query_result_index:]: if i >= SHOW_THIS_MANY: break # some images are blank, they have exactly 5086 or 3084 bytes. This hack # skips any images that size. Hacky fix until they fix it on the backend. is_blank =requests.head(an_image, headers={'Accept-Encoding': 'identity'}) if is_blank.status_code != 200 or is_blank.headers['content-length'] in ('5086', '3084'): responseFromAPI['images'].pop(i) continue urls.append(an_image) titles.append(responseFromAPI['images'][i]['title']) print an_image, responseFromAPI['images'][i]['pageUrl'] i +=1 dispatchMessage(context,'image',chat_id,from_user,urls,suggested_responses=titles) context['image_query_result_index'] = i + image_query_result_index # remember which results we've showed context['image_query_result'] = responseFromAPI storeContext(chat_id,from_user,context,action='showFitroomResults') if context['platform'] == 'KIK': selectAnImageMsg(chat_id,context) return responseFromAPI
def getShopStyleResults(chat_id, context): """ Run a text search against shopstyle api similar in function to getFitroomResults """ from_user = context['from_user'] context = retrieveContext(chat_id, from_user) if 'search_keywords' not in context: say(chat_id, context, canned_responses.error_message() + 'text_search') return Response(Status=200) search_keywords = '+'.join(context['search_keywords'].split()) API_URL = 'http://api.shopstyle.com/api/v2/products?pid=uid7984-31606272-0&format=json&fts={0}&offset=0&limit=10'.format( search_keywords) r = requests.get(API_URL) api_json = r.json() context['text_query_result'] = api_json context['text_query_result_index'] = 0 showShopStyleResults(chat_id, from_user, context) return Response(status=200)
def getShopStyleResults(chat_id,context): """ Run a text search against shopstyle api similar in function to getFitroomResults """ from_user = context['from_user'] context = retrieveContext(chat_id,from_user) if 'search_keywords' not in context: say(chat_id,context,canned_responses.error_message()+'text_search') return Response(Status=200) search_keywords = '+'.join(context['search_keywords'].split()) API_URL = 'http://api.shopstyle.com/api/v2/products?pid=uid7984-31606272-0&format=json&fts={0}&offset=0&limit=10'.format(search_keywords) r = requests.get(API_URL) api_json = r.json() context['text_query_result'] = api_json context['text_query_result_index'] = 0 showShopStyleResults(chat_id,from_user,context) return Response(status=200)
def buyThis(chat_id,context): """ User has selected a picture she likes, and would like to visit the store webpage """ from_user = context['from_user'] prev_context = retrieveContext(chat_id,from_user) if 'image_query_result' not in prev_context and 'text_query_result' not in prev_context: say(chat_id,context,canned_responses.error_message()+'query results issue') elif 'selected_outfit' not in prev_context: say(chat_id,context,canned_responses.error_message()+'selection issuse') else: i = int(prev_context['selected_outfit'])-1 if prev_context['search_type'] == 'image': i = int(prev_context['image_query_result_index'])-SHOW_THIS_MANY+i link = prev_context['image_query_result']['images'][i]['pageUrl'] title = prev_context['image_query_result']['images'][i]['title'] img_url = prev_context['image_query_result']['images'][i]['imageUrl'] # using a text message to send fitroom results because Kik breaks out links by putting a trailing "/" link_message = TextMessage(to=from_user,chat_id=chat_id,body=link) # link_message = LinkMessage(to=from_user,chat_id=chat_id,url=link,title=title) elif prev_context['search_type'] == 'text': i = int(prev_context['text_query_result_index'])-SHOW_THIS_MANY+i img_url = prev_context['text_query_result']['products'][i]['image']['sizes']['IPhone']['url'] link = prev_context['text_query_result']['products'][i]['clickUrl'] title = prev_context['text_query_result']['products'][i]['brandedName'] link_message = LinkMessage(to=from_user,chat_id=chat_id,url=link,title=title) if context['platform'] == 'KIK': here = TextMessage(to=from_user,chat_id=chat_id,body="Here ya go:") tip = TextMessage(to=from_user,chat_id=chat_id,body="Remember you can search again anytime by sending me a pic ;)") tip.keyboards.append( SuggestedResponseKeyboard( responses=[TextResponse('See more results'), TextResponse('Search with this pic'), TextResponse('New search')] )) kik.send_messages([here,link_message,tip]) elif context['platform'] == 'FB': dispatchMessage(context,'link',chat_id,from_user,[link],suggested_responses=[title],extras=[img_url])
def index_kik(): """ Main entry point for Kik POSTing to us. Get messages in batches an iter through each message, deciding what to do """ # Make sure it's Kik sending us messages if not kik.verify_signature(request.headers.get('X-Kik-Signature'), request.get_data()): return Response(status=403) messages = messages_from_json(request.json['messages']) for message in messages: context0 = {'from_user':message.from_user,'chat_id':message.chat_id} # Respond to mentions: we must send only one batch of messages if message.mention is not None: say(message.chat_id,context0,"Whoah Whoah Whoah! One at a time please. Are you trying to overload my circuts?!") continue # check to see if we've seen this user before, collect their previous context if retrieveContext(message.chat_id,message.from_user): context0 = retrieveContext(message.chat_id,message.from_user) context0['platform'] = 'KIK' if isinstance(message, TextMessage): storeContext(message.chat_id,message.from_user,context0,msg=message.body) selectActionFromText(message.chat_id,message.from_user,message.body,context0) elif isinstance(message, PictureMessage): # Always do a fitroom search when we get a picture message context0['user_img_url'] = message.pic_url context0['search_type'] = 'image' storeContext(message.chat_id,message.from_user,context0) doSearchEncounter(message.chat_id, context0) elif isinstance(message, StartChattingMessage): # User has started a chart for the first time; this is sent only once every for each user sendWelcomeMessage(message.chat_id,context0) else: # don't know how to respond to other messages e.g. videos say(message.chat_id,context0,"I'm new here. I'll be learning as I'm going. Try sending me a pic of a dress you'd like to search for") return Response(status=200) # If we return anything besides 200, Kik will try 3 more time to send the message
def buyThis(chat_id, context): """ User has selected a picture she likes, and would like to visit the store webpage """ from_user = context['from_user'] prev_context = retrieveContext(chat_id, from_user) if 'image_query_result' not in prev_context and 'text_query_result' not in prev_context: say(chat_id, context, canned_responses.error_message() + 'query results issue') elif 'selected_outfit' not in prev_context: say(chat_id, context, canned_responses.error_message() + 'selection issuse') else: i = int(prev_context['selected_outfit']) - 1 if prev_context['search_type'] == 'image': i = int( prev_context['image_query_result_index']) - SHOW_THIS_MANY + i link = prev_context['image_query_result']['images'][i]['pageUrl'] title = prev_context['image_query_result']['images'][i]['title'] img_url = prev_context['image_query_result']['images'][i][ 'imageUrl'] # using a text message to send fitroom results because Kik breaks out links by putting a trailing "/" link_message = TextMessage(to=from_user, chat_id=chat_id, body=link) # link_message = LinkMessage(to=from_user,chat_id=chat_id,url=link,title=title) elif prev_context['search_type'] == 'text': i = int( prev_context['text_query_result_index']) - SHOW_THIS_MANY + i img_url = prev_context['text_query_result']['products'][i][ 'image']['sizes']['IPhone']['url'] link = prev_context['text_query_result']['products'][i]['clickUrl'] title = prev_context['text_query_result']['products'][i][ 'brandedName'] link_message = LinkMessage(to=from_user, chat_id=chat_id, url=link, title=title) if context['platform'] == 'KIK': here = TextMessage(to=from_user, chat_id=chat_id, body="Here ya go:") tip = TextMessage( to=from_user, chat_id=chat_id, body= "Remember you can search again anytime by sending me a pic ;)") tip.keyboards.append( SuggestedResponseKeyboard(responses=[ TextResponse('See more results'), TextResponse('Search with this pic'), TextResponse('New search') ])) kik.send_messages([here, link_message, tip]) elif context['platform'] == 'FB': dispatchMessage(context, 'link', chat_id, from_user, [link], suggested_responses=[title], extras=[img_url])