def get(args: dict): """Browse available Prompts by year or month-year combo.""" # We always need a year if "year" not in args: return make_error_response( 422, "At the least, a prompt year must be provided!") # We also have a month, meaning we're browsing an individual month if "month" in args: # Handle the month coming in as single number if len(args["month"]) == 1: args["month"] = f"0{args['month']}" month_data = browse_by_month(args["year"], args["month"]) # Error out if there's no data if month_data["total"] != 0: return month_data return make_error_response( 404, f"No prompts available for year-month {args['year']}-{args['month']}!", # noqa ) # We only have a year, so we're browsing by year year_results = browse_by_year(args["year"]) # Error out if there's no data if year_results["total"] != 0: return year_results return make_error_response( 404, f"No prompts available for year {args['year']}!")
def post(args: dict): """Create a new Prompt.""" # Format the date in the proper format before writing args["date"] = helpers.format_datetime_ymd(args["date"]) # If we've not recieved an explict flag that this a duplicate data # (which can occur because there happened to more >1 prompt for the day), # we need to enforce a one-prompt-a-day constraint if not args["is_duplicate_date"]: # Don't create a prompt if it already exists if database.prompt.exists(pid="", date=args["date"]): return helpers.make_error_response( 422, f"A prompt for {args['date']} already exists!") # Download the given media media_result = True if args["media"] is not None and __is_valid_url(args["media"]): media_url = args["media"] media_result = media.move(media.download(args["id"], media_url)) # Extract the media URL args["media"] = media.saved_name(args["id"], media_url) # Write the prompt to the database db_result = database.prompt.create(args) # Return the proper status depending on adding result if db_result and media_result: return helpers.make_response(201) return helpers.make_error_response(422, "Unable to record new Prompt!")
def get(args: dict): """Get a Host by their Twitter ID or handle.""" # Return a list of all Hosts if "all" in args and args["all"]: return helpers.make_response(200, jsonify(database.host.get_all())) # We need something to search by if not args["uid"] and not args["handle"]: return helpers.make_error_response( 422, "Either a Host id or handle must be provided!") # Both a host ID and handle cannot be provided if args["uid"] and args["handle"]: return helpers.make_error_response( 422, "Providing a Host id and handle is not allowed!") # Get the host information found_host = database.host.get(uid=args["uid"], handle=args["handle"]) if found_host: return helpers.make_response(200, jsonify(found_host)) # Determine which param was given given_param = [(k, v) for k, v in args.items() if v][0] # We don't have that host return helpers.make_error_response( 404, f"Unable to get details for Host {given_param[0]} {given_param[1]}!")
def date_get(args: dict): """Get hosting period info for a Host, by either date or Host handle.""" # Both parameters were provided. That's a nada if len(args) > 1: return helpers.make_error_response( 422, "Only one parameter can be provided!") # We want to get the starting hosting date for this Host if "handle" in args: # That Host doesn't exist if not database.host.exists(handle=args["handle"]): return helpers.make_error_response( 404, f"Unable to get hosting period for {args['handle']}!", ) # Attempt to find the hosting period (or not) hosting_periods = database.host.get_date(args["handle"]) if hosting_periods: return helpers.make_response(200, jsonify(hosting_periods)) return helpers.make_error_response( 404, f"Unable to get hosting period for {args['handle']}!", ) # Ww want to get the Host for this specific date if "date" in args: current_host = database.host.get_by_date( helpers.format_datetime_ymd(args["date"])) if current_host: return helpers.make_response(200, jsonify(current_host)) return helpers.make_error_response( 404, f"Unable to get Host for {helpers.format_datetime_ymd(args['date'])}!", )
def get(args: dict): """Search for a Prompt by word or Host.""" # Both parameters were provided, and that is not supported if len(args) > 1: return make_error_response(422, "Only one parameter can be provided!") if "prompt" in args: return make_response(200, search_by_prompt(args["prompt"])) if "host" in args: return make_response(200, search_by_host(args["host"])) return make_error_response( 422, "At least one search parameter must be provided!")
def put(args: dict): """PUT request to update an existing API key.""" # That key doesn't exist if not database.api_key.exists(args["token"]): return helpers.make_error_response( 404, "The requested API key does not exist!", ) # Update and respond accordingly result = database.api_key.update(args) if result: return helpers.make_response(200) return helpers.make_error_response(422, "Unable to update the API key!")
def date_post(args: dict): """Create a new hosting date for the given Host.""" # That hosting date already exists and we can't duplicate it if database.host.exists_date(args["uid"], args["date"]): return helpers.make_error_response( 422, f'A hosting date of {args["date"]} for Host {args["uid"]} already exists!', ) result = database.host.create_date(args) if result: return helpers.make_response(201) return helpers.make_error_response( 503, f'Unable to create new hosting date for {args["date"]}!')
def put(query_args: dict, json_args: dict): """Update an existing Prompt.""" # Merge the two args dicts into a single dict for easier use args = {**query_args, **json_args} # The prompt needs to exist first if not database.prompt.exists(pid=args["id"], date=""): msg = "The prompt ID '{}' does not exist!".format(args["id"]) return helpers.make_error_response(404, msg) # If media is set to nothing, we want to delete it if args["media"] is None: media.delete(args["id"]) # We want to replace the existng media elif (args["media"] is not None and __is_valid_url(args["media"]) and args["media_replace"]): # Start by deleting the old media media.delete(args["id"]) # Download the new media media.move(media.download(args["id"], args["media"])) # Set the new media file name. It's not likely to be different # but better safe than sorry here args["media"] = media.saved_name(args["id"], args["media"]) # Format the date in the proper format args["date"] = helpers.format_datetime_ymd(args["date"]) # Finally, save all this to the database database.prompt.update(args) return helpers.make_response(204)
def get(args: dict): """Get a Prompt, either the latest or from a specific date.""" # Hitting the endpoint without a date returns the latest prompt(s) if "date" not in args: prompts = database.prompt.get_latest() # We want the prompt from a particular day else: # Handle the special one year anniversary image prompts if (args["date"].year == 2017 and args["date"].month == 9 and args["date"].day == 5): return database.prompt.get_one_year() # Format the date in the proper format before fetching date = helpers.format_datetime_ymd(args["date"]) # A prompt for that date doesn't exist prompts = database.prompt.get_by_date(date, date_range=False) if not prompts: return helpers.make_error_response( 404, f"No prompt exists for date {date}!") # Find out if we have a Prompt for the surrounding days for day_prompt in prompts: day_prompt["previous"] = prompt_exists(day_prompt.date, "previous") day_prompt["next"] = prompt_exists(day_prompt.date, "next") return jsonify(prompts)
def post(args: dict): """Add an email to the mailing list.""" # Define the error response error = helpers.make_error_response( 503, "Unable to add email to mailing list!") # If email sending is not enabled, always pretend it was added if not current_app.config["ENABLE_EMAIL_SENDING"]: return helpers.make_response(201) # Because this endpoint costs money with each hit, block it off # unless we are running in production if current_app.config["ENV"] == "production": # Validate the address to decide if we should record it if not mailgun.validate(args["email"]): return error # Add the address to the local database db_result = database.subscription.email_create(args["email"]) # It didn't added to the db if not db_result: return error # Add the address to the Mailgun mailing list mg_result = mailgun.create(args["email"]) # The address was successfully recorded if mg_result.status_code == codes.ok: return helpers.make_response(201) # ...Welllllll... actually it didn't... return error
def post(args: dict): """POST request to create a new API key.""" # Create the token result = database.api_key.create(args) # Respond according to if it was successful or not if result: return helpers.make_response(201, result) return helpers.make_error_response(422, "Unable to create a new API key!")
def post(args: dict): """Create a new Host.""" if database.host.exists(handle=args["handle"]): return helpers.make_error_response( 422, f'Host {args["handle"]} already exists!') # Get the Twitter user ID for this Host host_id = database.host.lookup(args["handle"]) if not host_id: return helpers.make_error_response( 503, f'Unable to find Twitter username {args["handle"]}!') # Create a host with all their details args["uid"] = host_id result = database.host.create(args) if result is None: return helpers.make_error_response( 503, f'Unable to create new Host {args["handle"]}!') return helpers.make_response(201, jsonify(result))
def patch(args: dict): """Update a Host's handle.""" # Attempt to find the host. They must exist to be updated existing_host = database.host.exists(uid=args["uid"]) if not existing_host: return helpers.make_error_response(400, "Unable to update Host details!") # Update the host database.host.update(args) return helpers.make_response(204)
def hosting_get(args: dict): # Except one and only one parameter is supported if len(args) > 1: return helpers.make_error_response( 422, "Only one parameter can be provided!") # We want the exact starting Hosting date for this day if "date" in args: return helpers.make_response( 200, jsonify([database.settings.hosting_start_date_get(args["date"])])) # We want the Hosting dates for this month if "month" in args: return helpers.make_response( 200, jsonify(database.settings.hosting_period_get(args["month"]))) # We didn't recieve any info so we don't know what to do ¯\_(ツ)_/¯ return helpers.make_error_response(422, "A single parameter must be provided!")
def delete(args: dict): """Delete a Host. This will only succeed if the Host does not have any associated Prompts to prevent orphaned records or an incomplete record. """ result = database.host.delete(args["uid"]) if result: return helpers.make_response(204) return helpers.make_error_response( 403, f"Unable to delete Host {args['uid']}! They have Prompts associated with them.", )
def get(args: dict): """GET request to fetch key permissions.""" # Cannot request info for a single key and all keys if "token" in args and "all" in args: return helpers.make_error_response( 422, "Cannot request individual and all key info together!") # We want all key info if "all" in args and args["all"]: records = database.api_key.get_all() return helpers.make_response(200, jsonify(records)) # We want info on a single key if "token" in args: record = database.api_key.get(args["token"]) if record is not None: return helpers.make_response(200, jsonify(record)) return helpers.make_error_response(404, "Could not get key information!") # Some form of info must be requested return helpers.make_error_response( 422, "Must request some form of key information!")
def post(args: dict): """Trigger an email broadcast for the given day's prompt.""" # Put the date in the proper format date = helpers.format_datetime_ymd(args["date"]) # A prompt for that date doesn't exist prompts = database.prompt.get_by_date(date, date_range=False) if not prompts: return helpers.make_error_response( 503, f"Unable to send out email broadcast for the {date} prompt!") # If email sending is not allowed, just pretend it worked if not current_app.config["ENABLE_EMAIL_SENDING"]: return helpers.make_response(200) # Pull out the exact prompt we want to broadcast. # If there's more than one prompt for this day, # it'll use whichever was requested. # By default, the latest recorded/only prompt is selected prompt = prompts[args["which"]] # Send an email to the MG mailing list # This helps us keep track of who is on the list at any given moment # but also resolves a crazy amount of trouble # when it comes to sending out a large amount of email messages # https://documentation.mailgun.com/en/latest/api-mailinglists.html#examples r = email.make_and_send( mailgun.mailing_list(), helpers.format_datetime_pretty(prompt.date), "email", **prompt, ) pprint(r) # There's no easy way to tell if they all sent, so just pretend they did return helpers.make_response(200)