Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add rate limiting for mentor requests #242

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions pybot/endpoints/slack/actions/mentor_request.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
from datetime import date, timedelta

from sirbot import SirBot
from slack import methods
Expand Down Expand Up @@ -27,13 +28,41 @@ async def mentor_request_submit(action: Action, app: SirBot):
username = action["user"]["name"]
user_info = await slack.query(methods.USERS_INFO, {"user": action["user"]["id"]})
email = user_info["user"]["profile"]["email"]
remaining_requests = 2
request_cycle_start_date = date.today().isoformat()

recent_requests = await airtable.find_recent_requests("Mentor Request", "Email", email)
if len(recent_requests) != 0:
"""
filter the recent requests by the value of most recent request cycle start date
if the user has already made 3 requests in the last 31 days, show them an error message
Otherwise, proceed to submit request
"""
request_cycle_start_date = recent_requests[0]["fields"]["start date"]
filtered_requests = [
request
for request in recent_requests
if request["fields"]["start date"] == request_cycle_start_date
]
remaining_requests -= len(filtered_requests)
if len(filtered_requests) == 3:
new_request_cycle_start_date = date.fromisoformat(request_cycle_start_date) + timedelta(days=31)
await request.submit_request_rate_limit_exceeded_error(
new_request_cycle_start_date.isoformat(), slack
)
return

airtable_response = await request.submit_request(username, email, airtable)
airtable_response = await request.submit_request(
username, email, request_cycle_start_date, airtable
)

if "error" in airtable_response:
await request.submission_error(airtable_response, slack)
else:
await request.submission_complete(slack)
request_cycle_end_date = date.fromisoformat(request_cycle_start_date) + timedelta(days=30)
await request.submission_complete(
remaining_requests, request_cycle_end_date.isoformat(), slack
)


async def mentor_details_submit(action: Action, app: SirBot):
Expand Down
28 changes: 25 additions & 3 deletions pybot/endpoints/slack/message_templates/mentor_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,15 @@ def add_errors(self) -> None:
}
self.attachments = [submit_attachment]

async def submit_request(self, username: str, email: str, airtable: AirtableAPI):
async def submit_request(
self, username: str, email: str, start_date: str, airtable: AirtableAPI
):
params = {"Slack User": username, "Email": email, "Status": "Available"}
if self.skillsets:
params["Skillsets"] = self.skillsets
if self.details:
params["Additional Details"] = self.details
params["start date"] = start_date

service_records = await airtable.find_records("Services", "Name", self.service)
params["Service"] = [service_records[0]["id"]]
Expand All @@ -118,11 +121,30 @@ def submission_error(
self.attachments = [error_attachment]
return self.update_message(slack)

def submission_complete(self, slack: SlackAPI) -> Coroutine[Any, Any, dict]:
def submit_request_rate_limit_exceeded_error(
self, new_start_date: str, slack: SlackAPI
) -> Coroutine[Any, Any, dict]:
error_attachment = {
"text": (
f"You have exceeded mentor request limit.\n"
f"New request can be made starting on {new_start_date}"
),
"color": "danger",
}
self.attachments = [error_attachment]
return self.update_message(slack)

def submission_complete(
self, remaining_requests: int, current_end_date: str, slack: SlackAPI
) -> Coroutine[Any, Any, dict]:
done_block = {
"type": "section",
"block_id": "submission",
"text": {"type": "mrkdwn", "text": "Request Submitted Successfully!"},
"text": {
"type": "mrkdwn",
"text": f"Request Submitted Successfully!\n"
f"You have now {remaining_requests} mentor requests remaining until {current_end_date}.",
},
"accessory": {
"type": "button",
"action_id": "cancel_btn",
Expand Down
21 changes: 21 additions & 0 deletions pybot/plugins/airtable/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,27 @@ async def find_records(self, table_name: str, field: str, value: str) -> list:
)
return []

async def find_recent_requests(
self, table_name: str, field: str, value: str
) -> list:
url = self.table_url(table_name)

params = {
"filterByFormula": f"AND(FIND(LOWER('{value}'), LOWER({{{field}}})), "
"{start date} != '', DATETIME_DIFF(NOW(), {start date}, 'days') <= 31)",
"maxRecords": 3,
"view": "Test Filter View",
}

try:
response = await self.get(url, params=params)
return response["records"]
except Exception as ex:
logger.exception(
f"Exception when attempting to get {field} from {table_name}.", ex
)
return []

async def update_request(self, request_record, mentor_id):
url = self.table_url("Mentor Request", request_record)
data = {"fields": {"Mentor Assigned": [mentor_id] if mentor_id else None}}
Expand Down