Skip to content

cocorum.basehandles

This module provides abstract classes for both API JSON and HTML wrappers, with methods that are common to both. This library does not contain any classes or functions meant to be used directly.

Base handles

Abstract classes for objects with methods that are common between API and HTML versions

Copyright 2025 Wilbur Jaywright.

This file is part of Cocorum.

Cocorum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Cocorum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with Cocorum. If not, see https://www.gnu.org/licenses/.

S.D.G.

BaseComment

A comment on a Rumble video

Source code in cocorum/basehandles.py
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class BaseComment:
    """A comment on a Rumble video"""
    def __int__(self):
        """The comment in integer form (its ID)"""
        return self.comment_id

    def __str__(self):
        """The comment as a string (its text)"""
        return self.text

    @property
    def comment_id_b10(self):
        """The base 10 ID of the comment"""
        return self.comment_id

    @property
    def comment_id_b36(self):
        """The base 36 ID of the comment"""
        return utils.base_10_to_36(self.comment_id)

    def __eq__(self, other):
        """Determine if this comment is equal to another.

    Args:
        other (int, str, HTMLComment, APIComment): Object to compare to.

    Returns:
        Comparison (bool, None): Did it fit the criteria?
        """

        # Check for direct matches first
        if isinstance(other, int):
            return self.comment_id_b10 == other
        if isinstance(other, str):
            return str(self) == other

        # Check for object attributes to match to
        if hasattr(other, "comment_id_b10"):
            return self.comment_id_b10 == other.comment_id_b10

        # Check conversion to integer last
        if hasattr(other, "__int__"):
            return self.comment_id_b10 == int(other)

        return False

    def pin(self, unpin: bool = False):
        """Pin or unpin this comment.

    Args:
        unpin (bool): If true, unpins instead of pinning comment.
        """

        return self.servicephp.comment_pin(self, unpin)

    def delete(self):
        """Delete this comment"""

        return self.servicephp.comment_delete(self)

    def restore(self):
        """Un-delete this comment"""

        return self.servicephp.comment_restore(self)

    def set_rumbles(self, vote: int):
        """Post a like or dislike on this comment.

    Args:
        vote (int): -1, 0, or 1 (0 means clear vote).
        """

        return self.servicephp.rumbles(vote, self, item_type = 2)

comment_id_b10 property

The base 10 ID of the comment

comment_id_b36 property

The base 36 ID of the comment

__eq__(other)

Determine if this comment is equal to another.

Parameters:

Name Type Description Default
other (int, str, HTMLComment, APIComment)

Object to compare to.

required

Returns:

Name Type Description
Comparison (bool, None)

Did it fit the criteria?

Source code in cocorum/basehandles.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __eq__(self, other):
    """Determine if this comment is equal to another.

Args:
    other (int, str, HTMLComment, APIComment): Object to compare to.

Returns:
    Comparison (bool, None): Did it fit the criteria?
    """

    # Check for direct matches first
    if isinstance(other, int):
        return self.comment_id_b10 == other
    if isinstance(other, str):
        return str(self) == other

    # Check for object attributes to match to
    if hasattr(other, "comment_id_b10"):
        return self.comment_id_b10 == other.comment_id_b10

    # Check conversion to integer last
    if hasattr(other, "__int__"):
        return self.comment_id_b10 == int(other)

    return False

__int__()

The comment in integer form (its ID)

Source code in cocorum/basehandles.py
62
63
64
def __int__(self):
    """The comment in integer form (its ID)"""
    return self.comment_id

__str__()

The comment as a string (its text)

Source code in cocorum/basehandles.py
66
67
68
def __str__(self):
    """The comment as a string (its text)"""
    return self.text

delete()

Delete this comment

Source code in cocorum/basehandles.py
115
116
117
118
def delete(self):
    """Delete this comment"""

    return self.servicephp.comment_delete(self)

pin(unpin=False)

Pin or unpin this comment.

Parameters:

