Skip to content

Commit 91300c1

Browse files
authored
support narrowcast api (#241)
1 parent 2e30239 commit 91300c1

File tree

10 files changed

+854
-1
lines changed

10 files changed

+854
-1
lines changed

linebot/api.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
MessageDeliveryBroadcastResponse, MessageDeliveryMulticastResponse,
2828
MessageDeliveryPushResponse, MessageDeliveryReplyResponse,
2929
InsightMessageDeliveryResponse, InsightFollowersResponse, InsightDemographicResponse,
30-
InsightMessageEventResponse, BroadcastResponse,
30+
InsightMessageEventResponse, BroadcastResponse, NarrowcastResponse,
31+
MessageProgressNarrowcastResponse,
3132
)
3233

3334

@@ -210,6 +211,70 @@ def broadcast(self, messages, notification_disabled=False, timeout=None):
210211

211212
return BroadcastResponse(request_id=response.headers.get('X-Line-Request-Id'))
212213

214+
def narrowcast(self, messages, recipient=None, filter=None, limit=None, timeout=None):
215+
"""Call narrowcast API.
216+
217+
https://developers.line.biz/en/reference/messaging-api/#send-narrowcast-message
218+
219+
Sends push messages to multiple users at any time.
220+
Messages cannot be sent to groups or rooms.
221+
222+
:param messages: Messages.
223+
Max: 5
224+
:type messages: T <= :py:class:`linebot.models.send_messages.SendMessage` |
225+
list[T <= :py:class:`linebot.models.send_messages.SendMessage`]
226+
:param recipient: audience object of recipient
227+
:type recipient: T <= :py:class:`linebot.models.recipient.AudienceRecipient`
228+
:param filter: demographic filter of recipient
229+
:type filter: T <= :py:class:`linebot.models.filter.DemographicFilter`
230+
:param limit: limit on this narrowcast
231+
:type limit: T <= :py:class:`linebot.models.limit.Limit`
232+
:param timeout: (optional) How long to wait for the server
233+
to send data before giving up, as a float,
234+
or a (connect timeout, read timeout) float tuple.
235+
Default is self.http_client.timeout
236+
:type timeout: float | tuple(float, float)
237+
:rtype: :py:class:`linebot.models.responses.NarrowcastResponse`
238+
"""
239+
if not isinstance(messages, (list, tuple)):
240+
messages = [messages]
241+
242+
data = {
243+
'messages': [message.as_json_dict() for message in messages],
244+
'recipient': recipient.as_json_dict(),
245+
'filter': filter.as_json_dict(),
246+
'limit': limit.as_json_dict(),
247+
}
248+
249+
response = self._post(
250+
'/v2/bot/message/narrowcast', data=json.dumps(data), timeout=timeout
251+
)
252+
253+
return NarrowcastResponse(request_id=response.headers.get('X-Line-Request-Id'))
254+
255+
def get_progress_status_narrowcast(self, request_id, timeout=None):
256+
"""Get progress status of narrowcast messages sent.
257+
258+
https://developers.line.biz/en/reference/messaging-api/#get-narrowcast-progress-status
259+
260+
Gets the number of messages sent with the /bot/message/progress/narrowcast endpoint.
261+
262+
:param str request_id: request ID of narrowcast.
263+
:param timeout: (optional) How long to wait for the server
264+
to send data before giving up, as a float,
265+
or a (connect timeout, read timeout) float tuple.
266+
Default is self.http_client.timeout
267+
:type timeout: float | tuple(float, float)
268+
:rtype: :py:class:`linebot.models.responses.MessageDeliveryBroadcastResponse`
269+
"""
270+
response = self._get(
271+
'/v2/bot/message/progress/narrowcast?requestId={request_id}'.format(
272+
request_id=request_id),
273+
timeout=timeout
274+
)
275+
276+
return MessageProgressNarrowcastResponse.new_from_json_dict(response.json)
277+
213278
def get_message_delivery_broadcast(self, date, timeout=None):
214279
"""Get number of sent broadcast messages.
215280

linebot/models/__init__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@
5454
Beacon,
5555
Link,
5656
)
57+
from .filter import( # noqa
58+
Filter,
59+
DemographicFilter,
60+
GenderFilter,
61+
AppTypeFilter,
62+
AreaFilter,
63+
AgeFilter,
64+
SubscriptionPeriodFilter,
65+
)
66+
5767
from .flex_message import ( # noqa
5868
FlexSendMessage,
5969
FlexContainer,
@@ -93,6 +103,11 @@
93103
MessageInsight,
94104
ClickInsight,
95105
)
106+
107+
from .limit import ( # noqa
108+
Limit,
109+
)
110+
96111
from .messages import ( # noqa
97112
Message,
98113
TextMessage,
@@ -103,6 +118,17 @@
103118
StickerMessage,
104119
FileMessage,
105120
)
121+
122+
from .operator import ( # noqa
123+
And,
124+
Or,
125+
Not
126+
)
127+
128+
from .recipient import ( # noqa
129+
AudienceRecipient
130+
)
131+
106132
from .responses import ( # noqa
107133
Profile,
108134
MemberIds,
@@ -122,6 +148,8 @@
122148
InsightDemographicResponse,
123149
InsightMessageEventResponse,
124150
BroadcastResponse,
151+
NarrowcastResponse,
152+
MessageProgressNarrowcastResponse,
125153
)
126154
from .rich_menu import ( # noqa
127155
RichMenu,

linebot/models/filter.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
"""linebot.models.filter module."""
16+
17+
from __future__ import unicode_literals
18+
19+
from abc import ABCMeta
20+
21+
from future.utils import with_metaclass
22+
23+
from .base import Base
24+
25+
26+
class Filter(with_metaclass(ABCMeta, Base)):
27+
"""Filter.
28+
29+
https://developers.line.biz/en/reference/messaging-api/#narrowcast-demographic-filter
30+
31+
A filter is the top-level structure of a demographic element.
32+
"""
33+
34+
def __init__(self, demographic=None, **kwargs):
35+
"""__init__ method.
36+
37+
:param demographic: Combination of different criteria using logical
38+
operator objects.
39+
:type demographic: :py:class:`linebot.model.DemographicFilter` |
40+
:py:class:`linebot.model.Operator`
41+
:param kwargs:
42+
"""
43+
super(Filter, self).__init__(**kwargs)
44+
45+
self.demographic = demographic
46+
47+
48+
class DemographicFilter(Filter):
49+
"""DemographicFilter.
50+
51+
https://developers.line.biz/en/reference/messaging-api/#narrowcast-demographic-filter
52+
53+
Demographic filter objects represent criteria (e.g. age, gender, OS, region,
54+
and friendship duration) on which to filter the list of recipients.
55+
You can filter recipients based on a combination of different criteria using
56+
logical operator objects.
57+
"""
58+
59+
def __init__(self, **kwargs):
60+
"""__init__ method.
61+
62+
:param kwargs:
63+
"""
64+
super(DemographicFilter, self).__init__(**kwargs)
65+
66+
self.type = None
67+
68+
69+
class GenderFilter(DemographicFilter):
70+
"""GenderFilter."""
71+
72+
def __init__(self, one_of=[], **kwargs):
73+
"""__init__ method.
74+
75+
:param one_of: Send messages to users of a given gender. One of:
76+
male: Users who identify as male
77+
female: Users who identify as female
78+
:type one_of: list[str]
79+
"""
80+
super(GenderFilter, self).__init__(**kwargs)
81+
82+
self.type = "gender"
83+
self.one_of = one_of
84+
85+
86+
class AppTypeFilter(DemographicFilter):
87+
"""AppTypeFilter."""
88+
89+
def __init__(self, one_of=[], **kwargs):
90+
"""__init__ method.
91+
92+
:param one_of: Send messages to users of the specified OS. One of:
93+
ios: Users who using iOS.
94+
android: Users who using Android.
95+
:type one_of: list[str]
96+
"""
97+
super(AppTypeFilter, self).__init__(**kwargs)
98+
99+
self.type = "appType"
100+
self.one_of = one_of
101+
102+
103+
class AreaFilter(DemographicFilter):
104+
"""AreaFilter."""
105+
106+
def __init__(self, one_of=[], **kwargs):
107+
"""__init__ method.
108+
109+
:param one_of: Send messages to users in the specified region.
110+
:type one_of: list[str]
111+
"""
112+
super(AreaFilter, self).__init__(**kwargs)
113+
114+
self.type = "area"
115+
self.one_of = one_of
116+
117+
118+
class AgeFilter(DemographicFilter):
119+
"""AgeFilter.
120+
121+
This lets you filter recipients with a given age range.
122+
"""
123+
124+
def __init__(self, gte=None, lt=None, **kwargs):
125+
"""__init__ method.
126+
127+
Be sure to specify either gte, lt, or both.
128+
129+
:param gte: Send messages to users at least as old as the specified age.
130+
:type gte: str
131+
:param lt: Send messages to users younger than the specified age.
132+
You can specify the same values as for the gte property.
133+
:type lt: str
134+
"""
135+
super(AgeFilter, self).__init__(**kwargs)
136+
137+
self.type = "age"
138+
self.gte = gte
139+
self.lt = lt
140+
141+
142+
class SubscriptionPeriodFilter(DemographicFilter):
143+
"""SubscriptionPeriodFilter.
144+
145+
This lets you filter recipients with a given range of friendship durations.
146+
"""
147+
148+
def __init__(self, gte=None, lt=None, **kwargs):
149+
"""__init__ method.
150+
151+
Be sure to specify either gte, lt, or both.
152+
153+
:param gte: Send messages to users who have been friends of yours for
154+
at least the specified number of days
155+
:type gte: str
156+
:param lt: Send messages to users who have been friends of yours for
157+
less than the specified number of days.
158+
You can specify the same values as for the gte property.
159+
:type lt: str
160+
"""
161+
super(SubscriptionPeriodFilter, self).__init__(**kwargs)
162+
163+
self.type = "subscriptionPeriod"
164+
self.gte = gte
165+
self.lt = lt

linebot/models/limit.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
"""linebot.models.recipient module."""
16+
17+
from __future__ import unicode_literals
18+
19+
from abc import ABCMeta
20+
21+
from future.utils import with_metaclass
22+
23+
from .base import Base
24+
25+
26+
class Limit(with_metaclass(ABCMeta, Base)):
27+
"""Limit.
28+
29+
https://developers.line.biz/en/reference/messaging-api/#send-narrowcast-message
30+
31+
"""
32+
33+
def __init__(self, max=None, **kwargs):
34+
"""__init__ method.
35+
36+
:param kwargs:
37+
"""
38+
super(Limit, self).__init__(**kwargs)
39+
40+
self.max = max

0 commit comments

Comments
 (0)