Skip to content

Commit

Permalink
feat: dynamic show recommended restaurant type
Browse files Browse the repository at this point in the history
  • Loading branch information
FawenYo committed Jan 2, 2021
1 parent a5ea2a7 commit 0069006
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 37 deletions.
83 changes: 50 additions & 33 deletions project/food/google_maps/info.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import random
import sys
import threading

import requests

sys.path.append(".")
from config import GOOGLE_MAPS_APIKEY, GOOGLE_MAPS_REQUEST_FIELD
import config
from food.restaurant import Restaurant


Expand All @@ -16,8 +15,9 @@ def __init__(
longitude: float,
keyword: str = "",
search_type: str = "restaurant",
complete_mode=False,
page_token="",
complete_mode: bool = False,
page_token: str = "",
index: int = 0,
):
"""初始化
Expand All @@ -26,7 +26,9 @@ def __init__(
longitude (float): 經度.
keyword (str): 關鍵字列表,以 " " 分割.
search_type (str, optional): 限制類別. Defaults to "restaurant".
complete_mode(bool): 限制搜尋.
complete_mode(bool): 限制搜尋. Defaults to false.
page_token (str, optional): 頁面搜尋token. Defaults to "".
index (int, optional): 搜尋項目. Defaults to 0.
"""
self.restaurants = []
self.threads = []
Expand All @@ -37,28 +39,22 @@ def __init__(
self.keyword = keyword
self.search_type = search_type
self.complete_mode = complete_mode
self.current_page = page_token
self.index = index

self.fetch_data(pagetoken=page_token)
self.fetch_data(page_token=page_token)

def fetch_data(
self,
pagetoken: str = "",
):
"""Google Maps 餐廳資料
Args:
pagetoken (str): Google Maps search page token.
"""
def fetch_data(self, page_token):
# Google Maps 餐廳資料
radius = 1000 if not self.complete_mode else 50000
param_data = {
"language": "zh-TW",
"location": f"{self.latitude},{self.longitude}",
"radius": radius,
"type": self.search_type,
"keyword": self.keyword,
"pagetoken": pagetoken,
"key": GOOGLE_MAPS_APIKEY,
"pagetoken": page_token,
"key": config.GOOGLE_MAPS_APIKEY,
}
response = requests.get(
f"https://maps.googleapis.com/maps/api/place/nearbysearch/json",
Expand All @@ -68,21 +64,22 @@ def fetch_data(

def parse_data(self, data):
if not self.complete_mode:
if len(data["results"]) < 6:
filter_results = data["results"]
else:
filter_results = random.sample(data["results"], 6)
filter_results = data["results"][0 + 5 * self.index : 5 + 5 * self.index]
else:
filter_results = data["results"]
for place in filter_results:
thread = threading.Thread(target=self.get_place_data, args=(place,))
self.threads.append(thread)
if not self.complete_mode or "next_page_token" not in data:
if "next_page_token" in data:
self.next_page = data["next_page_token"]
if not self.complete_mode:
if len(data["results"][5 + 5 * self.index :]) > 0:
self.next_page = f"{self.current_page}[|]{self.index + 1}"
elif "next_page_token" in data:
self.next_page = f"{data['next_page_token']}[|]0"
self.start_thread()
elif "next_page_token" not in data:
self.start_thread()
else:
self.fetch_data(pagetoken=data["next_page_token"])
self.fetch_data(page_token=data["next_page_token"])

def start_thread(self):
for thread in self.threads:
Expand All @@ -99,15 +96,35 @@ def get_place_data(self, place):
photo_url = self.place_photo(photo_reference=photo_reference)
name = place["name"]
location = place["geometry"]["location"]
open_now = place["opening_hours"]["open_now"]
if "opening_hours" not in place:
open_now = False
else:
open_now = place["opening_hours"]["open_now"]
rating = place["rating"]
operating_time = detail["opening_hours"]
if "opening_hours" not in detail:
operating_time = {
"open_now": False,
"periods": [],
"weekday_text": [
"星期一: 休息",
"星期二: 休息",
"星期三: 休息",
"星期四: 休息",
"星期五: 休息",
"星期六: 休息",
"星期日: 休息",
],
}
else:
operating_time = detail["opening_hours"]
address = detail["formatted_address"]
phone_number = detail["formatted_phone_number"]
if "website" in detail:
website = detail["website"]
else:
elif "url" in place:
website = place["url"]
else:
website = "https://www.google.com.tw/maps"
google_url = detail["url"]
reviews = []
for each in detail["reviews"]:
Expand All @@ -130,17 +147,17 @@ def get_place_data(self, place):
)
self.restaurants.append(restaurant)
except KeyError:
pass
config.console.print_exception()

def place_detail(self, place_id):
fileds_data = ",".join(GOOGLE_MAPS_REQUEST_FIELD)
fileds_data = ",".join(config.GOOGLE_MAPS_REQUEST_FIELD)
response = requests.get(
f"https://maps.googleapis.com/maps/api/place/details/json?language=zh-TW&place_id={place_id}&fields={fileds_data}&key={GOOGLE_MAPS_APIKEY}"
f"https://maps.googleapis.com/maps/api/place/details/json?language=zh-TW&place_id={place_id}&fields={fileds_data}&key={config.GOOGLE_MAPS_APIKEY}"
).json()
return response["result"]

def place_photo(self, photo_reference, max_width=400):
photo_url = requests.get(
f"https://maps.googleapis.com/maps/api/place/photo?maxwidth={max_width}&photoreference={photo_reference}&key={GOOGLE_MAPS_APIKEY}"
f"https://maps.googleapis.com/maps/api/place/photo?maxwidth={max_width}&photoreference={photo_reference}&key={config.GOOGLE_MAPS_APIKEY}"
).url
return photo_url
13 changes: 10 additions & 3 deletions project/food/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from .ifoodie.ifoodie import Ifoodie

sys.path.append(".")
import config
import MongoDB.operation as database
from bson.son import SON
from pymongo import GEOSPHERE

import config
import MongoDB.operation as database


class Nearby_restaurant:
def __init__(self, latitude, longitude, keyword="", page_token=""):
Expand Down Expand Up @@ -96,12 +97,18 @@ def get_google_maps_data(self, complete_mode=False):
Args:
complete_mode (bool, optional): Set it to True to get complete data. Defaults to False.
"""
if "[|]" not in self.page_token:
page_token = self.page_token
index = 0
else:
page_token, index = self.page_token.split("[|]")
restaurants = GM_Restaurant(
latitude=self.latitude,
longitude=self.longitude,
keyword=self.keyword,
complete_mode=complete_mode,
page_token=self.page_token,
page_token=page_token,
index=int(index),
)
if not complete_mode:
self.next_page = restaurants.next_page
Expand Down
27 changes: 26 additions & 1 deletion project/line/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from food.main import Nearby_restaurant
from line.templates import Template
from vote.main import create_event
from weather.main import Weather

line_bot_api = LineBotApi(config.LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(config.LINE_CHANNEL_SECRET)
Expand Down Expand Up @@ -228,7 +229,8 @@ def handle_message(event):
)
thread.start()

restaurant_category = ["隨便", "日式", "中式", "西式", "咖哩", "其他"]
# 預設類別
restaurant_category = ["隨便", "日式", "中式", "西式"]
quick_reply_items = [
QuickReplyButton(
action=PostbackAction(
Expand All @@ -240,6 +242,29 @@ def handle_message(event):
for category in restaurant_category
]

# 動態類別
dynamic_update_category = Weather().customized_category(lat=lat, lng=lng)
temp_quick_reply_items = [
QuickReplyButton(
action=PostbackAction(
label=category,
display_text=category,
data=f"search_||_{lat},{lng}_||_{dynamic_update_category[category]}",
)
)
for category in list(dynamic_update_category.keys())
]

quick_reply_items += temp_quick_reply_items
quick_reply_items.append(
QuickReplyButton(
action=PostbackAction(
label="其他",
display_text="其他",
data=f"search_||_{lat},{lng}_||_其他",
)
)
)
message = TextSendMessage(
text="請選擇餐廳類別",
quick_reply=QuickReply(items=quick_reply_items),
Expand Down
81 changes: 81 additions & 0 deletions project/weather/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import re
import sys
from datetime import datetime, timedelta

import requests
from bs4 import BeautifulSoup


class Weather:
Expand Down Expand Up @@ -60,3 +63,81 @@ def parse_data(self, data):
self.min_temperature = data["now"]["minT"]
self.wx = data["now"]["wx"]
self.aqi = data["aqi"]["content"]["aqiValue"]

def customized_category(self, lat, lng) -> dict:
"""依照天氣、日期,動態的新增類別
Args:
lat (float): 緯度
lng (float): 經度
"""
self.fetch_data(lat=lat, lng=lng)

category_reference = {
"好冷,想來點...": "火鍋",
"好熱,想來點...": "冰品",
"週末假期,想來點...": "聚餐",
"這麼晚了,想來點...": "宵夜",
"情人節,想來點...": "聚餐",
"農曆新年,想來點...": "聚餐",
"元宵節,想來點...": "湯圓",
"端午節,想來點...": "粽子",
"中秋節,想來點...": "烤肉",
"冬至,想來點...": "湯圓",
}

def add_to_customized(keyword: str):
for category in category_reference.keys():
if keyword in category:
customized_category[category] = category_reference[category]
break

customized_category = {}

if self.temperature >= 25 or self.max_temperature >= 25:
add_to_customized(keyword="好熱")
elif self.temperature <= 20 or self.min_temperature <= 25:
add_to_customized(keyword="好冷")

# 判斷是否今天是否為節日前後
today = datetime.now()
response = requests.get(f"https://toolskk.com/{today.year}calendar", timeout=10)
soup = BeautifulSoup(response.text, "html.parser")

festivals = {
"農曆新年": re.findall("(\d{1,2}/\d{1,2}) 除夕過年", soup.text),
"情人節": re.findall("(\d{1,2}/\d{1,2}).*?情人節", soup.text),
"端午節": re.findall("(\d{1,2}/\d{1,2}) 端午節", soup.text),
"中秋節": re.findall("(\d{1,2}/\d{1,2}) 中秋節", soup.text),
"元宵節": re.findall("(\d{1,2}/\d{1,2}) 元宵節", soup.text),
"冬至": re.findall("(\d{1,2}/\d{1,2}) 冬至", soup.text),
}

for festival, period in festivals.items():

if len(period) == 1:
if festival == "農曆新年":
start = datetime.strptime(f"{today.year}/{period[0]}", "%Y/%m/%d")
end = start + timedelta(days=7)

if start <= today <= end:
add_to_customized(keyword=festival)
elif festival == "中秋節":
base = datetime.strptime(f"{today.year}/{period[0]}", "%Y/%m/%d")
start = base - timedelta(days=15)
end = base + timedelta(days=15)
if start <= today <= end:
add_to_customized(keyword=festival)
else:
start = datetime.strptime(f"{today.year}/{period[0]}", "%Y/%m/%d")
if start == today:
add_to_customized(keyword=festival)
else:
for each in period:
if festival == "情人節":
end = datetime.strptime(f"{today.year}/{each}", "%Y/%m/%d")
start = end - timedelta(days=3)
if start <= today <= end:
add_to_customized(keyword=festival)

return customized_category

0 comments on commit 0069006

Please sign in to comment.