Name Type Description Default
unpin bool

If true, unpins instead of pinning comment.

False
Source code in cocorum/basehandles.py
106
107
108
109
110
111
112
113
def pin(self, unpin: bool = False):
    """Pin or unpin this comment.

Args:
    unpin (bool): If true, unpins instead of pinning comment.
    """

    return self.servicephp.comment_pin(self, unpin)

restore()

Un-delete this comment

Source code in cocorum/basehandles.py
120
121
122
123
def restore(self):
    """Un-delete this comment"""

    return self.servicephp.comment_restore(self)

set_rumbles(vote)

Post a like or dislike on this comment.

Parameters:

Name Type Description Default
vote int

-1, 0, or 1 (0 means clear vote).

required
Source code in cocorum/basehandles.py
125
126
127
128
129
130
131
132
def set_rumbles(self, vote: int):
    """Post a like or dislike on this comment.

Args:
    vote (int): -1, 0, or 1 (0 means clear vote).
    """

    return self.servicephp.rumbles(vote, self, item_type = 2)

BaseContentVotes

Likes and dislikes on a video or comment

Source code in cocorum/basehandles.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
class BaseContentVotes:
    """Likes and dislikes on a video or comment"""

    def __int__(self):
        """The integer form of the content votes"""
        return self.score

    def __eq__(self, other):
        """Determine if this content votes is equal to another.

    Args:
        other (int, str, HTMLContentVotes): Object to compare to.

    Returns:
        Comparison (bool, None): Did it fit the criteria?
        """

        # Check for direct matches first
        if isinstance(other, int):
            return self.score == other
        if isinstance(other, str):
            return str(self) == other

        # Check for object attributes to match to
        if hasattr(other, "score"):
            return self.score == other.score

        # Check conversion to integer last
        if hasattr(other, "__int__"):
            return self.score == int(other)

        return False

__eq__(other)

Determine if this content votes is equal to another.

Parameters:

Name Type Description Default
other (int, str, HTMLContentVotes)

Object to compare to.

required

Returns:

Name Type Description
Comparison (bool, None)

Did it fit the criteria?

Source code in cocorum/basehandles.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def __eq__(self, other):
    """Determine if this content votes is equal to another.

Args:
    other (int, str, HTMLContentVotes): Object to compare to.

Returns:
    Comparison (bool, None): Did it fit the criteria?
    """

    # Check for direct matches first
    if isinstance(other, int):
        return self.score == other
    if isinstance(other, str):
        return str(self) == other

    # Check for object attributes to match to
    if hasattr(other, "score"):
        return self.score == other.score

    # Check conversion to integer last
    if hasattr(other, "__int__"):
        return self.score == int(other)

    return False

__int__()

The integer form of the content votes

Source code in cocorum/basehandles.py
137
138
139
def __int__(self):
    """The integer form of the content votes"""
    return self.score

BasePlaylist

A playlist of Rumble videos

