Skip to content

Commit 99055dd

Browse files
Merge pull request #86 from stefan-qsd/develop
Message actions feature
2 parents 828b357 + 3dbab83 commit 99055dd

File tree

19 files changed

+603
-23
lines changed

19 files changed

+603
-23
lines changed

.pubnub.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
name: python
2-
version: 4.2.1
2+
version: 4.3.0
33
schema: 1
44
scm: github.com/pubnub/python
55
changelog:
6+
- version: v4.3.0
7+
date: Jan 28, 2020
8+
changes:
9+
- type: feature
10+
text: Implemented Message Actions API
11+
- type: feature
12+
text: Implemented Fetch Messages API
13+
- type: feature
14+
text: Added 'include_meta' to history()
15+
- type: feature
16+
text: Added 'include_meta' to fetch_messages()
17+
- type: feature
18+
text: Added 'include_message_actions' to fetch_messages()
619
- version: v4.2.1
720
date: Jan 9, 2020
821
changes:
@@ -191,6 +204,9 @@ features:
191204
- STORAGE-START-END
192205
- STORAGE-COUNT
193206
- STORAGE-MESSAGE-COUNT
207+
- STORAGE-HISTORY-WITH-META
208+
- STORAGE-FETCH-WITH-META
209+
- STORAGE-FETCH-WITH-MESSAGE-ACTIONS
194210
time:
195211
- TIME-TIME
196212
subscribe:
@@ -205,6 +221,7 @@ features:
205221
- SUBSCRIBE-USER-LISTENER
206222
- SUBSCRIBE-SPACE-LISTENER
207223
- SUBSCRIBE-MEMBERSHIP-LISTENER
224+
- SUBSCRIBE-MESSAGE-ACTIONS-LISTENER
208225
signal:
209226
- SIGNAL-SEND
210227
objects:
@@ -228,6 +245,10 @@ features:
228245
- OBJECTS-ADD-MEMBERS
229246
- OBJECTS-UPDATE-MEMBERS
230247
- OBJECTS-REMOVE-MEMBERS
248+
message-actions:
249+
- MESSAGE-ACTIONS-GET
250+
- MESSAGE-ACTIONS-ADD
251+
- MESSAGE-ACTIONS-REMOVE
231252

