aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenz Diener <[email protected]>2017-11-24 15:08:34 +0100
committerLorenz Diener <[email protected]>2017-11-24 15:08:34 +0100
commite220e7cc60839ee1e3b27781b3b1cb609e593f85 (patch)
tree0575d9a30ad250247f7b3bb171cedfb0d4e8af60
parentcea4d4251a0b998ae734811ee78651d60a138d3e (diff)
downloadmastodon.py-e220e7cc60839ee1e3b27781b3b1cb609e593f85.tar.gz
Many fixes for streaming stuff
-rw-r--r--docs/index.rst11
-rw-r--r--mastodon/Mastodon.py26
-rw-r--r--mastodon/__init__.py4
-rw-r--r--mastodon/streaming.py44
4 files changed, 51 insertions, 34 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 162d06c..63a8594 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -37,7 +37,7 @@ Mastodon.py
37 ) 37 )
38 mastodon.toot('Tooting from python using #mastodonpy !') 38 mastodon.toot('Tooting from python using #mastodonpy !')
39 39
40`Mastodon`_ is an ostatus based twitter-like federated social 40`Mastodon`_ is an ActivityPub and OStatus based twitter-like federated social
41network node. It has an API that allows you to interact with its 41network node. It has an API that allows you to interact with its
42every aspect. This is a simple python wrapper for that api, provided 42every aspect. This is a simple python wrapper for that api, provided
43as a single python module. By default, it talks to the 43as a single python module. By default, it talks to the
@@ -531,11 +531,18 @@ Streaming
531--------- 531---------
532These functions allow access to the streaming API. 532These functions allow access to the streaming API.
533 533
534If async is False, these methods block forever (or until an
535exception is raised).
536
537If async is True, the listener will listen on another thread and these methods
538will return a handle corresponding to the open connection. The
539connection may be closed at any time by calling its close() method.
540
534.. automethod:: Mastodon.user_stream 541.. automethod:: Mastodon.user_stream
535.. automethod:: Mastodon.public_stream 542.. automethod:: Mastodon.public_stream
543.. automethod:: Mastodon.local_stream
536.. automethod:: Mastodon.hashtag_stream 544.. automethod:: Mastodon.hashtag_stream
537 545
538
539.. _Mastodon: https://github.com/tootsuite/mastodon 546.. _Mastodon: https://github.com/tootsuite/mastodon
540.. _Mastodon flagship instance: http://mastodon.social/ 547.. _Mastodon flagship instance: http://mastodon.social/
541.. _Mastodon api docs: https://github.com/tootsuite/documentation/ 548.. _Mastodon api docs: https://github.com/tootsuite/documentation/
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index c35ad2d..9b28861 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -17,10 +17,11 @@ import re
17import copy 17import copy
18import threading 18import threading
19import sys 19import sys
20
20try: 21try:
21 from urllib.parse import urlparse 22 from urllib.parse import urlparse
22except ImportError: 23except ImportError:
23 from urlparse import urlparse 24 from urlparse import urlparse
24 25
25 26
26class Mastodon: 27class Mastodon:
@@ -1014,12 +1015,6 @@ class Mastodon:
1014 Streams events that are relevant to the authorized user, i.e. home 1015 Streams events that are relevant to the authorized user, i.e. home
1015 timeline and notifications. 'listener' should be a subclass of 1016 timeline and notifications. 'listener' should be a subclass of
1016 StreamListener which will receive callbacks for incoming events. 1017 StreamListener which will receive callbacks for incoming events.
1017
1018 If async is False, this method blocks forever.
1019
1020 If async is True, 'listener' will listen on another thread and this method
1021 will return a handle corresponding to the open connection. The
1022 connection may be closed at any time by calling its close() method.
1023 """ 1018 """
1024 return self.__stream('/api/v1/streaming/user', listener, async=async) 1019 return self.__stream('/api/v1/streaming/user', listener, async=async)
1025 1020
@@ -1027,12 +1022,6 @@ class Mastodon:
1027 """ 1022 """
1028 Streams public events. 'listener' should be a subclass of StreamListener 1023 Streams public events. 'listener' should be a subclass of StreamListener
1029 which will receive callbacks for incoming events. 1024 which will receive callbacks for incoming events.
1030
1031 If async is False, this method blocks forever.
1032
1033 If async is True, 'listener' will listen on another thread and this method
1034 will return a handle corresponding to the open connection. The
1035 connection may be closed at any time by calling its close() method.
1036 """ 1025 """
1037 return self.__stream('/api/v1/streaming/public', listener, async=async) 1026 return self.__stream('/api/v1/streaming/public', listener, async=async)
1038 1027
@@ -1041,11 +1030,6 @@ class Mastodon:
1041 Streams local events. 'listener' should be a subclass of StreamListener 1030 Streams local events. 'listener' should be a subclass of StreamListener
1042 which will receive callbacks for incoming events. 1031 which will receive callbacks for incoming events.
1043 1032
1044 If async is False, this method blocks forever.
1045
1046 If async is True, 'listener' will listen on another thread and this method
1047 will return a handle corresponding to the open connection. The
1048 connection may be closed at any time by calling its close() method.
1049 """ 1033 """
1050 return self.__stream('/api/v1/streaming/public/local', listener, async=async) 1034 return self.__stream('/api/v1/streaming/public/local', listener, async=async)
1051 1035
@@ -1054,12 +1038,6 @@ class Mastodon:
1054 Returns all public statuses for the hashtag 'tag'. 'listener' should be 1038 Returns all public statuses for the hashtag 'tag'. 'listener' should be
1055 a subclass of StreamListener which will receive callbacks for incoming 1039 a subclass of StreamListener which will receive callbacks for incoming
1056 events. 1040 events.
1057
1058 If async is False, this method blocks forever.
1059
1060 If async is True, 'listener' will listen on another thread and this method
1061 will return a handle corresponding to the open connection. The
1062 connection may be closed at any time by calling its close() method.
1063 """ 1041 """
1064 return self.__stream("/api/v1/streaming/hashtag?tag={}".format(tag), listener) 1042 return self.__stream("/api/v1/streaming/hashtag?tag={}".format(tag), listener)
1065 1043
diff --git a/mastodon/__init__.py b/mastodon/__init__.py
index 3123356..fdf776d 100644
--- a/mastodon/__init__.py
+++ b/mastodon/__init__.py
@@ -1,4 +1,4 @@
1from mastodon.Mastodon import Mastodon 1from mastodon.Mastodon import Mastodon
2from mastodon.streaming import StreamListener 2from mastodon.streaming import StreamListener, CallbackStreamListener
3 3
4__all__ = ['Mastodon', 'StreamListener'] 4__all__ = ['Mastodon', 'StreamListener', 'CallbackStreamListener']
diff --git a/mastodon/streaming.py b/mastodon/streaming.py
index cac2456..92a02dc 100644
--- a/mastodon/streaming.py
+++ b/mastodon/streaming.py
@@ -67,10 +67,6 @@ class StreamListener(object):
67 else: 67 else:
68 event[key] = value 68 event[key] = value
69 69
70 # end of stream
71 if event:
72 log.warn("outstanding partial event at end of stream: %s", event)
73
74 def _dispatch(self, event): 70 def _dispatch(self, event):
75 try: 71 try:
76 name = event['event'] 72 name = event['event']
@@ -92,8 +88,44 @@ class StreamListener(object):
92 handler_name = 'on_' + name 88 handler_name = 'on_' + name
93 try: 89 try:
94 handler = getattr(self, handler_name) 90 handler = getattr(self, handler_name)
95 except AttributeError: 91 except AttributeError as err:
96 log.warn("Unhandled event '%s'", name) 92 six.raise_from(
93 MastodonMalformedEventError('Bad event type', name),
94 err
95 )
97 else: 96 else:
98 # TODO: allow handlers to return/raise to stop streaming cleanly 97 # TODO: allow handlers to return/raise to stop streaming cleanly
99 handler(payload) 98 handler(payload)
99
100class CallbackStreamListener(StreamListener):
101 """
102 Simple callback stream handler class.
103 Can optionally additionally send local update events to a separate handler.
104 """
105 def __init__(self, update_handler = None, local_update_handler = None, delete_handler = None, notification_handler = None):
106 super(CallbackStreamListener, self).__init__()
107 self.update_handler = update_handler
108 self.local_update_handler = local_update_handler
109 self.delete_handler = delete_handler
110 self.notification_handler = notification_handler
111
112 def on_update(self, status):
113 if self.update_handler != None:
114 self.update_handler(status)
115
116 try:
117 if self.local_update_handler != None and not "@" in status["account"]["acct"]:
118 self.local_update_handler(status)
119 except Exception as err:
120 six.raise_from(
121 MastodonMalformedEventError('received bad update', status),
122 err
123 )
124
125 def on_delete(self, deleted_id):
126 if self.delete_handler != None:
127 self.delete_handler(deleted_id)
128
129 def on_notification(self, notification):
130 if self.notification_handler != None:
131 self.notification_handler(notification) \ No newline at end of file
Powered by cgit v1.2.3 (git 2.41.0)