Source code in cocorum/basehandles.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
class BasePlaylist:
    """A playlist of Rumble videos"""

    def __int__(self):
        """The playlist as an integer (it's ID in base 10)"""
        return self.playlist_id_b10

    def __str__(self):
        """The playlist as a string (it's ID in base 64)"""
        return self.playlist_id_b64

    def __eq__(self, other):
        """Determine if this playlist is equal to another.

    Args:
        other (int, str, HTMLPlaylist): Object to compare to.

    Returns:
        Comparison (bool, None): Did it fit the criteria?
        """

        # Check for direct matches first
        if isinstance(other, int):
            return self.playlist_id_b64 == other
        if isinstance(other, str):
            return str(other) == self.playlist_id_b64

        # # Check for object attributes to match to
        # if hasattr(other, "playlist_id_b10"):
        #     return self.playlist_id_b10 == other.playlist_id_b10

        # # Check conversion to integer last, in case another ID or something happens to match
        # if hasattr(other, "__int__"):
        #     return self.playlist_id_b10 == int(other)

        return False

    @property
    def playlist_id_b64(self):
        """The numeric ID of the playlist in base 64"""
        return self.playlist_id

    @property
    def playlist_id_b10(self):
        """The numeric ID of the playlist in base 10"""
        raise NotImplementedError("See Cocorum issue #22")
        # return utils.base_36_to_10(self.playlist_id)

    def add_video(self, video_id):
        """Add a video to this playlist

    Args:
        video_id (int, str): The numeric ID of the video to add, in base 10 or 36.
        """

        return self.servicephp.playlist_add_video(self.playlist_id, video_id)

    def delete_video(self, video_id):
        """Remove a video from this playlist

    Args:
        video_id (int, str): The numeric ID of the video to remove, in base 10 or 36.
        """

        self.servicephp.playlist_delete_video(self.playlist_id, video_id)

    def edit(self, title: str = None, description: str = None, visibility: str = None, channel_id = None):
        """Edit the details of this playlist. WARNING: The original object will probably be stale after this operation.

    Args:
        title (str): The title of the playlist.
            Defaults to staying the same.
        description (str): Describe the playlist.
            Defaults to staying the same.
        visibility (str): Set to public, unlisted, or private via string.
            Defaults to staying the same.
        channel_id (int | str | None): The ID of the channel to have the playlist under. TODO: Cannot be retrieved!
            Defaults to resetting to None.

    Returns:
        playlist (APIPlaylist): The edit result.
        """

        if title is None:
            title = self.title
        if description is None:
            description = self.description
        if visibility is None:
            visibility = self.visibility
        # if channel_id is False:
        #     channel_id = self.channel_id

        return self.servicephp.playlist_edit(self.playlist_id, title, description, visibility, channel_id)

    def delete(self):
        """Delete this playlist"""

        self.servicephp.playlist_delete(self)

playlist_id_b10 property

The numeric ID of the playlist in base 10

playlist_id_b64 property

The numeric ID of the playlist in base 64

__eq__(other)

Determine if this playlist is equal to another.

Parameters:

Name Type Description Default
other (int, str, HTMLPlaylist)

Object to compare to.

required

Returns:

Name Type Description
Comparison (bool, None)

Did it fit the criteria?

Source code in cocorum/basehandles.py
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
def __eq__(self, other):
    """Determine if this playlist is equal to another.

Args:
    other (int, str, HTMLPlaylist): Object to compare to.

Returns:
    Comparison (bool, None): Did it fit the criteria?
    """

    # Check for direct matches first
    if isinstance(other, int):
        return self.playlist_id_b64 == other
    if isinstance(other, str):
        return str(other) == self.playlist_id_b64

    # # Check for object attributes to match to
    # if hasattr(other, "playlist_id_b10"):
    #     return self.playlist_id_b10 == other.playlist_id_b10

    # # Check conversion to integer last, in case another ID or something happens to match
    # if hasattr(other, "__int__"):
    #     return self.playlist_id_b10 == int(other)

    return False

__int__()

