Skip to content

Commit

Permalink
Minor fixes and doc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
thelabcat committed Nov 28, 2024
1 parent cffbd79 commit aeca667
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 34 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ if livestream:
time.sleep(0.1)
```

## Experimental SSE chat submodule
## Experimental internal chat API submodule
This part of cocorum is not part of the official Rumble Live Stream API, but may provide a more reliable method of ensuring all chat messages are received.
It also can do to-chat interactions, sometimes via Service.PHP.

Example usage:
```
from cocorum import ssechat
from cocorum import chatapi
chat = ssechat.SSEChat(stream_id = stream_id) #Stream ID can be base 10 or 36
#Additionally pass username and password for to-chat interactions
chat = chatapi.ChatAPI(stream_id = STREAM_ID) #Stream ID can be base 10 or 36
chat.clear_mailbox() #Erase messages that were still visible before we connected
#Get messages for one minute
Expand Down
5 changes: 2 additions & 3 deletions src/cocorum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
Example usage:
```
from cocorum import RumbleAPI
from cocorum.localvars import *
api = RumbleAPI(API_URL, refresh_rate = 10)
Expand All @@ -27,7 +26,7 @@
livestream = api.latest_livestream #None if there is no stream running
if livestream:
if livestream.visibility != STREAM_VIS_PUBLIC:
if livestream.visibility != "public":
print("Stream is not public.")
#Get messages for one minute
Expand Down Expand Up @@ -212,7 +211,7 @@ def __getitem__(self, key):
#The livestream has not disappeared from the API listing,
#the key requested is not a value that doesn't change,
#and it has been api.refresh rate since the last time we refreshed
if (not self.is_disappeared) and (key not in static.StaticAPIEndpoints.main_STREAM) and (time.time() - self.api.last_refresh_time > self.api.refresh_rate):
if (not self.is_disappeared) and (key not in static.StaticAPIEndpoints.main) and (time.time() - self.api.last_refresh_time > self.api.refresh_rate):
self.api.refresh()

return self._jsondata[key]
Expand Down
58 changes: 32 additions & 26 deletions src/cocorum/chatapi.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#!/usr/bin/env python3
"""SSE chat display client
"""Internal chat API client
This part of cocorum is not part of the official Rumble Live Stream API, but may provide a more reliable method of ensuring all chat messages are received.
It also can do to-chat interactions, sometimes via Service.PHP.
Example usage:
```
from cocorum import ssechat
from cocorum import chatapi
chat = ssechat.SSEChat(stream_id = STREAM_ID) #Stream ID can be base 10 or 36
#Additionally pass username and password for to-chat interactions
chat = chatapi.ChatAPI(stream_id = STREAM_ID) #Stream ID can be base 10 or 36
chat.clear_mailbox() #Erase messages that were still visible before we connected
#Get messages for one minute
Expand All @@ -26,33 +28,33 @@
from . import utils
from . import UserAction

class SSEChatObject():
"""Object in SSE chat API"""
class ChatAPIObject():
"""Object in the internal chat API"""
def __init__(self, jsondata, chat):
"""Pass the object JSON, and the parent SSEChat object"""
"""Pass the object JSON, and the parent ChatAPI object"""
self._jsondata = jsondata
self.chat = chat

def __getitem__(self, key):
"""Get a key from the JSON"""
return self._jsondata[key]

class SSEChatter(UserAction, SSEChatObject):
"""A user or channel in the SSE chat"""
class ChatAPIChatter(UserAction, ChatAPIObject):
"""A user or channel in the internal chat API"""
def __init__(self, jsondata, chat):
"""Pass the object JSON, and the parent SSEChat object"""
"""Pass the object JSON, and the parent ChatAPI object"""
UserAction.__init__(self, jsondata)
SSEChatObject.__init__(self, jsondata, chat)
ChatAPIObject.__init__(self, jsondata, chat)

@property
def link(self):
"""The user's subpage of Rumble.com"""
return self["link"]

class SSEChatUser(SSEChatter):
"""User in SSE chat"""
class ChatAPIUser(ChatAPIChatter):
"""User in the internal chat API"""
def __init__(self, jsondata, chat):
"""Pass the object JSON, and the parent SSEChat object"""
"""Pass the object JSON, and the parent ChatAPI object"""
super().__init__(jsondata, chat)
self.previous_channel_ids = [] #List of channels the user has appeared as, including the current one
self._set_channel_id = None #Channel ID set from message
Expand Down Expand Up @@ -102,10 +104,10 @@ def __int__(self):
"""The user in integer form, via its user ID"""
return self.user_id

class SSEChatChannel(SSEChatter):
class ChatAPIChannel(ChatAPIChatter):
"""A channel in the SSE chat"""
def __init__(self, jsondata, chat):
"""Pass the object JSON, and the parent SSEChat object"""
"""Pass the object JSON, and the parent ChatAPI object"""
super().__init__(jsondata, chat)

#Find the user who has this channel
Expand All @@ -129,10 +131,10 @@ def user_id(self):
"""The numeric ID of the user of this channel"""
return self.user.user_id