232253
supported-platforms:
233254
-

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## [4.3.0](https://github.com/pubnub/python/tree/v4.3.0)
2+
3+
[Full Changelog](https://github.com/pubnub/python/compare/v4.2.1...v4.3.0)
4+
5+
- 🌟 Implemented Message Actions API
6+
- 🌟 Implemented Fetch Messages API
7+
- 🌟 Added 'include_meta' to history()
8+
- 🌟 Added 'include_meta' to fetch_messages()
9+
- 🌟 Added 'include_message_actions' to fetch_messages()
10+
111
## [4.2.1](https://github.com/pubnub/python/tree/v4.2.1)
212

313
[Full Changelog](https://github.com/pubnub/python/compare/v4.2.0...v4.2.1)

pubnub/callbacks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def space(self, pubnub, space):
3434
def membership(self, pubnub, membership):
3535
pass
3636

37+
def message_action(self, pubnub, message_action):
38+
pass
39+
3740

3841
class ReconnectionCallback(object):
3942
@abstractmethod

pubnub/endpoints/fetch_messages.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import logging
2+
3+
import six
4+
5+
from pubnub import utils
6+
from pubnub.endpoints.endpoint import Endpoint
7+
from pubnub.enums import HttpMethod, PNOperationType
8+
from pubnub.errors import PNERR_CHANNEL_MISSING, PNERR_HISTORY_MESSAGE_ACTIONS_MULTIPLE_CHANNELS
9+
from pubnub.exceptions import PubNubException
10+
from pubnub.models.consumer.history import PNFetchMessagesResult
11+
12+
logger = logging.getLogger("pubnub")
13+
14+
15+
class FetchMessages(Endpoint):
16+
FETCH_MESSAGES_PATH = "/v3/history/sub-key/%s/channel/%s"
17+
FETCH_MESSAGES_WITH_ACTIONS_PATH = "/v3/history-with-actions/sub-key/%s/channel/%s"
18+
19+
DEFAULT_MESSAGES = 100
20+
MAX_MESSAGES = 25
21+
MAX_MESSAGES_ACTIONS = 100
22+
23+
def __init__(self, pubnub):
24+
Endpoint.__init__(self, pubnub)
25+
self._channels = []
26+
self._start = None
27+
self._end = None
28+
self._maximum_per_channel = None
29+
self._include_meta = None
30+
self._include_message_actions = None
31+
32+
def channels(self, channels):
33+
utils.extend_list(self._channels, channels)
34+
return self
35+
36+
def maximum_per_channel(self, maximum_per_channel):
37+
assert isinstance(maximum_per_channel, six.integer_types)
38+
self._maximum_per_channel = maximum_per_channel
39+
return self
40+
41+
def start(self, start):
42+
assert isinstance(start, six.integer_types)
43+
self._start = start
44+
return self
45+
46+
def end(self, end):
47+
assert isinstance(end, six.integer_types)
48+
self._end = end
49+
return self
50+
51+
def include_meta(self, include_meta):
52+
assert isinstance(include_meta, bool)
53+
self._include_meta = include_meta
54+
return self
55+
56+
def include_message_actions(self, include_message_actions):
57+
assert isinstance(include_message_actions, bool)
58+
self._include_message_actions = include_message_actions
59+
return self
60+
61+
def custom_params(self):
62+
params = {'max': str(self._maximum_per_channel)}
63+
64+
if self._start is not None:
65+
params['start'] = str(self._start)
66+
67+
if self._end is not None:
68+
params['end'] = str(self._end)
69+
70+
if self._include_meta is not None:
71+
params['include_meta'] = "true" if self._include_meta else "false"
72+
73+
return params
74+
75+
def build_path(self):
76+
if self._include_message_actions is False:
77+
return FetchMessages.FETCH_MESSAGES_PATH % (
78+
self.pubnub.config.subscribe_key,
79+
utils.join_channels(self._channels)
80+
)
81+
else:
82+
return FetchMessages.FETCH_MESSAGES_WITH_ACTIONS_PATH % (
83+
self.pubnub.config.subscribe_key,
84+
utils.url_encode(self._channels[0])
85+
)
86+
87+
def http_method(self):
88+
return HttpMethod.GET
89+
90+
def is_auth_required(self):
91+
return True
92+
93+
def validate_params(self):
94+
self.validate_subscribe_key()
95+
96+
if self._channels is None or len(self._channels) == 0:
97+
raise PubNubException(pn_error=PNERR_CHANNEL_MISSING)
98+
99+
if self._include_meta is None:
100+
self._include_meta = False
101+
102+
if self._include_message_actions is None:
103+
self._include_message_actions = False
104+
105+
if self._include_message_actions is False:
106+
if self._maximum_per_channel is None or self._maximum_per_channel < FetchMessages.DEFAULT_MESSAGES:
107+
self._maximum_per_channel = FetchMessages.DEFAULT_MESSAGES
108+
logger.info("maximum_per_channel param defaulting to %d", FetchMessages.DEFAULT_MESSAGES)
109+
elif self._maximum_per_channel > FetchMessages.MAX_MESSAGES:
110+
self._maximum_per_channel = FetchMessages.MAX_MESSAGES
111+
logger.info("maximum_per_channel param defaulting to %d", FetchMessages.DEFAULT_MESSAGES)
112+
else:
113+
if len(self._channels) > 1:
114+
raise PubNubException(pn_error=PNERR_HISTORY_MESSAGE_ACTIONS_MULTIPLE_CHANNELS)
115+
116+
if self._maximum_per_channel is None or self._maximum_per_channel < 1 or\
117+
self._maximum_per_channel > FetchMessages.MAX_MESSAGES_ACTIONS:
118+
self._maximum_per_channel = FetchMessages.MAX_MESSAGES_ACTIONS
119+
logger.info("maximum_per_channel param defaulting to %d", FetchMessages.DEFAULT_MESSAGES)
120+
121+
def create_response(self, envelope): # pylint: disable=W0221
122+
return PNFetchMessagesResult.from_json(
123+
json_input=envelope,
124+
include_message_actions=self._include_message_actions,
125+
start_timetoken=self._start,
126+
end_timetoken=self._end)
127+
128+
def request_timeout(self):
129+
return self.pubnub.config.non_subscribe_request_timeout
130+
131+
def connect_timeout(self):
132+
return self.pubnub.config.connect_timeout
133+
134+
def operation_type(self):
135+
return PNOperationType.PNFetchMessagesOperation
136+
137+
def name(self):
138+
return "Fetch messages"

pubnub/endpoints/history.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(self, pubnub):
1818
self._reverse = None
1919
self._count = None
2020
self._include_timetoken = None
21+
self._include_meta = None
2122

2223
def channel(self, channel):
2324
self._channel = channel
@@ -48,6 +49,11 @@ def include_timetoken(self, include_timetoken):
4849
self._include_timetoken = include_timetoken
4950
return self
5051

52+
def include_meta(self, include_meta):
53+
assert isinstance(include_meta, bool)
54+
self._include_meta = include_meta
55+
return self
56+
5157
def custom_params(self):
5258
params = {}
5359

@@ -68,6 +74,9 @@ def custom_params(self):
6874
if self._include_timetoken is not None:
6975
params['include_token'] = "true" if self._include_timetoken else "false"
7076

77+
if self._include_meta is not None:
78+
params['include_meta'] = "true" if self._include_meta else "false"
79+
7180
return params
7281

7382
def build_path(self):
@@ -90,7 +99,8 @@ def create_response(self, envelope):
9099
return PNHistoryResult.from_json(
91100
json_input=envelope,
92101
crypto=self.pubnub.config.crypto,
93-
include_tt_option=self._include_timetoken,
102+
include_timetoken=self._include_timetoken,
103+
include_meta=self._include_meta,
94104
cipher=self.pubnub.config.cipher_key)
95105

96106
def request_timeout(self):

pubnub/endpoints/message_actions/__init__.py

Whitespace-only changes.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from pubnub import utils
2+
from pubnub.endpoints.endpoint import Endpoint
3+
from pubnub.errors import PNERR_MESSAGE_ACTION_VALUE_MISSING, PNERR_MESSAGE_ACTION_TYPE_MISSING, \
4+
PNERR_MESSAGE_TIMETOKEN_MISSING, PNERR_MESSAGE_ACTION_MISSING
5+
from pubnub.exceptions import PubNubException
6+
from pubnub.enums import HttpMethod, PNOperationType
7+
from pubnub.models.consumer.message_actions import PNAddMessageActionResult
8+
9+
10+
class AddMessageAction(Endpoint):
11+
ADD_MESSAGE_ACTION_PATH = "/v1/message-actions/%s/channel/%s/message/%s"
12+
13+
def __init__(self, pubnub):
14+
Endpoint.__init__(self, pubnub)
15+
self._channel = None
16+
self._message_action = None
17+
18+
def channel(self, channel):
19+
self._channel = str(channel)
20+
return self
21+
22+
def message_action(self, message_action):
23+
self._message_action = message_action
24+
return self
25+
26+
def custom_params(self):
27+
return {}
28+
29+
def build_data(self):
30+
params = {
31+
'type': self._message_action.type,
32+
'value': self._message_action.value
33+
}
34+
35+
return utils.write_value_as_string(params)
36+
37+
def build_path(self):
38+
return AddMessageAction.ADD_MESSAGE_ACTION_PATH % (
39+
self.pubnub.config.subscribe_key,
40+
utils.url_encode(self._channel),
41+
self._message_action.message_timetoken
42+
)
43+
44+
def http_method(self):
45+
return HttpMethod.POST
46+
47+
def validate_params(self):
48+
self.validate_subscribe_key()
49+
self.validate_channel()
50+
self.validate_message_action()
51+
52+
def create_response(self, envelope): # pylint: disable=W0221
53+
return PNAddMessageActionResult(envelope['data'])
54+
55+
def is_auth_required(self):
56+
return True
57+
58+
def request_timeout(self):
59+
return self.pubnub.config.non_subscribe_request_timeout
60+
61+
def connect_timeout(self):
62+
return self.pubnub.config.connect_timeout
63+
64+
def operation_type(self):
65+
return PNOperationType.PNAddMessageAction
66+
67+
def name(self):
68+
return "Add message action"
69+
70+
def validate_message_action(self):
71+
if self._message_action is None:
72+
raise PubNubException(pn_error=PNERR_MESSAGE_ACTION_MISSING)
73+
74+
if self._message_action.message_timetoken is None:
75+
raise PubNubException(pn_error=PNERR_MESSAGE_TIMETOKEN_MISSING)
76+
77+
if self._message_action.type is None or len(self._message_action.type) == 0:
78+
raise PubNubException(pn_error=PNERR_MESSAGE_ACTION_TYPE_MISSING)
79+
80+
if self._message_action.value is None or len(self._message_action.value) == 0:
81+
raise PubNubException(pn_error=PNERR_MESSAGE_ACTION_VALUE_MISSING)

0 commit comments

Comments
 (0)