OSDN Git Service

no message
[simple-tornado-bot/simple-tornado-bot.git] / linebot / api.py
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.api module."""
16
17 from __future__ import unicode_literals
18
19 import json
20
21 from .__about__ import __version__
22 from .exceptions import LineBotApiError
23 from .http_client import HttpClient, RequestsHttpClient
24 from .models import (
25     Error, Profile, MemberIds, Content, RichMenuResponse
26 )
27
28
29 class LineBotApi(object):
30     """LineBotApi provides interface for LINE messaging API."""
31
32     DEFAULT_API_ENDPOINT = 'https://api.line.me'
33
34     def __init__(self, channel_access_token, endpoint=DEFAULT_API_ENDPOINT,
35                  timeout=HttpClient.DEFAULT_TIMEOUT, http_client=RequestsHttpClient):
36         """__init__ method.
37
38         :param str channel_access_token: Your channel access token
39         :param str endpoint: (optional) Default is https://api.line.me
40         :param timeout: (optional) How long to wait for the server
41             to send data before giving up, as a float,
42             or a (connect timeout, read timeout) float tuple.
43             Default is linebot.http_client.HttpClient.DEFAULT_TIMEOUT
44         :type timeout: float | tuple(float, float)
45         :param http_client: (optional) Default is
46             :py:class:`linebot.http_client.RequestsHttpClient`
47         :type http_client: T <= :py:class:`linebot.http_client.HttpClient`
48         """
49         self.endpoint = endpoint
50         self.headers = {
51             'Authorization': 'Bearer ' + channel_access_token,
52             'User-Agent': 'line-bot-sdk-python/' + __version__
53         }
54
55         if http_client:
56             self.http_client = http_client(timeout=timeout)
57         else:
58             self.http_client = RequestsHttpClient(timeout=timeout)
59
60     def reply_message(self, reply_token, messages, timeout=None):
61         """Call reply message API.
62
63         https://devdocs.line.me/en/#reply-message
64
65         Respond to events from users, groups, and rooms.
66
67         Webhooks are used to notify you when an event occurs.
68         For events that you can respond to, a replyToken is issued for replying to messages.
69
70         Because the replyToken becomes invalid after a certain period of time,
71         responses should be sent as soon as a message is received.
72
73         Reply tokens can only be used once.
74
75         :param str reply_token: replyToken received via webhook
76         :param messages: Messages.
77             Max: 5
78         :type messages: T <= :py:class:`linebot.models.send_messages.SendMessage` |
79             list[T <= :py:class:`linebot.models.send_messages.SendMessage`]
80         :param timeout: (optional) How long to wait for the server
81             to send data before giving up, as a float,
82             or a (connect timeout, read timeout) float tuple.
83             Default is self.http_client.timeout
84         :type timeout: float | tuple(float, float)
85         """
86         if not isinstance(messages, (list, tuple)):
87             messages = [messages]
88
89         data = {
90             'replyToken': reply_token,
91             'messages': [message.as_json_dict() for message in messages]
92         }
93
94         self._post(
95             '/v2/bot/message/reply', data=json.dumps(data), timeout=timeout
96         )
97
98     def push_message(self, to, messages, timeout=None):
99         """Call push message API.
100
101         https://devdocs.line.me/en/#push-message
102
103         Send messages to users, groups, and rooms at any time.
104
105         :param str to: ID of the receiver
106         :param messages: Messages.
107             Max: 5
108         :type messages: T <= :py:class:`linebot.models.send_messages.SendMessage` |
109             list[T <= :py:class:`linebot.models.send_messages.SendMessage`]
110         :param timeout: (optional) How long to wait for the server
111             to send data before giving up, as a float,
112             or a (connect timeout, read timeout) float tuple.
113             Default is self.http_client.timeout
114         :type timeout: float | tuple(float, float)
115         """
116         if not isinstance(messages, (list, tuple)):
117             messages = [messages]
118
119         data = {
120             'to': to,
121             'messages': [message.as_json_dict() for message in messages]
122         }
123
124         self._post(
125             '/v2/bot/message/push', data=json.dumps(data), timeout=timeout
126         )
127
128     def multicast(self, to, messages, timeout=None):
129         """Call multicast API.
130
131         https://devdocs.line.me/en/#multicast
132
133         Send messages to multiple users at any time.
134
135         :param to: IDs of the receivers
136             Max: 150 users
137         :type to: list[str]
138         :param messages: Messages.
139             Max: 5
140         :type messages: T <= :py:class:`linebot.models.send_messages.SendMessage` |
141             list[T <= :py:class:`linebot.models.send_messages.SendMessage`]
142         :param timeout: (optional) How long to wait for the server
143             to send data before giving up, as a float,
144             or a (connect timeout, read timeout) float tuple.
145             Default is self.http_client.timeout
146         :type timeout: float | tuple(float, float)
147         """
148         if not isinstance(messages, (list, tuple)):
149             messages = [messages]
150
151         data = {
152             'to': to,
153             'messages': [message.as_json_dict() for message in messages]
154         }
155
156         self._post(
157             '/v2/bot/message/multicast', data=json.dumps(data), timeout=timeout
158         )
159
160     def get_profile(self, user_id, timeout=None):
161         """Call get profile API.
162
163         https://devdocs.line.me/en/#bot-api-get-profile
164
165         Get user profile information.
166
167         :param str user_id: User ID
168         :param timeout: (optional) How long to wait for the server
169             to send data before giving up, as a float,
170             or a (connect timeout, read timeout) float tuple.
171             Default is self.http_client.timeout
172         :type timeout: float | tuple(float, float)
173         :rtype: :py:class:`linebot.models.responses.Profile`
174         :return: Profile instance
175         """
176         response = self._get(
177             '/v2/bot/profile/{user_id}'.format(user_id=user_id),
178             timeout=timeout
179         )
180
181         return Profile.new_from_json_dict(response.json)
182
183     def get_group_member_profile(self, group_id, user_id, timeout=None):
184         """Call get group member profile API.
185
186         https://devdocs.line.me/en/#get-group-room-member-profile
187
188         Gets the user profile of a member of a group that
189         the bot is in. This can be the user ID of a user who has
190         not added the bot as a friend or has blocked the bot.
191
192         :param str group_id: Group ID
193         :param str user_id: User ID
194         :param timeout: (optional) How long to wait for the server
195             to send data before giving up, as a float,
196             or a (connect timeout, read timeout) float tuple.
197             Default is self.http_client.timeout
198         :type timeout: float | tuple(float, float)
199         :rtype: :py:class:`linebot.models.responses.Profile`
200         :return: Profile instance
201         """
202         response = self._get(
203             '/v2/bot/group/{group_id}/member/{user_id}'.format(group_id=group_id, user_id=user_id),
204             timeout=timeout
205         )
206
207         return Profile.new_from_json_dict(response.json)
208
209     def get_room_member_profile(self, room_id, user_id, timeout=None):
210         """Call get room member profile API.
211
212         https://devdocs.line.me/en/#get-group-room-member-profile
213
214         Gets the user profile of a member of a room that
215         the bot is in. This can be the user ID of a user who has
216         not added the bot as a friend or has blocked the bot.
217
218         :param str room_id: Room ID
219         :param str user_id: User ID
220         :param timeout: (optional) How long to wait for the server
221             to send data before giving up, as a float,
222             or a (connect timeout, read timeout) float tuple.
223             Default is self.http_client.timeout
224         :type timeout: float | tuple(float, float)
225         :rtype: :py:class:`linebot.models.responses.Profile`
226         :return: Profile instance
227         """
228         response = self._get(
229             '/v2/bot/room/{room_id}/member/{user_id}'.format(room_id=room_id, user_id=user_id),
230             timeout=timeout
231         )
232
233         return Profile.new_from_json_dict(response.json)
234
235     def get_group_member_ids(self, group_id, start=None, timeout=None):
236         """Call get group member IDs API.
237
238         https://devdocs.line.me/en/#get-group-room-member-ids
239
240         Gets the user IDs of the members of a group that the bot is in.
241         This includes the user IDs of users who have not added the bot as a friend
242         or has blocked the bot.
243
244         :param str group_id: Group ID
245         :param str start: continuationToken
246         :param timeout: (optional) How long to wait for the server
247             to send data before giving up, as a float,
248             or a (connect timeout, read timeout) float tuple.
249             Default is self.http_client.timeout
250         :type timeout: float | tuple(float, float)
251         :rtype: :py:class:`linebot.models.responses.MemberIds`
252         :return: MemberIds instance
253         """
254         params = None if start is None else {'start': start}
255
256         response = self._get(
257             '/v2/bot/group/{group_id}/members/ids'.format(group_id=group_id),
258             params=params,
259             timeout=timeout
260         )
261
262         return MemberIds.new_from_json_dict(response.json)
263
264     def get_room_member_ids(self, room_id, start=None, timeout=None):
265         """Call get room member IDs API.
266
267         https://devdocs.line.me/en/#get-group-room-member-ids
268
269         Gets the user IDs of the members of a group that the bot is in.
270         This includes the user IDs of users who have not added the bot as a friend
271         or has blocked the bot.
272
273         :param str room_id: Room ID
274         :param str start: continuationToken
275         :param timeout: (optional) How long to wait for the server
276             to send data before giving up, as a float,
277             or a (connect timeout, read timeout) float tuple.
278             Default is self.http_client.timeout
279         :type timeout: float | tuple(float, float)
280         :rtype: :py:class:`linebot.models.responses.MemberIds`
281         :return: MemberIds instance
282         """
283         params = None if start is None else {'start': start}
284
285         response = self._get(
286             '/v2/bot/room/{room_id}/members/ids'.format(room_id=room_id),
287             params=params,
288             timeout=timeout
289         )
290
291         return MemberIds.new_from_json_dict(response.json)
292
293     def get_message_content(self, message_id, timeout=None):
294         """Call get content API.
295
296         https://devdocs.line.me/en/#get-content
297
298         Retrieve image, video, and audio data sent by users.
299
300         :param str message_id: Message ID
301         :param timeout: (optional) How long to wait for the server
302             to send data before giving up, as a float,
303             or a (connect timeout, read timeout) float tuple.
304             Default is self.http_client.timeout
305         :type timeout: float | tuple(float, float)
306         :rtype: :py:class:`linebot.models.responses.Content`
307         :return: Content instance
308         """
309         response = self._get(
310             '/v2/bot/message/{message_id}/content'.format(message_id=message_id),
311             stream=True, timeout=timeout
312         )
313
314         return Content(response)
315
316     def leave_group(self, group_id, timeout=None):
317         """Call leave group API.
318
319         https://devdocs.line.me/en/#leave
320
321         Leave a group.
322
323         :param str group_id: Group ID
324         :param timeout: (optional) How long to wait for the server
325             to send data before giving up, as a float,
326             or a (connect timeout, read timeout) float tuple.
327             Default is self.http_client.timeout
328         :type timeout: float | tuple(float, float)
329         """
330         self._post(
331             '/v2/bot/group/{group_id}/leave'.format(group_id=group_id),
332             timeout=timeout
333         )
334
335     def leave_room(self, room_id, timeout=None):
336         """Call leave room API.
337
338         https://devdocs.line.me/en/#leave
339
340         Leave a room.
341
342         :param str room_id: Room ID
343         :param timeout: (optional) How long to wait for the server
344             to send data before giving up, as a float,
345             or a (connect timeout, read timeout) float tuple.
346             Default is self.http_client.timeout
347         :type timeout: float | tuple(float, float)
348         """
349         self._post(
350             '/v2/bot/room/{room_id}/leave'.format(room_id=room_id),
351             timeout=timeout
352         )
353
354     def get_rich_menu(self, rich_menu_id, timeout=None):
355         """Call get rich menu API.
356
357         https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu
358
359         :param str rich_menu_id: ID of the rich menu
360         :param timeout: (optional) How long to wait for the server
361             to send data before giving up, as a float,
362             or a (connect timeout, read timeout) float tuple.
363             Default is self.http_client.timeout
364         :type timeout: float | tuple(float, float)
365         :rtype: :py:class:`linebot.models.responses.RichMenuResponse`
366         :return: RichMenuResponse instance
367         """
368         response = self._get(
369             '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
370             timeout=timeout
371         )
372
373         return RichMenuResponse.new_from_json_dict(response.json)
374
375     def create_rich_menu(self, rich_menu, timeout=None):
376         """Call create rich menu API.
377
378         https://developers.line.me/en/docs/messaging-api/reference/#create-rich-menu
379
380         :param rich_menu: Inquired to create a rich menu object.
381         :type rich_menu: T <= :py:class:`linebot.models.rich_menu.RichMenu`
382         :param timeout: (optional) How long to wait for the server
383             to send data before giving up, as a float,
384             or a (connect timeout, read timeout) float tuple.
385             Default is self.http_client.timeout
386         :type timeout: float | tuple(float, float)
387         :rtype: str
388         :return: rich menu id
389         """
390         response = self._post(
391             '/v2/bot/richmenu', data=rich_menu.as_json_string(), timeout=timeout
392         )
393
394         return response.json.get('richMenuId')
395
396     def delete_rich_menu(self, rich_menu_id, timeout=None):
397         """Call delete rich menu API.
398
399         https://developers.line.me/en/docs/messaging-api/reference/#delete-rich-menu
400
401         :param str rich_menu_id: ID of an uploaded rich menu
402         :param timeout: (optional) How long to wait for the server
403             to send data before giving up, as a float,
404             or a (connect timeout, read timeout) float tuple.
405             Default is self.http_client.timeout
406         :type timeout: float | tuple(float, float)
407         """
408         self._delete(
409             '/v2/bot/richmenu/{rich_menu_id}'.format(rich_menu_id=rich_menu_id),
410             timeout=timeout
411         )
412
413     def get_rich_menu_id_of_user(self, user_id, timeout=None):
414         """Call get rich menu ID of user API.
415
416         https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-id-of-user
417
418         :param str user_id: IDs of the user
419         :param timeout: (optional) How long to wait for the server
420             to send data before giving up, as a float,
421             or a (connect timeout, read timeout) float tuple.
422             Default is self.http_client.timeout
423         :type timeout: float | tuple(float, float)
424         :rtype: str
425         :return: rich menu id
426         """
427         response = self._get(
428             '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
429             timeout=timeout
430         )
431
432         return response.json.get('richMenuId')
433
434     def link_rich_menu_to_user(self, user_id, rich_menu_id, timeout=None):
435         """Call link rich menu to user API.
436
437         https://developers.line.me/en/docs/messaging-api/reference/#link-rich-menu-to-user
438
439         :param str user_id: ID of an uploaded rich menu
440         :param str rich_menu_id: ID of the user
441         :type timeout: float | tuple(float, float)
442         """
443         self._post(
444             '/v2/bot/user/{user_id}/richmenu/{rich_menu_id}'.format(
445                 user_id=user_id,
446                 rich_menu_id=rich_menu_id
447             ),
448             timeout=timeout
449         )
450
451     def unlink_rich_menu_from_user(self, user_id, timeout=None):
452         """Call unlink rich menu from user API.
453
454         https://developers.line.me/en/docs/messaging-api/reference/#unlink-rich-menu-from-user
455
456         :param str user_id: ID of the user
457         :param timeout: (optional) How long to wait for the server
458             to send data before giving up, as a float,
459             or a (connect timeout, read timeout) float tuple.
460             Default is self.http_client.timeout
461         :type timeout: float | tuple(float, float)
462         """
463         self._delete(
464             '/v2/bot/user/{user_id}/richmenu'.format(user_id=user_id),
465             timeout=timeout
466         )
467
468     def get_rich_menu_image(self, rich_menu_id, timeout=None):
469         """Call download rich menu image API.
470
471         https://developers.line.me/en/docs/messaging-api/reference/#download-rich-menu-image
472
473         :param str rich_menu_id: ID of the rich menu with the image to be downloaded
474         :param timeout: (optional) How long to wait for the server
475             to send data before giving up, as a float,
476             or a (connect timeout, read timeout) float tuple.
477             Default is self.http_client.timeout
478         :type timeout: float | tuple(float, float)
479         :rtype: :py:class:`linebot.models.responses.Content`
480         :return: Content instance
481         """
482         response = self._get(
483             '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
484             timeout=timeout
485         )
486
487         return Content(response)
488
489     def set_rich_menu_image(self, rich_menu_id, content_type, content, timeout=None):
490         """Call upload rich menu image API.
491
492         https://developers.line.me/en/docs/messaging-api/reference/#upload-rich-menu-image
493
494         Uploads and attaches an image to a rich menu.
495
496         :param str rich_menu_id: IDs of the richmenu
497         :param str content_type: image/jpeg or image/png
498         :param content: image content as bytes, or file-like object
499         :param timeout: (optional) How long to wait for the server
500             to send data before giving up, as a float,
501             or a (connect timeout, read timeout) float tuple.
502             Default is self.http_client.timeout
503         :type timeout: float | tuple(float, float)
504         """
505         self._post(
506             '/v2/bot/richmenu/{rich_menu_id}/content'.format(rich_menu_id=rich_menu_id),
507             data=content,
508             headers={'Content-Type': content_type},
509             timeout=timeout
510         )
511
512     def get_rich_menu_list(self, timeout=None):
513         """Call get rich menu list API.
514
515         https://developers.line.me/en/docs/messaging-api/reference/#get-rich-menu-list
516
517         :param timeout: (optional) How long to wait for the server
518             to send data before giving up, as a float,
519             or a (connect timeout, read timeout) float tuple.
520             Default is self.http_client.timeout
521         :type timeout: float | tuple(float, float)
522         :rtype: list(T <= :py:class:`linebot.models.reponse.RichMenuResponse`)
523         :return: list[RichMenuResponse] instance
524         """
525         response = self._get(
526             '/v2/bot/richmenu/list',
527             timeout=timeout
528         )
529
530         result = []
531         for richmenu in response.json['richmenus']:
532             result.append(RichMenuResponse.new_from_json_dict(richmenu))
533
534         return result
535
536     def _get(self, path, params=None, headers=None, stream=False, timeout=None):
537         url = self.endpoint + path
538
539         if headers is None:
540             headers = {}
541         headers.update(self.headers)
542
543         response = self.http_client.get(
544             url, headers=headers, params=params, stream=stream, timeout=timeout
545         )
546
547         self.__check_error(response)
548         return response
549
550     def _post(self, path, data=None, headers=None, timeout=None):
551         url = self.endpoint + path
552
553         if headers is None:
554             headers = {'Content-Type': 'application/json'}
555         headers.update(self.headers)
556
557         response = self.http_client.post(
558             url, headers=headers, data=data, timeout=timeout
559         )
560
561         self.__check_error(response)
562         return response
563
564     def _delete(self, path, data=None, headers=None, timeout=None):
565         url = self.endpoint + path
566
567         if headers is None:
568             headers = {}
569         headers.update(self.headers)
570
571         response = self.http_client.delete(
572             url, headers=headers, data=data, timeout=timeout
573         )
574
575         self.__check_error(response)
576         return response
577
578     @staticmethod
579     def __check_error(response):
580         if 200 <= response.status_code < 300:
581             pass
582         else:
583             error = Error.new_from_json_dict(response.json)
584             raise LineBotApiError(response.status_code, error)