Skip to content

Commit d941a6f

Browse files
committed
Add some docs and various additions.
1 parent fbecbf3 commit d941a6f

File tree

1 file changed

+123
-10
lines changed

1 file changed

+123
-10
lines changed

twitchio/ext/overlays/core.py

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333
import zlib
3434
from typing import TYPE_CHECKING, Any, ClassVar, Literal, Self, overload
3535

36+
from twitchio import Colour
37+
3638
from .enums import Animation, AnimationSpeed, EventPosition, Font
37-
from .exceptions import BlueprintError
39+
from .exceptions import AudioAlreadyLoadedError, BlueprintError
3840

3941

4042
if TYPE_CHECKING:
@@ -55,16 +57,65 @@ def __init__(self) -> None:
5557
self._raw: OverlayEventT = {
5658
"parts": [],
5759
"audio": "",
58-
"duration": 800000,
60+
"duration": 5000,
5961
"duration_is_audio": False,
6062
"force_override": False,
61-
"stack_event": True,
63+
"stack_event": False,
6264
}
6365

6466
def escape(self, value: str, /) -> str:
67+
"""Method which escapes the provided the content via the ``html`` standard library.
68+
69+
Parameters
70+
----------
71+
value: str
72+
The content to escape.
73+
74+
Returns
75+
-------
76+
str
77+
The escaped content.
78+
"""
6579
return html.escape(value)
6680

67-
def add_html(self) -> Self: ...
81+
def add_html(
82+
self,
83+
html: str,
84+
animation: Animation | None = None,
85+
animation_speed: AnimationSpeed | None = None,
86+
) -> Self:
87+
"""Method to add a custom HTML segment to this event.
88+
89+
.. important::
90+
91+
This method is unsafe and care should be taken to ensure that the input is trusted. The input provided to this
92+
method will **NOT** be escaped and could be used to inject scripts into the Javascript of the overlay.
93+
94+
.. warning::
95+
96+
We do not recommend using this method if any of the input comes from a third-party or external source; including
97+
chatters or other API's.
98+
99+
Parameters
100+
----------
101+
html: str
102+
The ``HTML`` to use as a segment for this event. Ensure the content provided to this parameter is trusted.
103+
animation: :class:`~twitchio.ext.overlays.Animation` | ``None``
104+
An optional animation to apply to the provided HTML content. Defaults to ``None``.
105+
animation_speed: :class:`~twitchio.ext.overlays.AnimationSpeed` | ``None``
106+
An optional speed of animation to provide. Defaults to ``None`` which is the default speed.
107+
108+
Returns
109+
-------
110+
OverlayEvent
111+
This method returns ``self`` which allows for fluid-style chaining.
112+
"""
113+
middle = f" animate__{animation.value}" if animation else ""
114+
speed = f" animate__{animation_speed.value}" if animation_speed else ""
115+
part: OverlayPartT = {"content": html, "animation": middle, "speed": speed}
116+
117+
self._raw["parts"].append(part)
118+
return self
68119