class SSEChatUserBadge(SSEChatObject):
class ChatAPIUserBadge(ChatAPIObject):
"""A badge of a user"""
def __init__(self, slug, jsondata, chat):
"""Pass the slug, the object JSON, and the parent SSEChat object"""
"""Pass the slug, the object JSON, and the parent ChatAPI object"""
super().__init__(jsondata, chat)
self.slug = slug #The unique identification for this badge
self.__icon = None
Expand Down Expand Up @@ -173,10 +175,10 @@ def icon(self):

return self.__icon

class SSEChatMessage(SSEChatObject):
"""A single chat message from the SSE API"""
class ChatAPIMessage(ChatAPIObject):
"""A single chat message in the internal chat API"""
def __init__(self, jsondata, chat):
"""Pass the object JSON, and the parent SSEChat object"""
"""Pass the object JSON, and the parent ChatAPI object"""
super().__init__(jsondata, chat)

#Set the channel ID of our user
Expand Down Expand Up @@ -379,7 +381,7 @@ def send_message(self, text: str, channel_id: int = None):
print("Error: Sending message failed,", r, r.content.decode(static.Misc.text_encoding))
return

return SSEChatMessage(r.json()["data"], self)
return ChatAPIMessage(r.json()["data"], self)

def delete_message(self, message):
"""Delete a message in chat
Expand All @@ -403,17 +405,20 @@ def delete_message(self, message):

def pin_message(self, message):
"""Pin a message"""
assert self.session_cookie, "Not logged in, cannot pin message"
return servicephp.pin_message(self.session_cookie, self.stream_id_b10, message)

def unpin_message(self, message = None):
"""Unpin the pinned message"""
assert self.session_cookie, "Not logged in, cannot unpin message"
if not message:
message = self.pinned_message
assert message, "No known pinned message and ID not provided"
return servicephp.unpin_message(self.session_cookie, self.stream_id_b10, message)

def mute_user(self, user, duration: int = None, total: bool = False):
"""Mute a user"""
assert self.session_cookie, "Not logged in, cannot mute user"
return servicephp.mute_user(
session_cookie = self.session_cookie,
username = str(user),
Expand All @@ -425,6 +430,7 @@ def mute_user(self, user, duration: int = None, total: bool = False):

def unmute_user(self, user):
"""Unmute a user"""
assert self.session_cookie, "Not logged in, cannot unmute user"
record_id = utils.get_muted_user_record(self.session_cookie, str(user))
assert record_id, "User was not in muted records"
return servicephp.unmute_user(self.session_cookie, record_id)
Expand Down Expand Up @@ -473,7 +479,7 @@ def parse_init_data(self, jsondata):
def update_mailbox(self, jsondata):
"""Parse chat messages from an SSE data JSON"""
#Add new messages
self.__mailbox += [SSEChatMessage(message_json, self) for message_json in jsondata["data"]["messages"] if message_json["id"] not in self.__mailbox]
self.__mailbox += [ChatAPIMessage(message_json, self) for message_json in jsondata["data"]["messages"] if message_json["id"] not in self.__mailbox]

def clear_mailbox(self):
"""Delete anything in the mailbox"""
Expand All @@ -491,19 +497,19 @@ def update_users(self, jsondata):
try:
self.users[user_json["id"]]._jsondata = user_json #Update an existing user's JSON
except KeyError: #User is new
self.users[user_json["id"]] = SSEChatUser(user_json, self)
self.users[user_json["id"]] = ChatAPIUser(user_json, self)

def update_channels(self, jsondata):
"""Update our dictionary of channels from an SSE data JSON"""
for channel_json in jsondata["data"]["channels"]:
try:
self.channels[channel_json["id"]]._jsondata = channel_json #Update an existing channel's JSON
except KeyError: #Channel is new
self.channels.update({channel_json["id"] : SSEChatChannel(channel_json, self)})
self.channels.update({channel_json["id"] : ChatAPIChannel(channel_json, self)})

def load_badges(self, jsondata):
"""Create our dictionary of badges given a dictionary of badges"""
self.badges = {badge_slug : SSEChatUserBadge(badge_slug, jsondata["data"]["config"]["badges"][badge_slug], self) for badge_slug in jsondata["data"]["config"]["badges"].keys()}
self.badges = {badge_slug : ChatAPIUserBadge(badge_slug, jsondata["data"]["config"]["badges"][badge_slug], self) for badge_slug in jsondata["data"]["config"]["badges"].keys()}

@property
def stream_id_b10(self):
Expand All @@ -530,7 +536,7 @@ def get_message(self):

#Pinned message
elif jsondata["type"] == "pin_message":
self.pinned_message = SSEChatMessage(jsondata["data"]["message"], self)
self.pinned_message = ChatAPIMessage(jsondata["data"]["message"], self)

#New messages
elif jsondata["type"] == "messages":
Expand Down
4 changes: 2 additions & 2 deletions src/cocorum/static.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Cocorum local variable definitions
"""Cocorum static variable definitions
This submodule provides absolute variable definitions for Cocorum.
Provides various data that, if changed, would change globally
S.D.G."""

Expand Down

0 comments on commit aeca667

Please sign in to comment.