Skip to content

Commit 80651d6

Browse files
committed
feat(kno-237): user preferences, workflows, user deletions
1 parent b2e016c commit 80651d6

File tree

6 files changed

+283
-36
lines changed

6 files changed

+283
-36
lines changed

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ from knockapi import Knock
5656
client = Knock(api_key="sk_12345")
5757

5858
client.notify(
59-
name="dinosaurs-loose",
59+
key="dinosaurs-loose",
6060
actor="dnedry",
6161
recipients=["jhammond", "agrant", "imalcolm", "esattler"],
62+
cancellation_key=alert.id,
6263
data={
6364
"type": "trex",
6465
"priority": 1
@@ -72,13 +73,30 @@ client.notify(
7273
from knockapi import Knock
7374
client = Knock(api_key="sk_12345")
7475

75-
client.cancel_notify(
76-
name="dinosaurs-loose",
76+
client.workflows.cancel(
77+
key="dinosaurs-loose",
7778
cancelation_key=alert.id,
7879
recipients=["jhammond", "agrant", "imalcolm", "esattler"],
7980
)
8081
```
8182

83+
### User preferences
84+
85+
```python
86+
from knockapi import Knock
87+
client = Knock(api_key="sk_12345")
88+
89+
# Replaces the preferences for the user
90+
client.preferences.update(
91+
user_id="jhammond",
92+
channel_types={'email': True},
93+
workflows={'dinosaurs-loose': False}
94+
)
95+
96+
# Retrieve the current preferences
97+
client.preferences.get(user_id="jhammond")
98+
```
99+
82100
### Signing JWTs
83101

84102
You can use the `pyjwt` package to [sign JWTs easily](https://pyjwt.readthedocs.io/en/stable/usage.html#encoding-decoding-tokens-with-rs256-rsa).

knockapi/client.py

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import requests
22

3-
__version__ = '0.1.1'
3+
__version__ = '0.2.0'
44

55

66
class Connection(object):
@@ -43,44 +43,29 @@ def users(self):
4343
from .resources import User
4444
return User(self)
4545

46-
def notify(self, name, actor, recipients, data={}, cancelation_key=None):
46+
@property
47+
def workflows(self):
48+
from .resources import Workflows
49+
return Workflows(self)
50+
51+
@property
52+
def preferences(self):
53+
from .resources import Preferences
54+
return Preferences(self)
55+
56+
def notify(self, key, actor, recipients, data={}, cancellation_key=None):
4757
"""
48-
Triggers a notification workflow.
58+
Triggers a workflow.
4959
5060
Args:
51-
name (str): The name of the notification to invoke.
61+
key (str): The key of the workflow to invoke.
5262
actor (str): The ID of the actor performing this action.
5363
recipients (array): An array of user IDs of who should be notified.
5464
data (dict): Any data to be passed to the notify call.
55-
cancelation_key (str): A key used to cancel this notify.
56-
57-
Returns:
58-
dict: Response from Knock.
59-
"""
60-
params = {
61-
'name': name,
62-
'actor': actor,
63-
'recipients': recipients,
64-
'data': data,
65-
'cancelation_key': cancelation_key
66-
}
67-
return self.request("post", "/notify", payload=params)
68-
69-
def cancel_notify(self, name, cancelation_key, recipients=None):
70-
"""
71-
Cancels an in-flight notify call.
72-
73-
Args:
74-
name (str): The name of the notification to invoke.
75-
cancelation_key (str): The key to identify the notify.
76-
recipients (array): An array of user IDs for recipients to cancel (can be omitted).
65+
cancellation_key (str): A key used to cancel this workflow.
7766
7867
Returns:
7968
dict: Response from Knock.
8069
"""
81-
params = {
82-
'name': name,
83-
'recipients': recipients,
84-
'cancelation_key': cancelation_key
85-
}
86-
return self.request("post", "/notify/cancel", payload=params)
70+
# Note: this is essentially a delegated method
71+
return self.workflows.trigger(key, actor, recipients, data=data, cancellation_key=cancellation_key)

knockapi/resources/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
from .users import User
1+
from .users import User
2+
from .workflows import Workflows
3+
from .preferences import Preferences

knockapi/resources/preferences.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from .service import Service
2+
3+
default_set_id = "default"
4+
5+
6+
class Preferences(Service):
7+
def get_all(self, user_id):
8+
"""
9+
Get a users full set of preferences
10+
11+
Args:
12+
user_id: The users ID
13+
14+
Returns:
15+
dict: User response from Knock.
16+
"""
17+
endpoint = '/users/{}/preferences'.format(user_id)
18+
return self.client.request('get', endpoint)
19+
20+
def get(self, user_id, options={}):
21+
"""
22+
Get a users preference set
23+
24+
Args:
25+
user_id (str): The users ID
26+
options (dict):
27+
preference_set (str): The preference set to retrieve (defaults to "default")
28+
29+
Returns:
30+
dict: User response from Knock.
31+
"""
32+
preference_set_id = options.get('preference_set', default_set_id)
33+
endpoint = '/users/{}/preferences/{}'.format(
34+
user_id, preference_set_id)
35+
36+
return self.client.request('get', endpoint)
37+
38+
def update(self, user_id, channel_types=None, categories=None, workflows=None, options={}):
39+
"""
40+
Sets the preference set for the user
41+
42+
Args:
43+
user_id (str): The users ID
44+
channel_types (dict): A dictionary of channel type preferences
45+
categories (dict): A dictionary of category preferences
46+
workflows (dict): A dictionary of workflow preferences
47+
options (dict): A dictionary of options
48+
49+
Returns:
50+
dict: User response from Knock.
51+
"""
52+
preference_set_id = options.get('preference_set', default_set_id)
53+
54+
endpoint = '/users/{}/preferences/{}'.format(
55+
user_id, preference_set_id)
56+
57+
params = {
58+
'channel_types': channel_types,
59+
'categories': categories,
60+
'workflows': workflows
61+
}
62+
63+
return self.client.request('put', endpoint, payload=params)
64+
65+
def set_channel_types(self, user_id, preferences, options={}):
66+
"""
67+
Sets the channel type preferences for the user
68+
69+
Args:
70+
user_id (str): The users ID
71+
preferences (dict): A dictionary of channel type preferences
72+
options (dict): A dictionary of options
73+
74+
Returns:
75+
dict: User response from Knock.
76+
"""
77+
preference_set_id = options.get('preference_set', default_set_id)
78+
79+
endpoint = '/users/{}/preferences/{}/channel_types'.format(
80+
user_id, preference_set_id)
81+
82+
return self.client.request('put', endpoint, payload=preferences)
83+
84+
def set_channel_type(self, user_id, channel_type, setting, options={}):
85+
"""
86+
Sets the channel type preference for the user
87+
88+
Args:
89+
user_id (str): The users ID
90+
channel_type (str): The channel_type to set
91+
setting (boolean): The preference setting
92+
options (dict): A dictionary of options
93+
94+
Returns:
95+
dict: User response from Knock.
96+
"""
97+
preference_set_id = options.get('preference_set', default_set_id)
98+
99+
endpoint = '/users/{}/preferences/{}/channel_types/{}'.format(
100+
user_id, preference_set_id, channel_type)
101+
102+
return self.client.request('put', endpoint, payload={'subscribed': setting})
103+
104+
def set_workflows(self, user_id, preferences, options={}):
105+
"""
106+
Sets the workflow preferences for the user
107+
108+
Args:
109+
user_id (str): The users ID
110+
preferences (dict): A dictionary of workflow preferences
111+
options (dict): A dictionary of options
112+
113+
Returns:
114+
dict: User response from Knock.
115+
"""
116+
preference_set_id = options.get('preference_set', default_set_id)
117+
118+
endpoint = '/users/{}/preferences/{}/workflows'.format(
119+
user_id, preference_set_id)
120+
121+
return self.client.request('put', endpoint, payload=preferences)
122+
123+
def set_workflow(self, user_id, key, setting, options={}):
124+
"""
125+
Sets the workflow preferences for the user
126+
127+
Args:
128+
user_id (str): The users ID
129+
key (str): The workflow key
130+
setting (boolean or dict): The preference setting
131+
options (dict): A dictionary of options
132+
133+
Returns:
134+
dict: User response from Knock.
135+
"""
136+
preference_set_id = options.get('preference_set', default_set_id)
137+
138+
endpoint = '/users/{}/preferences/{}/workflows/{}'.format(
139+
user_id, preference_set_id, key)
140+
141+
return self.client.request('put', endpoint, payload={'subscribed': setting})
142+
143+
def set_categories(self, user_id, preferences, options={}):
144+
"""
145+
Sets the categories preferences for the user
146+
147+
Args:
148+
user_id (str): The users ID
149+
preferences (dict): A dictionary of category preferences
150+
options (dict): A dictionary of options
151+
152+
Returns:
153+
dict: User response from Knock.
154+
"""
155+
preference_set_id = options.get('preference_set', default_set_id)
156+
157+
endpoint = '/users/{}/preferences/{}/categories'.format(
158+
user_id, preference_set_id)
159+
160+
return self.client.request('put', endpoint, payload=preferences)
161+
162+
def set_category(self, user_id, key, setting, options={}):
163+
"""
164+
Sets the category preferences for the user
165+
166+
Args:
167+
user_id (str): The users ID
168+
key (str): The category key
169+
setting (boolean or dict): The preference setting
170+
options (dict): A dictionary of options
171+
172+
Returns:
173+
dict: User response from Knock.
174+
"""
175+
preference_set_id = options.get('preference_set', default_set_id)
176+
177+
endpoint = '/users/{}/preferences/{}/categories/{}'.format(
178+
user_id, preference_set_id, key)
179+
180+
return self.client.request('put', endpoint, payload={'subscribed': setting})

knockapi/resources/users.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,16 @@ def identify(self, id, data={}):
2828
"""
2929
endpoint = '/users/{}'.format(id)
3030
return self.client.request('put', endpoint, payload=data)
31+
32+
def delete(self, id):
33+
"""
34+
Delets the given user.
35+
36+
Args:
37+
id (str): The users ID
38+
39+
Returns:
40+
dict: User response from Knock.
41+
"""
42+
endpoint = '/users/{}'.format(id)
43+
return self.client.request('delete', endpoint)

knockapi/resources/workflows.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from .service import Service
2+
3+
4+
class Workflows(Service):
5+
def trigger(self, key, actor, recipients, data={}, cancellation_key=None):
6+
"""
7+
Triggers a workflow.
8+
9+
Args:
10+
key (str): The key of the workflow to invoke.
11+
actor (str): The ID of the actor performing this action.
12+
recipients (array): An array of user IDs of who should be notified.
13+
data (dict): Any data to be passed to the notify call.
14+
cancellation_key (str): A key used to cancel this notify.
15+
16+
Returns:
17+
dict: Response from Knock.
18+
"""
19+
endpoint = '/workflows/{}/trigger'.format(key)
20+
21+
params = {
22+
'actor': actor,
23+
'recipients': recipients,
24+
'data': data,
25+
'cancellation_key': cancellation_key
26+
}
27+
28+
return self.request("post", endpoint, payload=params)
29+
30+
def cancel(self, key, cancellation_key, recipients=None):
31+
"""
32+
Cancels an in-flight workflow.
33+
34+
Args:
35+
key (str): The workflow to cancel.
36+
cancellation_key (str): The key to identify the workflow.
37+
recipients (array): An array of user IDs for recipients to cancel (can be omitted).
38+
39+
Returns:
40+
dict: Response from Knock.
41+
"""
42+
endpoint = '/workflows/{}/cancel'.format(key)
43+
44+
params = {
45+
'recipients': recipients,
46+
'cancellation_key': cancellation_key
47+
}
48+
49+
return self.request("post", endpoint, payload=params)

0 commit comments

Comments
 (0)