Skip to content

Commit

Permalink
Merge pull request #969 from JGreenlee/configurable_push_notifs
Browse files Browse the repository at this point in the history
make push notifs configurable, i18n, & only for users missing labels
  • Loading branch information
shankari authored May 26, 2024
2 parents 36432a8 + 7034479 commit 3150c99
Showing 1 changed file with 90 additions and 19 deletions.
109 changes: 90 additions & 19 deletions bin/push/push_remind.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,59 @@
import arrow
import json
import logging
import os
import requests
import sys

import emission.core.get_database as edb
import emission.storage.decorations.analysis_timeseries_queries as esda
import emission.storage.decorations.user_queries as esdu
import emission.storage.timeseries.timequery as estt
import emission.net.ext_service.push.notify_usage as pnu

STUDY_CONFIG = os.getenv('STUDY_CONFIG', "stage-program")


def users_without_recent_user_input(uuid_list, recent_user_input_threshold=None):
if recent_user_input_threshold is None:
logging.debug("No recent_user_input_threshold provided, returning all users")
return uuid_list
now = arrow.now()
tq = estt.TimeQuery(
"data.start_ts",
now.shift(days=-recent_user_input_threshold).int_timestamp,
now.int_timestamp
)
filtered_uuids = []
for user_id in uuid_list:
trips = esda.get_entries(esda.CONFIRMED_TRIP_KEY, user_id, tq)
for trip in trips:
# If the trip's user_input is blank, it will be an empty dict {} which is falsy.
# A slight caveat to this is that if the trip is partially labeled (i.e. they
# labeled 'Mode' but not 'Purpose'), it will be non-empty and will be considered
# the same as if it was fully labeled.
# I think this is fine because if a user has partially labeled a trip, they have
# already seen it and bugging them again is not likely to help.
if not trip['data']['user_input']: # empty user_input is {} which is falsy
logging.debug(f"User {user_id} has trip with no user input: {trip['_id']}")
filtered_uuids.append(user_id)
break
return filtered_uuids


def bin_users_by_lang(uuid_list, langs, lang_key='phone_lang'):
uuids_by_lang = {lang: [] for lang in langs}
for user_id in uuid_list:
user_profile = edb.get_profile_db().find_one({'user_id': user_id})
user_lang = user_profile.get(lang_key) if user_profile else None
logging.debug(f"User {user_id} has phone language {user_lang}")
if user_lang not in uuids_by_lang:
logging.debug(f"{user_lang} was not one of the provided langs, defaulting to en")
user_lang = "en"
uuids_by_lang[user_lang].append(user_id)
return uuids_by_lang


if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
logging.debug(f"STUDY_CONFIG is {STUDY_CONFIG}")
Expand All @@ -20,23 +66,48 @@
if r.status_code != 200:
logging.debug(f"Unable to download study config, status code: {r.status_code}")
sys.exit(1)
else:
dynamic_config = json.loads(r.text)
logging.debug(f"Successfully downloaded config with version {dynamic_config['version']} "\
f"for {dynamic_config['intro']['translated_text']['en']['deployment_name']} "\
f"and data collection URL {dynamic_config['server']['connectUrl']}")

if "reminderSchemes" in dynamic_config:
logging.debug("Found flexible notification configuration, skipping server-side push")
else:
uuid_list = esdu.get_all_uuids()
json_data = {
"title": "Trip labels requested",
"message": "Please label your trips for the day"
}
response = pnu.send_visible_notification_to_users(uuid_list,
json_data["title"],
json_data["message"],
json_data,
dev = False)

dynamic_config = json.loads(r.text)
logging.debug(f"Successfully downloaded config with version {dynamic_config['version']} "\
f"for {dynamic_config['intro']['translated_text']['en']['deployment_name']} "\
f"and data collection URL {dynamic_config['server']['connectUrl']}")

if "reminderSchemes" in dynamic_config:
logging.debug("Found flexible notification configuration, skipping server-side push")
sys.exit(0)

# get push notification config (if not present in dynamic_config, use default)
push_config = dynamic_config.get('push_notifications', {
"title": {
"en": "Trip labels requested",
"es": "Etiquetas de viaje solicitadas",
},
"message": {
"en": "Please label your recent trips",
"es": "Por favor etiquete sus viajes recientes",
},
"recent_user_input_threshold": 7, # past week
})

# filter users based on recent user input and bin by language
filtered_uuids = users_without_recent_user_input(
esdu.get_all_uuids(),
push_config.get('recent_user_input_threshold')
)
filtered_uuids_by_lang = bin_users_by_lang(filtered_uuids, push_config['title'].keys())

# for each language, send a push notification to the selected users in that language
for lang, uuids_to_notify in filtered_uuids_by_lang.items():
if len(uuids_to_notify) == 0:
logging.debug(f"No users to notify in lang {lang}")
continue
logging.debug(f"Sending push notifications to {len(uuids_to_notify)} users in lang {lang}")
json_data = {
"title": push_config["title"][lang],
"message": push_config["message"][lang],
}
response = pnu.send_visible_notification_to_users(uuids_to_notify,
json_data["title"],
json_data["message"],
json_data,
dev = False)

0 comments on commit 3150c99

Please sign in to comment.