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

Ability to silence DM messages from HeyFireball #14 #21

Merged
merged 11 commits into from
Nov 18, 2017
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,5 @@ ENV/
.vscode

# custom
*.ignoreme
*.ignoreme
.DS_Store
74 changes: 59 additions & 15 deletions hey_fireball.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
# instantiate Slack & Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))

commands = ['leaderboard', 'fullboard', POINTS, '{}left'.format(POINTS)]
commands = ['leaderboard', 'fullboard', POINTS, '{}left'.format(POINTS), 'setpm']
commands_with_target = [POINTS, 'all']

user_list = slack_client.api_call("users.list")['members']
Expand Down Expand Up @@ -80,6 +80,8 @@ def __init__(self, msg):
self.target_name = self.target_id
self.command = self._extract_command()
self.count = self._extract_count()
self.setting = self._extract_setting() # Find on/off or assume toggle
self.ts = msg['ts'] # Store the thread_ts

def __str__(self):
return str(vars(self))
Expand Down Expand Up @@ -149,6 +151,24 @@ def _extract_count(self):
return int(self.parts[idx])
except ValueError:
pass

def _extract_setting(self):
if self.bot_is_first:
idx = 2
curPref = get_pm_preference(self.requestor_id)
if len(self.parts) < 3:
#Act as a toggle
if curPref:
return 0
else:
return 1
if self.parts[idx].lower() == 'on' and not curPref:
return 1
elif self.parts[idx].lower() == 'off' and curPref:
return 0
else:
pass