The playlist as an integer (it's ID in base 10)

Source code in cocorum/basehandles.py
229
230
231
def __int__(self):
    """The playlist as an integer (it's ID in base 10)"""
    return self.playlist_id_b10

__str__()

The playlist as a string (it's ID in base 64)

Source code in cocorum/basehandles.py
233
234
235
def __str__(self):
    """The playlist as a string (it's ID in base 64)"""
    return self.playlist_id_b64

add_video(video_id)

Add a video to this playlist

Parameters:

Name Type Description Default
video_id (int, str)

The numeric ID of the video to add, in base 10 or 36.

required
Source code in cocorum/basehandles.py
274
275
276
277
278
279
280
281
def add_video(self, video_id):
    """Add a video to this playlist

Args:
    video_id (int, str): The numeric ID of the video to add, in base 10 or 36.
    """

    return self.servicephp.playlist_add_video(self.playlist_id, video_id)

delete()

Delete this playlist

Source code in cocorum/basehandles.py
320
321
322
323
def delete(self):
    """Delete this playlist"""

    self.servicephp.playlist_delete(self)

delete_video(video_id)

Remove a video from this playlist

Parameters:

Name Type Description Default
video_id (int, str)

The numeric ID of the video to remove, in base 10 or 36.

required
Source code in cocorum/basehandles.py
283
284
285
286
287
288
289
290
def delete_video(self, video_id):
    """Remove a video from this playlist

Args:
    video_id (int, str): The numeric ID of the video to remove, in base 10 or 36.
    """

    self.servicephp.playlist_delete_video(self.playlist_id, video_id)

edit(title=None, description=None, visibility=None, channel_id=None)

Edit the details of this playlist. WARNING: The original object will probably be stale after this operation.

Parameters:

Name Type Description Default
title str

The title of the playlist. Defaults to staying the same.

None
description str

Describe the playlist. Defaults to staying the same.

None
visibility str

Set to public, unlisted, or private via string. Defaults to staying the same.

None
channel_id int | str | None

The ID of the channel to have the playlist under. TODO: Cannot be retrieved! Defaults to resetting to None.

None

Returns:

Name Type Description
playlist APIPlaylist

The edit result.

Source code in cocorum/basehandles.py
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
def edit(self, title: str = None, description: str = None, visibility: str = None, channel_id = None):
    """Edit the details of this playlist. WARNING: The original object will probably be stale after this operation.

Args:
    title (str): The title of the playlist.
        Defaults to staying the same.
    description (str): Describe the playlist.
        Defaults to staying the same.
    visibility (str): Set to public, unlisted, or private via string.
        Defaults to staying the same.
    channel_id (int | str | None): The ID of the channel to have the playlist under. TODO: Cannot be retrieved!
        Defaults to resetting to None.

Returns:
    playlist (APIPlaylist): The edit result.
    """

    if title is None:
        title = self.title
    if description is None:
        description = self.description
    if visibility is None:
        visibility = self.visibility
    # if channel_id is False:
    #     channel_id = self.channel_id

    return self.servicephp.playlist_edit(self.playlist_id, title, description, visibility, channel_id)

BaseUser

A Rumble user

Source code in cocorum/basehandles.py
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
class BaseUser:
    """A Rumble user"""

    def __int__(self):
        """The user as an integer (it's ID in base 10)"""
        return self.user_id_b10

    def __eq__(self, other):
        """Determine if this user is equal to another.

    Args:
        other (int, str, APIUser): Object to compare to.

    Returns:
        Comparison (bool, None): Did it fit the criteria?
        """

        #Check for direct matches first
        if isinstance(other, int):
            return self.user_id_b10 == other
        if isinstance(other, str):
            return str(other) in (self.user_id_b36, self.username)

        #Check for object attributes to match to
        if hasattr(other, "user_id"):
            return self.user_id_b10 == utils.ensure_b10(other.user_id)

        #Check conversion to integer last, in case another ID or something happens to match
        if hasattr(other, "__int__"):
            return self.user_id_b10 == int(other)

        return False

    @property
    def user_id_b10(self):
        """The numeric ID of the user in base 10"""
        return self.user_id

    @property
    def user_id_b36(self):
        """The numeric ID of the user in base 36"""
        return utils.base_10_to_36(self.user_id)

    def mute(self, duration: int = None, total: bool = False):
        """Mute this user.

    Args:
        duration (int): How long to mute the user in seconds.
            Defaults to infinite.
        total (bool): Wether or not they are muted across all videos.
            Defaults to False, just this video.
            """

        self.servicephp.mute(self, self.username, duration, total)

    def unmute(self):
        """Unmute this user."""
        self.servicephp.unmute(self.username)

user_id_b10 property

The numeric ID of the user in base 10

user_id_b36 property

The numeric ID of the user in base 36

__eq__(other)

Determine if this user is equal to another.

Parameters:

Name Type Description Default
other (int, str, APIUser)

Object to compare to.

required

Returns:

Name Type Description
Comparison (bool, None)

Did it fit the criteria?

Source code in cocorum/basehandles.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
def __eq__(self, other):
    """Determine if this user is equal to another.

Args:
    other (int, str, APIUser): Object to compare to.

Returns:
    Comparison (bool, None): Did it fit the criteria?
    """

    #Check for direct matches first
    if isinstance(other, int):
        return self.user_id_b10 == other
    if isinstance(other, str):
        return str(other) in (self.user_id_b36, self.username)

    #Check for object attributes to match to
    if hasattr(other, "user_id"):
        return self.user_id_b10 == utils.ensure_b10(other.user_id)

    #Check conversion to integer last, in case another ID or something happens to match
    if hasattr(other, "__int__"):
        return self.user_id_b10 == int(other)

    return False

__int__()

The user as an integer (it's ID in base 10)

Source code in cocorum/basehandles.py
170
171
172
def __int__(self):
    """The user as an integer (it's ID in base 10)"""
    return self.user_id_b10

mute(duration=None, total=False)

Mute this user.

Parameters:

Name Type Description Default
duration int

How long to mute the user in seconds. Defaults to infinite.

None
total bool

Wether or not they are muted across all videos. Defaults to False, just this video.

False
Source code in cocorum/basehandles.py
210
211
212
213
214
215
216
217
218
219
220
def mute(self, duration: int = None, total: bool = False):
    """Mute this user.

Args:
    duration (int): How long to mute the user in seconds.
        Defaults to infinite.
    total (bool): Wether or not they are muted across all videos.
        Defaults to False, just this video.
        """

    self.servicephp.mute(self, self.username, duration, total)

unmute()

Unmute this user.

Source code in cocorum/basehandles.py
222
223
224
def unmute(self):
    """Unmute this user."""
    self.servicephp.unmute(self.username)

BaseUserBadge

A badge on a username

Source code in cocorum/basehandles.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class BaseUserBadge:
    """A badge on a username"""
    def __eq__(self, other):
        """Check if this badge is equal to another.

    Args:
        other (str, HTMLUserBadge): Object to compare to.

    Returns:
        Comparison (bool, None): Did it fit the criteria?
        """

        # Check if the string is either our slug or our label in any language
        if isinstance(other, str):
            return other in (self.slug, self.label.values())

        # Check if the compared object has the same slug, if it has one
        if hasattr(other, "slug"):
            return self.slug == other.slug

        return False

    def __str__(self):
        """The chat user badge in string form"""
        return self.slug

    @property
    def icon(self):
        """The badge's icon as a bytestring"""
        if not self.__icon:  # We never queried the icon before
            # TODO make the timeout configurable
            response = requests.get(self.icon_url, timeout = static.Delays.request_timeout)
            assert response.status_code == 200, "Status code " + str(response.status_code)

            self.__icon = response.content

        return self.__icon

icon property

The badge's icon as a bytestring

__eq__(other)

Check if this badge is equal to another.

Parameters:

Name Type Description Default
other (str, HTMLUserBadge)

Object to compare to.

required

Returns:

Name Type Description
Comparison (bool, None)

Did it fit the criteria?

Source code in cocorum/basehandles.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def __eq__(self, other):
    """Check if this badge is equal to another.

Args:
    other (str, HTMLUserBadge): Object to compare to.

Returns:
    Comparison (bool, None): Did it fit the criteria?
    """

    # Check if the string is either our slug or our label in any language
    if isinstance(other, str):
        return other in (self.slug, self.label.values())

    # Check if the compared object has the same slug, if it has one
    if hasattr(other, "slug"):
        return self.slug == other.slug

    return False

__str__()

The chat user badge in string form

Source code in cocorum/basehandles.py
44
45
46
def __str__(self):
    """The chat user badge in string form"""
    return self.slug

S.D.G.