33
44from urbanairship .devices import ChannelTags
55from urbanairship import common
6+ from urbanairship .push .payload import device_types
67
78logger = logging .getLogger ("urbanairship" )
89
@@ -14,57 +15,123 @@ def __init__(self, airship, named_user_id=None):
1415
1516 self ._airship = airship
1617 self .named_user_id = named_user_id
18+ self .channel_id = None
19+ self .email_address = None
20+ self .device_type = None
1721
18- def associate (self , channel_id , device_type ):
19- """Associate a channel with a named user ID
22+ @property
23+ def _channel_associate_payload (self ):
24+ """
25+ creates the paylaod for channel_id associate and disassociate calls
26+ """
27+ payload = {"named_user_id" : self .named_user_id , "channel_id" : self .channel_id }
28+
29+ if self .device_type :
30+ payload ["device_type" ] = self .device_type
31+
32+ return payload
33+
34+ @property
35+ def _email_associate_payload (self ):
36+ """
37+ creates the payload for email_address associate and disassociate calls
38+ """
39+ return {
40+ "named_user_id" : self .named_user_id ,
41+ "email_address" : self .email_address ,
42+ }
43+
44+ def _dis_associate (self , url , body ):
45+ response = self ._airship .request (
46+ method = "POST" ,
47+ body = json .dumps (body ),
48+ url = url ,
49+ content_type = "application/json" ,
50+ version = 3 ,
51+ )
52+
53+ return response
54+
55+ def associate (self , channel_id , device_type = None ):
56+ """Associate a channel_id with a named user ID.
57+ Either channel_id and device_type OR email_address must be included.
2058
21- :param channel_id: The ID of the channel you would like to associate
59+ :param channel_id: Required. The ID of the channel you would like to associate
2260 with the named user
23- :param device_type: The device type of the channel
61+ :param device_type: The device type of the channel, do not include for web
62+ notify channel_ids
63+
2464 :return:
2565 """
2666 if not self .named_user_id :
2767 raise ValueError ("named_user_id is required for association" )
2868
29- body = json .dumps (
30- {
31- "channel_id" : channel_id ,
32- "device_type" : device_type ,
33- "named_user_id" : self .named_user_id ,
34- }
35- ).encode ("utf-8" )
36- response = self ._airship ._request (
37- "POST" ,
38- body ,
39- self ._airship .urls .get ("named_user_associate_url" ),
40- "application/json" ,
41- version = 3 ,
69+ self .channel_id = channel_id
70+
71+ if device_type :
72+ self .device_type = device_type
73+
74+ return self ._dis_associate (
75+ url = self ._airship .urls .get ("named_user_associate_url" ),
76+ body = self ._channel_associate_payload ,
4277 )
43- return response
4478
45- def disassociate (self , channel_id , device_type ):
79+ def email_associate (self , email_address ):
80+ """Associate an email_address with a named user id. This call is for a literal
81+ email address.
82+
83+ :param email_address: Required. The email address to associate.
84+
85+ :return:
86+ """
87+ if not self .named_user_id :
88+ raise ValueError ("named_user_id is required for association" )
89+
90+ self .email_address = email_address
91+
92+ return self ._dis_associate (
93+ url = self ._airship .urls .get ("named_user_associate_url" ),
94+ body = self ._email_associate_payload ,
95+ )
96+
97+ def disassociate (self , channel_id , device_type = None ):
4698 """Disassociate a channel with a named user ID
4799
48100 :param channel_id: The ID of the channel you would like to disassociate
49- :param device_type: The device type of the channel
101+ :param device_type: The device type of the channel. Do not include for web
102+ notify channels.
103+
50104 :return:
51105 """
106+ if not self .named_user_id :
107+ raise ValueError ("named_user_id is required for association" )
52108
53- payload = { " channel_id" : channel_id , "device_type" : device_type }
109+ self . channel_id = channel_id
54110
55- if self . named_user_id :
56- payload [ "named_user_id" ] = self . named_user_id
111+ if device_type :
112+ self . device_type = device_type
57113
58- body = json .dumps (payload ).encode ("utf-8" )
59- response = self ._airship ._request (
60- "POST" ,
61- body ,
62- self ._airship .urls .get ("named_user_disassociate_url" ),
63- "application/json" ,
64- version = 3 ,
114+ return self ._dis_associate (
115+ url = self ._airship .urls .get ("named_user_disassociate_url" ),
116+ body = self ._channel_associate_payload ,
65117 )
66118
67- return response
119+ def email_disassociate (self , email_address ):
120+ """Disassociate an email_address with a named user ID
121+
122+ :param channel_id: The email_address you would like to disassociate
123+
124+ :return:
125+ """
126+ if not self .named_user_id :
127+ raise ValueError ("named_user_id is required for association" )
128+
129+ self .email_address = email_address
130+
131+ return self ._dis_associate (
132+ url = self ._airship .urls .get ("named_user_disassociate_url" ),
133+ body = self ._email_associate_payload ,
134+ )
68135
69136 def lookup (self ):
70137 """Lookup a single named user
@@ -125,6 +192,113 @@ def tag(self, group, add=None, remove=None, set=None):
125192
126193 return response .json ()
127194
195+ def update (self , associate = None , disassociate = None , tags = None , attributes = None ):
196+ """
197+ Create or update a named user by associating/disassociating channels
198+ and adding/removing tags and attributes in a single request.
199+ If a channel has an assigned named user and you make an additional call to
200+ associate that same channel with a new named user, the original named user
201+ association will be removed and the new named user and associated data will
202+ take its place. Additionally, all tags associated to the original named
203+ user cannot be used to address this channel unless they are also associated
204+ with the new named user.
205+
206+ Please see https://docs.airship.com/api/ua/#operation-api-named_users-named_user_id-post
207+
208+ :param assocaite: Optional. List of objects to associate with the named user
209+ :param disassociate: Optional. List of objects to disassociate from the named
210+ user
211+ :param tags: Optional. Dictionary of set, add, remove objects to apply to
212+ named user
213+ :param attributes: Optional. List of attributes to apply to named user.
214+
215+ :return:
216+ """
217+ if not any ([associate , disassociate , tags , attributes ]):
218+ raise ValueError (
219+ "At least one of associate, disassociate, tags, or attributes must be included"
220+ )
221+
222+ body = {}
223+
224+ if associate :
225+ body ["associate" ] = associate
226+ if disassociate :
227+ body ["disassociate" ] = disassociate
228+ if tags :
229+ body ["tags" ] = tags
230+ if attributes :
231+ body ["attributes" ] = attributes
232+
233+ response = self ._airship .request (
234+ method = "POST" ,
235+ body = json .dumps (body ),
236+ url = self ._airship .urls .get ("named_user_url" ) + self .named_user_id ,
237+ content_type = "application/json" ,
238+ version = 3 ,
239+ )
240+
241+ return response
242+
243+ def attributes (self , attributes ):
244+ """
245+ Set or remove attributes on a named user.
246+ A single request body may contain a set or remove field, or both, or a single
247+ set field. If both set and remove fields are present and the intersection of
248+ the attributes in these fields is not empty, then a 400 will be returned.
249+ If an attribute request is partially valid, i.e. at least one attribute exists,
250+ Airship returns a 200 with a warning in containing a list of attributes that
251+ failed to update.
252+ Please see https://docs.airship.com/api/ua/#operation-api-named_users-named_user_id-attributes-post
253+ for more about using Airship attributes.
254+
255+ :params attributes: Required. A list of attribute objects to set or remove on
256+ the named user.
257+ """
258+ if type (attributes ) is not list :
259+ raise ValueError ("attributes must be a list of attribute objects" )
260+
261+ response = self ._airship .request (
262+ method = "POST" ,
263+ body = json .dumps ({"attributes" : attributes }),
264+ url = self ._airship .urls .get ("named_user_url" )
265+ + self .named_user_id
266+ + "attributes" ,
267+ content_type = "application/json" ,
268+ version = 3 ,
269+ )
270+
271+ return response
272+
273+ @classmethod
274+ def uninstall (cls , airship , named_users ):
275+ """
276+ Disassociate and delete all channels associated with the named_user_id(s) and
277+ also delete the named_user_id(s). This call removes all channels associated
278+ with a named user from Airship systems in compliance with data privacy laws.
279+ Uninstalling channels also removes accompanying analytic data (including
280+ Performance Analytics) from the system.
281+ Channel uninstallation, like channel creation, is an asynchronous operation,
282+ and may take some time to complete.
283+
284+ :param airship: Required. An urbanairship.Airship instance.
285+ :param named_users: Required a list of named_user_ids to completely uninstall
286+
287+ :return:
288+ """
289+ if type (named_users ) is not list :
290+ raise ValueError ("named_users must be a list" )
291+
292+ response = airship .request (
293+ method = "POST" ,
294+ body = json .dumps ({"named_user_id" : named_users }),
295+ url = airship .urls .get ("named_user_uninstall_url" ),
296+ content_type = "application/json" ,
297+ version = 3 ,
298+ )
299+
300+ return response
301+
128302 @classmethod
129303 def from_payload (cls , payload ):
130304 """
0 commit comments