'''
# Use the following to catch and handle missing methods/properties as we want
def __getattr__(self, name):
Expand Down Expand Up @@ -205,6 +225,14 @@ def get_users_and_scores() -> list:
"""Return list of (user, total points received) tuples."""
return _storage.get_users_and_scores_total()

def get_pm_preference(user_id: str) -> int:
"""Return user's PM Preference"""
return _storage.get_pm_preference(user_id)

def set_pm_preference(user_id: str, pref: int):
"""Set user's PM Preference"""
_storage.set_pm_preference(user_id, pref)


#####################
# Parsing Message
Expand Down Expand Up @@ -277,7 +305,6 @@ def handle_command(fireball_message):
if SELF_POINTS == 'DISALLOW' and (fireball_message.requestor_id == fireball_message.target_id):
msg = 'You cannot give points to yourself!'
send_message_to = fireball_message.requestor_id_only

# Determine if requestor has enough points to give.
elif check_points(fireball_message.requestor_id, fireball_message.count):
# Add points to target score.
Expand All @@ -286,7 +313,7 @@ def handle_command(fireball_message):
add_user_points_used(fireball_message.requestor_id, fireball_message.count)
msg = f'You received {fireball_message.count} {POINTS} from {fireball_message.requestor_name}'
send_message_to = fireball_message.target_id_only

else:
# Requestor lacks enough points to give.
msg = f'You do not have enough {POINTS}!'
Expand Down Expand Up @@ -323,26 +350,43 @@ def handle_command(fireball_message):
msg = f"You have {points_rmn} {POINTS} remaining"
send_message_to = fireball_message.requestor_id_only

elif fireball_message.command == 'setpm':
set_pm_preference(fireball_message.requestor_id, fireball_message.setting)
if fireball_message.setting:
msg = "Receive PM's: On"
else:
msg = "Receive PM's: Off\n*Warning:* _Future messages that were sent only to you will look like this. This type of response does not typically persist between slack sessions._"
send_message_to = fireball_message.requestor_id_only
else:
# Message was not valid, so
# Message was not valid, so
msg = f'{fireball_message.requestor_id}: I do not understand your message. Try again!'
send_message_to = fireball_message.channel

# Post message to Slack.
slack_client.api_call("chat.postMessage", channel=send_message_to,
text=msg, as_user=True, attachments=attach)
if (send_message_to == fireball_message.requestor_id_only and
get_pm_preference(fireball_message.requestor_id) == 0):
slack_client.api_call("chat.postEphemeral", channel=fireball_message.channel,
text=msg, user=fireball_message.requestor_id_only,
attachments=attach)
elif (send_message_to == fireball_message.target_id and
get_pm_preference(fireball_message.target_id) == 0):
slack_client.api_call("chat.postEphemeral", channel=fireball_message.channel,
text=msg, user=fireball_message.target_id_only,
attachments=attach)
else:
slack_client.api_call("chat.postMessage", channel=send_message_to,
text=msg, as_user=True, attachments=attach)


def give_fireball(user_id, number_of_points):
"""Add `number_of_points` to `user_id`'s total score.
"""
add_user_points_received(user_id, number_of_points)
# def give_fireball(user_id, number_of_points):
# """Add `number_of_points` to `user_id`'s total score.
# """
# add_user_points_received(user_id, number_of_points)


def remove_points(user_id, number_of_points):
"""
"""
pass
# def remove_points(user_id, number_of_points):
# """
# """
# pass


def check_points(user_id, number_of_points):
Expand Down
72 changes: 62 additions & 10 deletions storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ def get_users_and_scores_total(self):
"""Return list of tuples (user_id, points_received_total)."""
pass

### PM Preferences
def get_pm_preference(self, user_id: str):
"""Return user's PM Preference"""
pass

def set_pm_preference(self, user_id: str, pref: int):
"""Set user's PM Preference"""
pass

class AzureTableStorage(Storage):
"""Implementation of `Storage` that uses Azure Table Service.

Expand Down Expand Up @@ -99,6 +108,7 @@ class AzureTableStorage(Storage):
NEGATIVE_POINTS_USED_TODAY = 'NEGATIVE_POINTS_USED_TODAY'
USERS_LIST = 'USERS_LIST'
TOTAL_PARTITION = 'TOTAL'
PM_PREFERENCE = 'PM_PREFERENCE'

def __init__(self):
super().__init__()
Expand Down Expand Up @@ -127,16 +137,17 @@ def _create_user_entry(self, user_id: str):
self.NEGATIVE_POINTS_USED_TOTAL: 0,
self.POINTS_RECEIVED_TODAY: 0,
self.POINTS_USED_TODAY: 0,
self.NEGATIVE_POINTS_USED_TODAY: 0})
self.NEGATIVE_POINTS_USED_TODAY: 0,
self.PM_PREFERENCE: 1})
self._users.add(user_id)

def _user_exists(self, user_id: str) -> bool:
"""Return True if user_id is in storage."""
if self._users is None:
filter_query = "PartitionKey eq '{partition}'".format(partition=self.TOTAL_PARTITION)
records = self._table_service.query_entities(self._table_name,
filter=filter_query,
select='RowKey')
filter=filter_query,
select='RowKey')
self._users = {r['RowKey'] for r in records}
return user_id in self._users

Expand All @@ -149,8 +160,8 @@ def _check_user(self, user_id: str):
def _move_user_to_new_day(self, user_id: str):
"""Save the daily record and reset daily counts on Total partion."""
total_record = self._table_service.get_entity(self._table_name,
self.TOTAL_PARTITION,
user_id)
self.TOTAL_PARTITION,
user_id)
del total_record['etag']
self._save_daily_record(total_record)
self._reset_daily_counts(total_record)
Expand Down Expand Up @@ -271,7 +282,7 @@ def add_user_points_received(self, user_id: str, num: int):
# This record is from a previous day, so need to update table.
self._move_user_to_new_day(user_id)
# Since the record was old, there are 0 Daily points.
record[self.POINTS_RECEIVED_TODAY] = num
record[self.POINTS_RECEIVED_TODAY] = num
else:
# The record is current, so update Daily count.
record[self.POINTS_RECEIVED_TODAY] += num
Expand All @@ -284,10 +295,31 @@ def get_users_and_scores_total(self) -> list:
filter_query = "PartitionKey eq '{}'".format(self.TOTAL_PARTITION)
select_query = "Timestamp,RowKey,{}".format(self.POINTS_RECEIVED_TOTAL)
records = self._table_service.query_entities(self._table_name,
filter=filter_query,
select=select_query)
filter=filter_query,
select=select_query)
return [(r['RowKey'], r[self.POINTS_RECEIVED_TOTAL]) for r in records]

def set_pm_preference(self, user_id: str, pref: int):
"""Set the user's PM Preference"""
self._check_user(user_id)
select_query = "PartitionKey,RowKey,Timestamp,{}".format(self.PM_PREFERENCE)
record = self._table_service.get_entity(self._table_name,
partition_key=self.TOTAL_PARTITION,
row_key=user_id,
select=select_query)
# del record['etag'] # Need to read up on this
record[self.PM_PREFERENCE] = pref

def get_pm_preference(self, user_id: str) -> int:
"""Return user's PM Preference integer. 0 = no pm's, 1 = all pm's"""
self._check_user(user_id)
select_query = "PartitionKey,RowKey,Timestamp,{}".format(self.PM_PREFERENCE)
record = self._table_service.get_entity(self._table_name,
partition_key=self.TOTAL_PARTITION,
row_key=user_id,
select=select_query)
return record[self.PM_PREFERENCE]

@staticmethod
def _get_today() -> datetime.date:
"""Return today's date as a string YYYY-MM-DD."""
Expand Down Expand Up @@ -335,7 +367,7 @@ def _check_date(ts: datetime.datetime) -> bool:

# def _create_user_entry(self, user_id: str):
# """Create new user entry and init fields."""
# self._redis.hmset(user_id, {self.POINTS_USED:0, self.POINTS_RECEIVED:0})
# self._redis.hmset(user_id, {self.POINTS_USED:0, self.POINTS_RECEIVED:0, self.PM_PREFERENCE:1})
# self._redis.sadd(self.USERS_LIST_KEY, user_id)

# def user_exists(self, user_id: str):
Expand Down Expand Up @@ -363,13 +395,21 @@ def _check_date(ts: datetime.datetime) -> bool:
# users = self._redis.smembers(self.USERS_LIST_KEY)
# return [(user, self.get_user_points_received(user)) for user in users]

# def get_pm_preference(self, user_id: str) -> int:
# """Return integer of user's PM preference. 0 = no pm's. 1 = all pm's"""
# return int(self._redis.hget(user_id, self.PM_PREFERENCE))

# def set_pm_preference(self, user_id: str, pref: int):
# """Set's the user's PM Preference"""
# self._redis.hmset(user_id, {self.PM_PREFERENCE:pref})

class InMemoryStorage(Storage):
"""Implementation of `Storage` that uses a dict in memory.
"""

POINTS_USED = 'POINTS_USED'
POINTS_RECEIVED = 'POINTS_RECEIVED'
PM_PREFERENCE = 'PM_PREFERENCE'

def __init__(self):
super().__init__()
Expand All @@ -385,7 +425,8 @@ def create_user_entry(self, user_id: str):
"""Create new user entry and init fields."""
self._data[user_id] = {
self.POINTS_USED : 0,
self.POINTS_RECEIVED : 0
self.POINTS_RECEIVED : 0,
self.PM_PREFERENCE: 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work with the table schema that exists already @MattPitlyk ? Do we have to worry about this setting defaulting back to some value each day?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine. The daily resets are for explicitly specified fields, so if we don't put the preference setting in the daily rest function, it won't be reset.

}

def user_exists(self, user_id: str):
Expand Down Expand Up @@ -417,3 +458,14 @@ def add_user_points_received(self, user_id: str, num: int):
def get_users_and_scores(self):
"""Return list of tuples (user_id, points_received)."""
return [(k, v[self.POINTS_RECEIVED]) for k,v in self._data.items()]

def get_pm_preference(self, user_id: str) -> int:
"""Return user's PM Preference"""
self.check_user(user_id=user_id)
return self._data[user_id].get(self.PM_PREFERENCE)

def set_pm_preference(self, user_id: str, pref: int):
"""Set user's PM Preference"""
self.check_user(user_id=user_id)
user_data = self._data.setdefault(user_id, {})
user_data[self.PM_PREFERENCE] = pref