def favorite_tour(): ''' Togggles whether a tour is favorited for a user. Returns "removed" or "created". Returns 422 if incorrect JSON arguments are provided. <u>JSON Args:</u> user_id, tour_id ''' if not checkLogin(): return notAuthorizedResponse() data = request.get_json() user_id = data.get("user_id") tour_id = data.get("tour_id") if user_id is None or tour_id is None: return "must supply tour_id and user_id", 422 query = get_session().query(FavoritesClass).filter( and_(FavoritesClass.user_id == user_id, FavoritesClass.tour_id == tour_id)) fav = safe_call(query, "first", None) deleted = False print(fav) if fav is None: fav = FavoritesClass() fav.user_id = user_id fav.tour_id = tour_id get_session().add(fav) else: get_session().delete(fav) deleted = True print(deleted) commitSession() return ("removed" if deleted else "created")
def search(): """ Searches tours. If user_id is specified, it will also check if each result is a favorited tour for that user. Will be returned as "is_fav: Bool" <u>URL Args:</u> interests, keywords, rating, priceMin/Max, city, page, page_size, user_id (optional) """ interests = request.args.get("interests", None) keyWordsStr = request.args.get("keywords", None) rating = request.args.get("rating", None) priceMin = request.args.get("priceMin", None) priceMax = request.args.get("priceMax", None) city = request.args.get("city", None) page = int(request.args.get("page", 0)) page_size = int(request.args.get("page_size", 10)) user_id = request.args.get("user_id", None) if page_size == 0: page_size = 1 query = get_session().query(Tour) if interests is not None: query = query.filter( or_(Tour.interests.any(name=x) for x in interests.split(','))) if keyWordsStr is not None: query = query.filter( or_((func.lower(Tour.name).contains(word.lower()) | func.lower(Tour.description).contains(word.lower())) for word in keyWordsStr.split(','))) if rating is not None: query = query.filter("Tour.average_rating>=" + rating) if priceMin is not None: query = query.filter("Tour.price>=" + priceMin) if priceMax is not None: query = query.filter("Tour.price<=" + priceMax) if city is not None: query = query.filter(Tour.address.has(city=city)) count = query.count() query = limiting_query(query, page, page_size) print(count) tours = safe_call(query, "all", None) result = [] if tours is None: tours = [] for tour in tours: stour = tour.serialize(True) is_fav = False if user_id is not None: is_fav = get_session().query(FavoritesClass).filter( and_(FavoritesClass.user_id == user_id, FavoritesClass.tour_id == stour["id_tour"])).scalar() is not None stour["is_fav"] = is_fav result.append(stour) return jsonify({ "page_count": math.ceil(count / page_size), "page_size": page_size, "page": page, "data": result })
def upload(self, file, filename, tourid=None, userid=None): result = Media() query = get_session().query(Media).filter(Media.id_tour == tourid) medias = safe_call(query, "all", None) rank = len(medias) + 1 extension = filename.split('.')[-1] key = None if userid is None: key = 'tour/' + tourid + '/' + filename else: key = 'user/profile/' + userid + '/' + filename url = 'https://s3.amazonaws.com/silktours-media/' + key result.upload_to_s3(file, filename, key) is_video = self.isVideo(extension) values = {} values['url'] = url values['is_video'] = is_video values['display_rank'] = rank values['id_tour'] = tourid values['file_name'] = filename if tourid is not None: result.post(values) return values
def get_tourevents(tourid): """ Gets a list of tour events for a tour. """ query = get_session().query(TourEvent).filter(TourEvent.id_tour == tourid) events = safe_call(query, "all", None) return jsonify([event.serialize() for event in events])
def create(data): result = None if "id_address" in data: result = get_session().query(Address).get(data["id_address"]) if result is None: result = Address() result.setProps(data) return result
def get_image(tourid): """ Gets all media for a given tour. """ if not checkLogin(): return notAuthorizedResponse() query = get_session().query(Media).filter(Media.id_tour == tourid) medias = safe_call(query, "all", None) return jsonify([media.serialize() for media in medias])
def edit_tour(tourid): """ Edits a tour. Takes the usual tour JSON. """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() tour = safe_call(get_session().query(Tour), "get", tourid) tour.createOrEdit(data) return jsonify(tour.serialize(False))
def compute_tour_event(eventId): """ Marks the given tour event as completed. Also creates a pending review. """ if not checkLogin(): return notAuthorizedResponse() event = safe_call(get_session().query(TourEvent), "get", eventId) event.state = "C" event.pending_review = True commitSession(event)
def clear_pending_review(eventId): """ Clears the pending review for the tour event. """ if not checkLogin(): return notAuthorizedResponse() event = safe_call(get_session().query(TourEvent), "get", eventId) event.pending_review = False commitSession(event) return "Success"
def edit_user(id): """ Edits a users object using the usual user JSON """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() user = safe_call(get_session().query(User), "get", id) user.create_or_edit(data) return jsonify(user.serialize())
def get_user_by_email(email): """ Gets a user by thier email """ #if not checkLogin(): # return notAuthorizedResponse() query = get_session().query(User).filter(User.email == email) user = safe_call(query, "first", None) if user is None: return jsonify({}), 404 return jsonify(user.serialize())
def create(data, id_tour=None): result = None if "id_stop" in data: result = get_session().query(Stop).get(data["id_stop"]) if result is None: result = Stop() result.set_props(data.get("id_tour"), data.get("lat"), data.get("lon")) if id_tour is not None: result.id_tour = id_tour commitSession(result) return result
def edit_tourevent(eventid): """ Edits a tour event. Takes the usual tour event JSON. """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() event = safe_call(get_session().query(TourEvent), "get", eventid) event.set_props(data) commitSession(event) return jsonify(event.serialize())
def get_user(id): """ Gets a user by id. """ print("Get User") deep = request.args.get("deep", False) == "true" print("deep: " + str(deep)) #if not checkLogin(): # return notAuthorizedResponse() user = safe_call(get_session().query(User), "get", id) return jsonify(user.serialize(deep))
def create(data, id_tour=None): result = None if "id_tour_guide" in data: result = get_session().query(TourGuidesClass).get( data["id_tour_guide"]) if result is None: result = TourGuidesClass() result.set_props(data) if id_tour is not None: result.id_tour = id_tour commitSession(result) return result
def get_prs(id_user): """ Get a list of pending reviews for the user. """ if not checkLogin(): return notAuthorizedResponse() query = get_session().query(TourEvent).filter( and_(TourEvent.id_user == id_user, TourEvent.pending_review)) events = safe_call(query, "all", None) result = [] for event in events: result.append(event.serialize()) return jsonify(result)
def create_hours(tourid): ''' Sets the hours for a tourid, overriding any existing hours. See schema section for JSON format. <u>JSON Fields:</u> See Tour Hours Input Schema ''' if not checkLogin(): return notAuthorizedResponse() data = request.get_json() if request.method == 'POST': get_session().query(TourHours).filter( TourHours.tour_id == tourid).delete() get_session().query(TourHoursSpecial).filter( TourHoursSpecial.tour_id == tourid).delete() base_hours = data.get("base_hours", []) special_hours = data.get("special_hours", []) result = {"base_hours": [], "special_hours": []} for hour in base_hours: result["base_hours"].append(TourHours.create(hour, tourid).serialize()) for hour in special_hours: result["special_hours"].append( TourHoursSpecial.create(hour, tourid).serialize()) return jsonify(result)
def create(data, id_tour=None, id_user=None): result = None if "id_tourEvent" in data: result = get_session().query(TourEvent).get(data["id_tourEvent"]) if result is None: result = TourEvent() result.set_props(data) if id_tour is not None: result.id_tour = id_tour if id_user is not None: result.id_user = id_user commitSession(result) return result
def create(data, id_tour=None, id_user=None): result = None if "id_interestList" in data: result = get_session().query(Interests).get( data["id_interestList"]) if result is None: result = Interests() result.set_props(data) if id_tour is not None: result.id_tour = id_tour if id_user is not None: result.id_user = id_user commitSession(result) return result
def create(data, id_tour=None): result = None if "tour_hours_id" in data: result = get_session().query(TourHoursSpecial).get( data["tour_hours_special_id"]) if result is None: result = TourHoursSpecial() result.set_props(data.get("tour_id"), data.get("date"), data.get("open_time"), data.get("close_time"), data.get("overrides")) if id_tour is not None: result.tour_id = id_tour commitSession(result) return result
def favorite_details(user_id): ''' Returns an array of tour objects that the user has favorited. <u>URL Args:</u> user_id ''' if not checkLogin(): return notAuthorizedResponse() query = get_session().query(FavoritesClass).filter( FavoritesClass.user_id == user_id) favs = safe_call(query, "all", None) result = [] for fav in favs: result.append(fav.tour.serialize(deep=False)) return jsonify(result)
def add_rating(): """ Adds a new raing to the tour. <u>JSON fields:</u> id_user_rated=the raters id, id_tour_rated=the tour to rate, rating=rating from 1-5, comment=string comment """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() rating = Rating() id_user_rated = data["id_user_rated"] id_tour_rated = data["id_tour_rated"] rating_value = float(data["rating"]) comment = data["comment"] rating.set_props(rating_value, comment, id_tour_rated, id_user_rated) tour = get_session().query(Tour).get(int(id_tour_rated)) tour.average_rating = ( (tour.average_rating * tour.rating_count + rating_value) / (tour.rating_count + 1)) tour.rating_count += 1 get_session().add(tour) get_session().add(rating) commitSession() return "Success"
def create(data, id_tour=None): result = None if "tour_hours_id" in data: result = get_session().query(TourHours).get(data["tour_hours_id"]) if result is None: result = TourHours() result.set_props( data.get("tour_id"), data.get("day_of_week"), data.get("open_time"), data.get("close_time"), data.get("start_time"), data.get("end_time")) if id_tour is not None: result.tour_id = id_tour commitSession(result) return result
def edit_user_profile(userid): """ Uploads and sets a user's profile image <u>JSON fields:</u> file=base 64 string, name=the filename """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() file_data = data['file'] filename = data['name'] media = Media() result = media.upload(file_data, filename, userid=userid) user = safe_call(get_session().query(User), "get", userid) user.profile_picture = result["url"] # TODO set profile image size in db commitSession(user) return jsonify(result)
def edit_tour_profile(tourid): """ Uploads and sets a tour's profile image. <u>JSON fields:</u>file=base64 encoded file, name=filename """ if not checkLogin(): return notAuthorizedResponse() data = request.get_json() file_data = data['file'] filename = data['name'] media = Media() result = media.upload(file_data, filename, tourid=tourid) tour = safe_call(get_session().query(Tour), "get", tourid) tour.profile_image = result["url"] # TODO set profile image size in db commitSession(tour) return jsonify(result)
def get_tourevent(eventid): """ Gets a tour event by id. """ event = safe_call(get_session().query(TourEvent), "get", eventid) return jsonify(event.serialize(True))
def setProps(self, data): for key in data: setattr(self, key, data[key]) createSession() get_session().add(self) commitSession()
def get_tour(tourid): """ Gets a tour by id. """ tour = safe_call(get_session().query(Tour), "get", tourid) return jsonify(tour.serialize(True))
def site_map(): """ Returns this documentation. """ html = """ <style> .info { margin-left: 30px } </style> <h2>Endpoints</h2> """ for rule in app.url_map.iter_rules(): print(rule) options = {} for arg in rule.arguments: options[arg] = "[{0}]".format(arg) desc = "None<br>" if rule.endpoint in globals(): desc = globals()[rule.endpoint].__doc__ if desc is not None: if desc[0] is "\n": desc = desc[1:] if desc[-1] is "\n": desc = desc[:-1] desc = desc.replace("\n", "<br>") methods = ', '.join( [i for i in rule.methods if i not in ["HEAD", "OPTIONS"]]) url = url_for(rule.endpoint, **options) line = urllib.parse.unquote(""" <b>{}</b> <div class="info" <br> <u>URL:</u> {} <br> <u>Description:</u> {} <u>Methods:</u> {} </div> <br><br> """.format(rule.endpoint, url, desc, methods)) html += line user = safe_call(get_session().query(User), "first", None).serialize(True) clean_object(user) tour = safe_call(get_session().query(Tour), "first", None).serialize(True) clean_object(tour) tour_event = safe_call(get_session().query(TourEvent), "first", None).serialize(include_tour=False) clean_object(tour_event) hours = safe_call(get_session().query(TourHours), "first", None).serialize() hours_special = safe_call(get_session().query(TourHoursSpecial), "first", None).serialize() hours_input = {"base_hours": [hours], "hours_special": [hours_special]} clean_object(hours_special) clean_object(hours) clean_object(hours_input) html += """ <br> <h2>Schema</h2> <b>User:</b><br> """ + clean_json(user) + """ <br><br> <b>Tour:</b><br> """ + clean_json(tour) + """ <br><br> <b>Tour Event:</b><br> """ + clean_json(tour_event) + """ <br><br> <b>Tour Base Hours:</b><br> """ + clean_json(hours) + """ <br><br> <b>Tour Special Hours:</b><br> """ + clean_json(hours_special) + """ <br><br> <b>Tour Hours Input Format:</b><br> """ + clean_json(hours_input) return html
def get_hours(): """ Gets a list of available times for a tour based on base hours, special hours, and booked tours. The end_date parameter will default to one week after start_date if not specified. <u>URL Args:</u> tour_id, start_date=ISO standard date string, end_date """ tour_id = request.args.get("tour_id", None) start_date = parse(request.args.get("start_date", time.time())).date() end_date = start_date + datetime.timedelta(days=7) end_date = parse(request.args.get("end_date", str(end_date))).date() if tour_id is None: return 422, "No tour specified" tour = safe_call(get_session().query(Tour), "get", tour_id) length = tour.length if length is None or length is 0: length = 1 query = get_session().query(TourHours).filter(TourHours.tour_id == tour_id) baseHours = safe_call(query, "all", None) query = get_session().query(TourHoursSpecial).filter( TourHoursSpecial.tour_id == tour_id # TODO filter by date ) specialHours = safe_call(query, "all", None) print(start_date) print(end_date) #print("start: {}, end: {}" % (str(start_date), str(end_date))) query = get_session().query(TourEvent).filter(TourEvent.id_tour == tour_id) ''' query = query.filter( TourEvent.start_date_time >= start_date ) query = query.filter( TourEvent.end_date_time <= end_date ) ''' query = query.filter(TourEvent.state == 'B') events = safe_call(query, "all", None) hours = defaultdict(list) overridden = set() for sHour in specialHours: if sHour.date < start_date or sHour.date > end_date: continue ds = str(sHour.date) print("ds special: " + ds) if sHour.overrides: overridden.add(ds) add_hour_entries(hours[ds], sHour.open_time, sHour.close_time, length) for hour in baseHours: start = hour.open_time end = hour.close_time sh = start.hour eh = end.hour dow = hour.day_of_week offset = dow - start_date.weekday() curr_date = datetime.date(start_date.year, start_date.month, start_date.day + offset) while curr_date <= end_date: curr_date += datetime.timedelta(days=7) ds = str(curr_date) print("ds base: " + ds) if ds in overridden: continue add_hour_entries(hours[ds], start, end, length) for event in events: start = event.start_date_time ds = str(start.date()) print("ds event: " + ds) sh = start.hour eh = event.end_date_time.hour if ds not in hours: continue i = 0 while i < len(hours[ds]): # Check for overlapping hours if (sh <= hours[ds][i]["end"]) and (eh >= hours[ds][i]["start"]): del hours[ds][i] else: i += 1 for ds in hours: for i in range(len(hours[ds])): hours[ds][i]["start"] = hour_to_ts(hours[ds][i]["start"]) hours[ds][i]["end"] = hour_to_ts(hours[ds][i]["end"]) return jsonify(hours)