4141
4242
4343class AutoPoster (DataContainerMixin ):
44+ """
45+ A helper class for autoposting. Takes in a :obj:`~.client.DBLClient` to instantiate.
46+
47+ Parameters
48+ ----------
49+ client: :obj:`~.client.DBLClient`
50+ An instance of DBLClient.
51+ """
52+
4453 __slots__ = (
4554 "_error" ,
4655 "_success" ,
@@ -79,6 +88,27 @@ def on_success(self, callback: CallbackT) -> "AutoPoster":
7988 ...
8089
8190 def on_success (self , callback : t .Any = None ) -> t .Any :
91+ """
92+ Registers an autopost success callback. The callback can be either sync or async.
93+ This method can be used as a decorator or a decorator factory.
94+
95+ Example
96+ -------
97+ .. code-block:: python
98+
99+ # The following are valid.
100+ autopost = dblclient.autopost().on_success(lambda: print("Success!"))
101+
102+ # Used as decorator, the decorated function will become the AutoPoster object.
103+ @autopost.on_success
104+ def autopost():
105+ ...
106+
107+ # Used as decorator factory, the decorated function will still be the function itself.
108+ @autopost.on_success()
109+ def on_success():
110+ ...
111+ """
82112 if callback is not None :
83113 self ._success = callback
84114 return self
@@ -94,6 +124,30 @@ def on_error(self, callback: CallbackT) -> "AutoPoster":
94124 ...
95125
96126 def on_error (self , callback : t .Any = None ) -> t .Any :
127+ """
128+ Registers an autopost error callback. The callback can be either sync or async.
129+ This method can be used as a decorator or a decorator factory.
130+
131+ .. note::
132+ If you don't provide an error callback, the default error handler will be called.
133+
134+ Example
135+ -------
136+ .. code-block:: python
137+
138+ # The following are valid.
139+ autopost = dblclient.autopost().on_error(lambda exc: print("Failed posting stats!", exc))
140+
141+ # Used as decorator, the decorated function will become the AutoPoster object.
142+ @autopost.on_error
143+ def autopost(exc: Exception):
144+ ...
145+
146+ # Used as decorator factory, the decorated function will still be the function itself.
147+ @autopost.on_error()
148+ def on_error(exc: Exception):
149+ ...
150+ """
97151 if callback is not None :
98152 self ._error = callback # type: ignore
99153 return self
@@ -109,6 +163,32 @@ def stats(self, callback: StatsCallbackT) -> "AutoPoster":
109163 ...
110164
111165 def stats (self , callback : t .Any = None ) -> t .Any :
166+ """
167+ Registers a function that returns an instance of :obj:`~.types.StatsWrapper`. The callback can be either sync or async.
168+ This method can be used as a decorator or a decorator factory.
169+
170+ Example
171+ -------
172+ .. code-block:: python
173+
174+ import topgg
175+
176+ # In this example, we fetch the stats from a Discord client instance.
177+ client = Client(...)
178+ dblclient = topgg.DBLClient(TOKEN).set_data(client)
179+ autopost = (
180+ dblclient
181+ .autopost()
182+ .on_success(lambda: print("Successfully posted the stats!")
183+ )
184+
185+ @autopost.stats()
186+ def get_stats(client: Client = topgg.data(Client)):
187+ return topgg.StatsWrapper(guild_count=len(client.guilds), shard_count=len(client.shards))
188+
189+ # somewhere after the event loop has started
190+ autopost.start()
191+ """
112192 if callback is not None :
113193 self ._stats = callback
114194 return self
@@ -117,13 +197,27 @@ def stats(self, callback: t.Any = None) -> t.Any:
117197
118198 @property
119199 def interval (self ) -> float :
200+ """The interval between posting stats."""
120201 return self ._interval
121202
122203 @interval .setter
123204 def interval (self , seconds : t .Union [float , datetime .timedelta ]) -> None :
205+ """Alias to :meth:`~.autopost.AutoPoster.set_interval`"""
124206 self .set_interval (seconds )
125207
126208 def set_interval (self , seconds : t .Union [float , datetime .timedelta ]) -> "AutoPoster" :
209+ """
210+ Sets the interval between posting stats.
211+
212+ Parameters
213+ ----------
214+ seconds: :obj:`float` or :obj:`datetime.timedelta`
215+
216+ Raises
217+ ------
218+ :obj:`ValueError`:
219+ If the provided interval is less than 900 seconds.
220+ """
127221 if isinstance (seconds , datetime .timedelta ):
128222 seconds = seconds .total_seconds ()
129223
@@ -135,6 +229,7 @@ def set_interval(self, seconds: t.Union[float, datetime.timedelta]) -> "AutoPost
135229
136230 @property
137231 def is_running (self ) -> bool :
232+ """Whether or not the autopost is running."""
138233 return self ._task is not None and self ._task .done ()
139234
140235 async def _internal_loop (self ) -> None :
@@ -161,6 +256,17 @@ async def _internal_loop(self) -> None:
161256 self ._task = None
162257
163258 def start (self ) -> "asyncio.Task[None]" :
259+ """
260+ Starts the autoposting loop.
261+
262+ .. note::
263+ This method must be called when the event loop has already running!
264+
265+ Raises
266+ ------
267+ :obj:`~.errors.TopGGException`:
268+ If there's no callback provided or the autopost is already running.
269+ """
164270 if not hasattr (self , "_stats" ):
165271 raise errors .TopGGException (
166272 "you must provide a callback that returns the stats."
@@ -173,10 +279,24 @@ def start(self) -> "asyncio.Task[None]":
173279 return task
174280
175281 def stop (self ) -> None :
282+ """
283+ Stops the autoposting loop.
284+
285+ .. note::
286+ This differs from :meth:`~.autopost.AutoPoster.cancel`
287+ because this will stop after posting as opposed to cancel immediately.
288+ """
176289 self ._stopping = True
177290 return None
178291
179292 def cancel (self ) -> None :
293+ """
294+ Cancels the autoposting loop.
295+
296+ .. note::
297+ This differs from :meth:`~.autopost.AutoPoster.stop`
298+ because this will stop the loop right away.
299+ """
180300 if self ._task is None :
181301 return
182302
0 commit comments