69120
def add_text(
70121
self,
@@ -74,28 +125,76 @@ def add_text(
74125
animation_speed: AnimationSpeed | None = None,
75126
font: Font | None = None, # TODO: Default Font...
76127
size: int = 24,
128+
colour: Colour | None = None,
77129
) -> Self:
78-
# TODO: Font...
130+
"""Method to add custom text content as a segement to this event.
131+
132+
.. note::
133+
134+
The text content provided to this method is escaped via :meth:`.escape`.
135+
136+
Parameters
137+
----------
138+
content: str
139+
The text content to use as a segment for this event. This content will be escaped.
140+
animation: :class:`~twitchio.ext.overlays.Animation` | ``None``
141+
An optional animation to apply to the provided text content. Defaults to ``None``.
142+
animation_speed: :class:`~twitchio.ext.overlays.AnimationSpeed` | ``None``
143+
An optional speed of animation to provide. Defaults to ``None`` which is the default speed.
144+
font: :class:`~twitchio.ext.overlays.Font` | ``None``
145+
...
146+
size: int
147+
An optional :class:`int` which is the size of the font in `px`. Defaults to ``24``.
148+
colour: :class:`twitchio.Colour`
149+
An optional :class:`twitchio.Colour` or :class:`twitchio.Color` to use for the text. Defaults to ``None``, which
150+
will be ``black`` / ``#000000``.
151+
152+
Returns
153+
-------
154+
OverlayEvent
155+
This method returns ``self`` which allows for fluid-style chaining.
156+
"""
79157

80158
if not isinstance(size, int): # pyright: ignore[reportUnnecessaryIsInstance]
81159
raise TypeError(f"Parameter 'size' expected 'int' got {type(size)!r}.")
82160

83161
escaped = self.escape(content)
84162
middle = f" animate__{animation.value}" if animation else ""
85163
speed = f" animate__{animation_speed.value}" if animation_speed else ""
164+
col = colour or Colour.from_hex("#000000")
86165

87-
part: OverlayPartT = {"content": escaped, "animation": middle, "speed": speed, "size": size}
166+
part: OverlayPartT = {"content": escaped, "animation": middle, "speed": speed, "size": size, "colour": col.html}
88167
self._raw["parts"].append(part)
89168

90169
return self
91170

92171
def add_image(self) -> Self: ...
93172

94-
def set_audio(self) -> Self: ...
173+
def set_audio(self, name: str, /) -> Self: ...
174+
175+
def set_duration(self, value: int | None = 5000, *, as_audio: bool = False) -> Self:
176+
"""Method which sets the overall duration of this overlay event.
177+
178+
Parameters
179+
----------
180+
value: int | None
181+
The duration of the event in ``ms (milliseconds)`` as an :class:`int`. Could be ``None`` which would mean the
182+
event will not be removed from the overlay until another condition is met, such as a new event overriding it.
183+
Defaults to ``5000`` (5 seconds).
184+
as_audio: bool
185+
An optional bool which when set will ensure the event lasts for as long as any audio provided does. If a duration
186+
is provided when this parameter is set to ``True``, the duration will be additive. Defaults to ``False``.
187+
188+
Returns
189+
-------
190+
OverlayEvent
191+
This method returns ``self`` which allows for fluid-style chaining.
192+
"""
193+
duration = max(0, value or 0) or None
194+
self._raw["duration"] = duration
195+
self._raw["duration_is_audio"] = as_audio
95196

96-
def set_position(self) -> Self: ...
97-
98-
def set_duration(self, value: int, *, as_audio: bool = False) -> Self: ...
197+
return self
99198

100199
@overload
101200
def _compress(self, convert: Literal[True] = True) -> str: ...
@@ -140,6 +239,13 @@ def to_blueprint(self) -> str:
140239
return self._compress()
141240

142241
def as_dict(self) -> OverlayEventT:
242+
"""Method which does a deep-copy on the raw data and returns it as a dictionary.
243+
244+
Returns
245+
-------
246+
dict
247+
The raw data for this event.
248+
"""
143249
return copy.deepcopy(self._raw)
144250

145251

@@ -177,6 +283,7 @@ def __new__(cls, *args: Any, **Kwargs: Any) -> Self:
177283
def __init__(self, *, secret: str) -> None:
178284
self._secret = secret
179285
self._position = EventPosition.center
286+
self._audio_paths: dict[str, os.PathLike[str]] = {}
180287

181288
@property
182289
def secret(self) -> str:
@@ -260,6 +367,12 @@ def set_position(self, position: EventPosition, /) -> Self:
260367
self._position = position
261368
return self
262369

370+
async def mount_audio(self, name: str, *, path: os.PathLike[str]) -> ...:
371+
if name in self._audio_paths:
372+
raise AudioAlreadyLoadedError(f"Audio with the name '{name}' has already been added to {self!r}.")
373+
374+
self._audio_paths[name] = path
375+
263376
def generate_html(self) -> str:
264377
template = self.template
265378
js = self.javascript

0 commit comments

Comments
 (0)