Skip to content

Commit

Permalink
Merge pull request #2 from joshbenner/enhancements
Browse files Browse the repository at this point in the history
Several minor enhancements
  • Loading branch information
jamesridgway authored Jul 3, 2021
2 parents c60fe22 + 353234f commit 2297b74
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 6 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Example configuration:
key: 7
text: Off sick
emoji: ':face_with_thermometer:'
until: tomorrow at 8am
- action: status
key: 8
text: On holiday
Expand All @@ -71,7 +72,7 @@ This plugin requires a Slack API key to function.

Head over to https://api.slack.com/apps to create your app.

Once you have created your app you will be able to access your OAuth Access Token under **OAuth & Permissions** - this
Once you have created your app you will be able to access your OAuth Access Token under **OAuth & Permissions** - this
is your `api_key` value.

### Scopes
Expand Down
17 changes: 16 additions & 1 deletion devdeck_slack/slack_deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,24 @@ def settings_schema(self):
'type': 'string',
'required': False
},
'emoji_slack': {
'type': 'string',
'required': False
},
'dnd': {
'type': 'boolean',
'required': False
},
'duration': {
'type': 'integer',
'required': False
'min': 1,
'required': False,
'excludes': 'until',
},
'until': {
'type': 'string',
'required': False,
'excludes': 'duration'
}
}
}
Expand Down
53 changes: 51 additions & 2 deletions devdeck_slack/slack_status_control.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import logging
import math
import time

import parsedatetime
import tzlocal

from devdeck_core.controls.deck_control import DeckControl


class SlackStatusControl(DeckControl):
def __init__(self, key_no, api_client, **kwargs):
self.api_client = api_client
self.__logger = logging.getLogger('devdeck')
self.cal = parsedatetime.Calendar(
version=parsedatetime.VERSION_CONTEXT_STYLE)
super().__init__(key_no, **kwargs)

def initialize(self):
Expand All @@ -13,10 +23,30 @@ def initialize(self):
.end()

def pressed(self):
expires = 0 # 0 = never
if 'duration' in self.settings:
expires = int(time.time()) + self.settings['duration'] * 60
elif 'until' in self.settings:
dt, _ = self.cal.parseDT(self.settings['until'],
tzinfo=tzlocal.get_localzone())
if dt is None:
self.__logger.error("Could not parse until: %s",
self.settings['until'])
else:
expires = int(dt.timestamp())
dnd = self.settings.get('dnd', False)
self.api_client.users_profile_set(profile={
"status_text": self.settings['text'],
"status_emoji": self.settings['emoji']
"status_emoji": self.settings.get('emoji_slack',
self.settings['emoji']),
"status_expiration": expires
})
if dnd:
if expires > 0:
minutes = int(math.ceil((expires - time.time()) / 60))
self.api_client.dnd_setSnooze(num_minutes=minutes)
else:
self.api_client.dnd_setSnooze()

def settings_schema(self):
return {
Expand All @@ -28,4 +58,23 @@ def settings_schema(self):
'type': 'string',
'required': True,
},
}
'emoji_slack': {
'type': 'string',
'required': False
},
'dnd': {
'type': 'boolean',
'required': False
},
'duration': {
'type': 'integer',
'min': 1,
'required': False,
'excludes': 'until',
},
'until': {
'type': 'string',
'required': False,
'excludes': 'duration'
}
}
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
assertpy
devdeck-core==1.0.6
pytest
slack_sdk==3.1.0
slack_sdk==3.1.0
parsedatetime
tzlocal
69 changes: 68 additions & 1 deletion tests/devdeck_slack/test_slack_status_control.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import math
from unittest import mock
import time

import parsedatetime
import tzlocal

from devdeck_core.mock_deck_context import mock_context, assert_rendered
from devdeck_core.renderer import Renderer
Expand All @@ -21,5 +26,67 @@ def test_pressed_sets_status(self, api_client):
control.pressed()
api_client.users_profile_set.assert_called_with(profile={
'status_text': 'On lunch',
'status_emoji': ':sandwich:'
'status_emoji': ':sandwich:',
'status_expiration': 0
})
api_client.dnd_setSnooze.assert_not_called()

@mock.patch('slack_sdk.WebClient')
def test_pressed_sets_status_alt_emoji(self, api_client):
control = SlackStatusControl(0, api_client, **{
'emoji': ':sandwich:', 'text': 'On lunch', 'emoji_slack': ':test:'
})
with mock_context(control) as ctx:
control.pressed()
api_client.users_profile_set.assert_called_with(profile={
'status_text': 'On lunch',
'status_emoji': ':test:',
'status_expiration': 0
})
api_client.dnd_setSnooze.assert_not_called()

@mock.patch('slack_sdk.WebClient')
def test_dnd_set_without_timeout(self, api_client):
control = SlackStatusControl(0, api_client, **{
'emoji': ':calendar:', 'text': 'Busy', 'dnd': True
})
with mock_context(control) as ctx:
control.pressed()
api_client.users_profile_set.assert_called_with(profile={
'status_text': 'Busy',
'status_emoji': ':calendar:',
'status_expiration': 0
})
api_client.dnd_setSnooze.assert_called_with()

@mock.patch('slack_sdk.WebClient')
def test_dnd_set_with_duration(self, api_client):
control = SlackStatusControl(0, api_client, **{
'emoji': ':calendar:', 'text': 'Busy', 'dnd': True, 'duration': 5
})
with mock_context(control) as ctx:
control.pressed()
api_client.users_profile_set.assert_called_with(profile={
'status_text': 'Busy',
'status_emoji': ':calendar:',
'status_expiration': int(time.time()) + 300
})
api_client.dnd_setSnooze.assert_called_with(num_minutes=5)

@mock.patch('slack_sdk.WebClient')
def test_dnd_set_with_until(self, api_client):
control = SlackStatusControl(0, api_client, **{
'emoji': ':calendar:', 'text': 'Busy', 'dnd': True,
'until': 'tomorrow at 7am'
})
c = parsedatetime.Calendar(version=parsedatetime.VERSION_CONTEXT_STYLE)
ts, _ = c.parseDT('tomorrow at 7am', tzinfo=tzlocal.get_localzone())
minutes = int(math.ceil((ts.timestamp() - time.time()) / 60))
with mock_context(control) as ctx:
control.pressed()
api_client.users_profile_set.assert_called_with(profile={
'status_text': 'Busy',
'status_emoji': ':calendar:',
'status_expiration': int(ts.timestamp())
})
api_client.dnd_setSnooze.assert_called_with(num_minutes=minutes)

0 comments on commit 2297b74

Please sign in to comment.