def admin_delete_user(username): """ ADMIN: Delete users if necessary. The ADMIN account has option to delete users from database if it needs to. This would delete all of that user's recipes, too. """ user = get_user_lower(username) # find all recipes belonging to user being deleted user_recipes = [recipe for recipe in user.get("user_recipes")] # for each user recipe, remove it from database and pull from others' favs for recipe in user_recipes: recipes_collection.remove({"_id": recipe}) users_collection.update_many({}, {"$pull": {"user_favs": recipe}}) # find all recipes that the user saved user_favs = [recipe for recipe in user.get("user_favs")] # decrement each recipe the user liked by -1 for recipe in user_favs: recipes_collection.update_one({"_id": recipe}, {"$inc": { "user_favs": -1 }}) flash( Markup(f"<i class='fas fa-user-times red-text'></i>\ User has been successfully deleted.")) # delete the user from database using .remove() users_collection.remove({"_id": user.get("_id")}) return redirect(url_for("users.profile", username="******"))
def desserts_delete_favorite(recipe_id, slugUrl): """ Remove recipe from user favorites, decrease number of favorites and number of views by -1. Flash message advising user. """ users_collection.find_one_and_update( {"username_lower": session["user"].lower()}, {"$pull": {"user_favs": ObjectId(recipe_id)}}) recipes_collection.update_one( {"_id": ObjectId(recipe_id)}, {"$inc": {"user_favs": -1, "views": -1}}) flash(Markup( f"<i class='fas fa-minus-circle red-text'></i>\ Removed from your favorites.")) return redirect(request.referrer)
def desserts_add_favorite(recipe_id, slugUrl): """ Add recipe to user favorites, increase number of favorites by +1, and decrease number of views by -1. Flash message advising user. """ users_collection.find_one_and_update( {"username_lower": session["user"].lower()}, {"$push": {"user_favs": ObjectId(recipe_id)}}) recipes_collection.update_one( {"_id": ObjectId(recipe_id)}, {"$inc": {"user_favs": 1, "views": -1}}) flash(Markup( f"<i class='fas fa-heart pink-text'></i>\ Saved to your favorites!")) return redirect(request.referrer)
def profile_delete_account(username): """ Delete entire user account if desired. Each user has the option to delete their account. This would delete all of their recipes, too. """ user = get_user_lower(session["user"]) # check if stored hashed password matches current password in form if check_password_hash(user["user_password"], request.form.get("verify_password")): # find all recipes belonging to user user_recipes = [recipe for recipe in user.get("user_recipes")] # for each user recipe, remove from database and pull from others' favs for recipe in user_recipes: recipes_collection.remove({"_id": recipe}) users_collection.update_many({}, {"$pull": {"user_favs": recipe}}) # find all recipes that the user saved user_favs = [recipe for recipe in user.get("user_favs")] # decrement each recipe the user liked by -1 for recipe in user_favs: recipes_collection.update_one({"_id": recipe}, {"$inc": { "user_favs": -1 }}) flash( Markup(f"<i class='fas fa-user-times red-text'></i>\ Your account and recipes have been successfully deleted.")) # remove user from session cookies and delete user from database session.pop("user") users_collection.remove({"_id": user.get("_id")}) return redirect(url_for("main.home")) else: # password does not match, so redirect back to profile flash( Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\ Whoops! Looks like your <span class='pink-text text-lighten-2'>\ password</span> is incorrect. Please try again.")) return redirect(url_for("users.profile", username=username))
def desserts_new(): """ Create recipe for database. Inject all form data to new recipe document on submit. """ if request.method == "GET": allergen_list = dropdown_allergens() dessert_list = dropdown_dessert_type() measurement_list = dropdown_measurement() return render_template( "desserts_new.html", allergens=allergen_list, desserts=dessert_list, measurements=measurement_list) if request.method == "POST": # get today's date and date recipe was last edited today = datetime.now().strftime("%d %B, %Y") last_edit = int(datetime.now().strftime("%Y%m%d")) # get user / author details session_user = get_user_lower(session["user"])["username"] author = users_collection.find_one({"username": session_user})["_id"] # get and convert total time hours = int(request.form.get( "total_hrs")) * 60 if request.form.get( "total_hrs") else "" total_time = int(request.form.get( "total_mins")) + hours if hours else int(request.form.get( "total_mins")) # slugify url to be user-friendly slugUrl = slugify(request.form.get("recipe_name")) # get form data prior to submitting submit = { "recipe_name": request.form.get("recipe_name"), "recipe_slug": slugUrl, "description": request.form.get("description"), "dessert_type": request.form.get("dessert_type"), "ingredient_amount": request.form.getlist("ingredient_amount"), "ingredient_measurement": request.form.getlist( "ingredient_measurement"), "ingredient_name": request.form.getlist("ingredient_name"), "directions": request.form.getlist("directions"), "total_hrs": request.form.get("total_hrs"), "total_mins": request.form.get("total_mins"), "total_time": total_time, "allergens": request.form.getlist("allergens"), "img_src": request.form.get("img_src"), "author": author, "date_added": today, "date_updated": today, "last_edit": last_edit, "views": 0, "user_favs": 0 } # get the new _id being created on submit newID = recipes_collection.insert_one(submit) # add recipe _id to user's recipe list users_collection.update_one( {"_id": ObjectId(author)}, {"$push": {"user_recipes": newID.inserted_id}}) flash(Markup( f"<i class='far fa-check-circle green-text'></i>\ Sounds delicious! Thanks for adding this recipe!")) # if selected, add recipe to user-favs as well if request.form.get("add_favs"): users_collection.update_one( {"_id": ObjectId(author)}, {"$push": {"user_favs": newID.inserted_id}}) # increase number of favorites on this recipe by +1 recipes_collection.update_one( {"_id": newID.inserted_id}, {"$inc": {"user_favs": 1}}) # # send me an email when a recipe gets added (personal backup) # msg = MIMEMultipart() # msg["From"] = MY_ADDRESS # msg["To"] = SEND_TO # msg["Subject"] = "2BN-Desserts | New Recipe Added: " + slugUrl # formatEmail = "<br><br>".join(["%s: %s" % kv for kv in submit.items()]) # msg.attach(MIMEText(str(formatEmail), "html")) # must convert to str() # smtpserver = smtplib.SMTP("smtp.gmail.com", 587) # access server # smtpserver.ehlo() # identify ourselves to smtp gmail client # smtpserver.starttls() # secure our email with tls encryption # smtpserver.ehlo() # re-identify ourselves as an encrypted connection # smtpserver.login(MY_ADDRESS, PASSWORD) # login to the server # smtpserver.send_message(msg) # send the message # smtpserver.quit() # quit the server # add recipe to admin's profile as back-up (in lieu of email) users_collection.update_one( {"username": "******"}, {"$push": {"new_recipes": submit}}) return redirect(url_for( "recipes.desserts_recipe", recipe_id=newID.inserted_id, slugUrl=slugUrl))
def desserts_recipe(recipe_id, slugUrl): """ Read recipe in database. Gather details from document for displaying to user. """ recipe = get_recipe(recipe_id) author = users_collection.find_one( {"_id": ObjectId(recipe.get("author"))})["username"] user_avatar = users_collection.find_one( {"_id": ObjectId(recipe.get("author"))})["user_avatar"] amounts = recipe.get("ingredient_amount") measurements = recipe.get("ingredient_measurement") ingredients = recipe.get("ingredient_name") amount = [] measurement = [] units = [] """ if amount contains valid unicode fraction, convert it (ie: input 1/2 converts to ½ for display) """ fractions = ( ["1/2", "1/3", "1/4", "1/5", "1/6", "1/8", "2/3", "2/5", "3/4", "3/5", "3/8", "4/5", "5/6", "5/8", "7/8"]) for num in amounts: if "/" in num: if any(frac in num for frac in fractions): frac_match = re.match(r"^(.*?)(\d\/\d)(.*?)$", num) new_num = ( frac_match.group(1) + "&frac" + re.sub("/", "", frac_match.group(2)) + ";" + frac_match.group(3)) amount.append(html.unescape(new_num)) else: amount.append(num) else: amount.append(num) # only display the abbreviated unit of measurement for unit in measurements: units.append(unit) match = re.search(r"\(([a-zA-Z]+)\)$", unit) if match: measurement.append(match.group(1)) else: measurement.append(unit) # zip ingredient items into single full_ingredient full_ingredient = zip(amount, measurement, ingredients) # get user favorites (if available) try: user_favs = get_user_lower(session["user"])["user_favs"] except: user_favs = [] # increment number of views by +1 recipes_collection.update_one( {"_id": ObjectId(recipe_id)}, {"$inc": {"views": 1}}) """ Display Recommendations: Get the Previous and Next recipes in collection to display. If currently on last document, then get the first document for display. If currently on first document, then get the last document for display. """ first_recipe = recipes_collection.find().sort("_id", 1).limit(1) last_recipe = recipes_collection.find().sort("_id", -1).limit(1) previous_recipe = recipes_collection.find( {"_id": {"$lt": ObjectId(recipe_id)}})\ .sort([("_id", -1)])\ .limit(1) if str(recipe_id) != str(first_recipe[0]["_id"])\ else last_recipe next_recipe = recipes_collection.find( {"_id": {"$gt": ObjectId(recipe_id)}})\ .sort([("_id", 1)])\ .limit(1) if str(recipe_id) != str(last_recipe[0]["_id"])\ else first_recipe return render_template( "desserts_recipe.html", recipe=recipe, full_ingredient=full_ingredient, units=units, author=author, user_favs=user_favs, user_avatar=user_avatar, previous_recipe=previous_recipe, next_recipe=next_recipe)
def desserts_new(): """ Create recipe for database. Inject all form data to new recipe document on submit. """ if request.method == "GET": allergen_list = dropdown_allergens() dessert_list = dropdown_dessert_type() measurement_list = dropdown_measurement() return render_template("desserts_new.html", allergens=allergen_list, desserts=dessert_list, measurements=measurement_list) if request.method == "POST": # get today's date and date recipe was last edited today = datetime.now().strftime("%d %B, %Y") last_edit = int(datetime.now().strftime("%Y%m%d")) # get user / author details session_user = get_user_lower(session["user"])["username"] author = users_collection.find_one({"username": session_user})["_id"] # get and convert total time hours = int(request.form.get("total_hrs")) * 60 if request.form.get( "total_hrs") else "" total_time = int( request.form.get("total_mins")) + hours if hours else int( request.form.get("total_mins")) # slugify url to be user-friendly slugUrl = slugify(request.form.get("recipe_name")) # get form data prior to submitting submit = { "recipe_name": request.form.get("recipe_name"), "recipe_slug": slugUrl, "description": request.form.get("description"), "dessert_type": request.form.get("dessert_type"), "ingredient_amount": request.form.getlist("ingredient_amount"), "ingredient_measurement": request.form.getlist("ingredient_measurement"), "ingredient_name": request.form.getlist("ingredient_name"), "directions": request.form.getlist("directions"), "total_hrs": request.form.get("total_hrs"), "total_mins": request.form.get("total_mins"), "total_time": total_time, "allergens": request.form.getlist("allergens"), "img_src": request.form.get("img_src"), "author": author, "date_added": today, "date_updated": today, "last_edit": last_edit, "views": 0, "user_favs": 0 } # get the new _id being created on submit newID = recipes_collection.insert_one(submit) # add recipe _id to user's recipe list users_collection.update_one( {"_id": ObjectId(author)}, {"$push": { "user_recipes": newID.inserted_id }}) flash( Markup(f"<i class='far fa-check-circle green-text'></i>\ Sounds delicious! Thanks for adding this recipe!")) # if selected, add recipe to user-favs as well if request.form.get("add_favs"): users_collection.update_one( {"_id": ObjectId(author)}, {"$push": { "user_favs": newID.inserted_id }}) # increase number of favorites on this recipe by +1 recipes_collection.update_one({"_id": newID.inserted_id}, {"$inc": { "user_favs": 1 }}) return redirect( url_for("recipes.desserts_recipe", recipe_id=newID.inserted_id, slugUrl=slugUrl))