-
Notifications
You must be signed in to change notification settings - Fork 45
Add suggested channels greeting message #106
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
external_button_attachments, | ||
second_team_join_message, | ||
team_join_initial_message, | ||
profile_suggestion_message, | ||
) | ||
|
||
logger = logging.getLogger(__name__) | ||
|
@@ -32,7 +33,9 @@ def base_user_message(user_id: str) -> Message: | |
|
||
def build_messages(user_id) -> Tuple[Message, Message, Message, Message]: | ||
initial_message = base_user_message(user_id) | ||
initial_message["text"] = team_join_initial_message(user_id) | ||
initial_message["text"] = team_join_initial_message( | ||
user_id | ||
) # <--- Initial message is built | ||
|
||
second_message = base_user_message(user_id) | ||
second_message["text"] = second_team_join_message() | ||
|
@@ -103,3 +106,69 @@ async def get_backend_auth_headers(session: ClientSession) -> Dict[str, str]: | |
data = await response.json() | ||
headers = {"Authorization": f"Bearer {data['token']}"} | ||
return headers | ||
|
||
|
||
async def get_profile_suggestions( | ||
slack_id: int, | ||
auth_header: Dict[str, str], | ||
slack_api: SlackAPI, | ||
session: ClientSession, | ||
) -> List[Tuple[str, str]]: | ||
""" | ||
Generates a list of slack channels to suggest | ||
|
||
:param slack_id: The slack_id to return profile information from | ||
:return: A list of slack channel names to suggest for the user | ||
""" | ||
results = [] | ||
|
||
# Get profile data that we want to build suggestions from. | ||
user_info = await slack_api.query(methods.USERS_INFO, {"user": slack_id}) | ||
email = user_info["user"]["profile"]["email"] | ||
|
||
async with session.get( | ||
f"{BACKEND_URL}/auth/profile/admin/", | ||
headers=auth_header, | ||
params={"email": email}, | ||
) as response: | ||
data = await response.json() | ||
logger.info(f"Retrieved profile data from email: {email}") | ||
|
||
# Get the names of all public, non-archived channels | ||
channels = await slack_api.query( | ||
methods.CONVERSATION_LIST, {"exclude_archived": True} | ||
) | ||
|
||
# Get a list of all the profile data we want to compare | ||
possible_suggestions = parse_suggestions_from_profile(data) | ||
|
||
# For each value in the profile data, check that we have a channel name that matches. | ||
for info in possible_suggestions: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not to worried about a double for loop but you could avoid the lookup if you converted the list of channels into a set, or a key value pair. But I think the naming should be clearer: for suggestion in possible_suggestions:
for channel in channels:
if suggestion in channel[1]:
results.append((channel[0], channel[1]))
break |
||
for channel in channels: | ||
if info in channel[1]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how you got that the channel can be indexed... "channels": [
{
"id": "C0G9QF9GW",
"name": "random",
"is_channel": true,
"created": 1449709280,
"creator": "U0G9QF9C6",
"is_archived": false,
"is_general": false,
"name_normalized": "random",
"is_shared": false,
"is_org_shared": false,
"is_member": true,
"is_private": false,
........
}, I think you need to compare the channel['name'] to the suggestion. But you should also exclude the channel when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh thanks for catching that. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on the above, ignore the |
||
results.append((channel[0], channel[1])) | ||
break | ||
|
||
return results | ||
|
||
|
||
def parse_suggestions_from_profile(profile: Dict) -> List[str]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not very clear at first what this is doing.
For some profile fields they are lists, and some profile fields they are single items. This is because we are storing lists of items as strings joined by commas. Stylistically I think something like this is a bit clearer. def filter_non_empty_profile_fields(profile: Dict) -> List[str]:
# These fields are a 1:N for possible channel matching split on commas
csv_profile_fields = ["interests", "programming_languages", "disciplines"]
# These fields can only be a single channel for the item
flat_profile_fields = ["city", "state" ]
filtered_profile_field_values = []
for field in csv_profile_fields:
if profile.get(field) is not None:
for word in filter(None, profile[field].lower().split(",")):
filtered_profile_field_values.append(word)
for field in flat_profile_fields:
word = profile.get(field)
if word is not None:
filtered_profile_field_values.append(word)
return filtered_profile_field_values I don't remember if the api has a way to filter some of the profile values, or request the api to split the values when they have multiple items into a list. It would be better if we stored them in the database as a 1:N relationship and then had the api return a list in the json. |
||
# To use more profile fields add them here. | ||
suggestible_fields = ["city", "state", "interests", "programming_languages", "disciplines"] | ||
data = [] | ||
|
||
for field in suggestible_fields: | ||
if field in profile.keys() and profile[field] is not None: | ||
if field in ["interests", "programming_languages", "disciplines"]: | ||
for word in profile[field].lower().split(","): | ||
data.append(word) | ||
else: | ||
data.append(profile[field]) | ||
return data | ||
|
||
|
||
def build_suggestion_messages(user_id: str, channels: List[Tuple[str, str]]) -> Message: | ||
suggestion_message = base_user_message(user_id) | ||
message = profile_suggestion_message(channels) | ||
suggestion_message["text"] = message | ||
return suggestion_message |
Uh oh!
There was an error while loading. Please reload this page.