Implement persistent unique colors for chatters

This commit is contained in:
2025-10-30 19:26:29 +01:00
parent eede9a3560
commit 865330db76

View File

@@ -3,6 +3,7 @@ import sys
import os import os
import time import time
import re import re
import json
from datetime import datetime from datetime import datetime
from rich.console import Console from rich.console import Console
from rich.style import Style from rich.style import Style
@@ -11,21 +12,56 @@ console = Console()
# Define the emoji pattern and coloring function # Define the emoji pattern and coloring function
emoji_pattern = re.compile( emoji_pattern = re.compile(
r'(' r"""
r'\U0001F600-\U0001F64F' # emoticons (
r'\U0001F300-\U0001F5FF' # symbols & pictographs U0001F600-U0001F64F # emoticons
r'\U0001F680-\U0001F6FF' # transport & map symbols U0001F300-U0001F5FF # symbols & pictographs
r'\U0001F1E0-\U0001F1FF' # flags (iOS) U0001F680-U0001F6FF # transport & map symbols
r'\u2702-\u27B0' # Dingbats U0001F1E0-U0001F1FF # flags (iOS)
r'\u24C2-\u2B55' # Enclosed characters U2702-U27B0 # Dingbats
r'\U0001F900-\U0001F9FF' # Supplemental Symbols & Pictographs U24C2-U2B55 # Enclosed characters
r'\u200D' # ZWJ U0001F900-U0001F9FF # Supplemental Symbols & Pictographs
r'\uFE0F' # VS-16 U200D # ZWJ
r')+', flags=re.UNICODE) UFE0F # VS-16
)+"""
, re.UNICODE | re.VERBOSE)
def colour_emoji(txt): def colour_emoji(txt):
return emoji_pattern.sub(r'[magenta]\1[/magenta]', txt) return emoji_pattern.sub(r'[magenta]\1[/magenta]', txt)
# --- User Color Management ---
USER_COLORS_FILE = "user_colors.json"
# A palette of distinct colors for usernames
COLOR_PALETTE = [
"#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#00FFFF", "#FF00FF",
"#FFA500", "#800080", "#008000", "#FFC0CB", "#808000", "#008080",
"#C0C0C0", "#800000", "#000080", "#FFD700", "#ADFF2F", "#FF69B4"
]
user_color_map = {}
def load_user_colors():
global user_color_map
if os.path.exists(USER_COLORS_FILE):
with open(USER_COLORS_FILE, 'r') as f:
user_color_map = json.load(f)
def save_user_colors():
with open(USER_COLORS_FILE, 'w') as f:
json.dump(user_color_map, f, indent=4)
def get_user_color(author_id):
global user_color_map
if author_id not in user_color_map:
# Assign a new color from the palette
# Cycle through colors, or pick randomly if palette is exhausted
next_color_index = len(user_color_map) % len(COLOR_PALETTE)
user_color_map[author_id] = COLOR_PALETTE[next_color_index]
save_user_colors() # Save immediately after assigning a new color
return user_color_map[author_id]
# --- Main Script Logic ---
def main(): def main():
# Clear the terminal screen # Clear the terminal screen
os.system('clear') os.system('clear')
@@ -40,6 +76,9 @@ def main():
log_file = open(log_filename, "w", encoding="utf-8") log_file = open(log_filename, "w", encoding="utf-8")
console.print(f"[green]Chat will be logged to {log_filename}[/green]") console.print(f"[green]Chat will be logged to {log_filename}[/green]")
# Load existing user colors
load_user_colors()
try: try:
livechat = pytchat.create(video_id=video_id) livechat = pytchat.create(video_id=video_id)
console.print(f"[green]Listening to live chat for video ID: {video_id}[/green]") console.print(f"[green]Listening to live chat for video ID: {video_id}[/green]")
@@ -53,6 +92,8 @@ def main():
while livechat.is_alive(): while livechat.is_alive():
for c in livechat.get().sync_items(): for c in livechat.get().sync_items():
author_display_name = c.author.name author_display_name = c.author.name
# pytchat provides author.channelId, which is perfect for unique identification
author_channel_id = c.author.channelId
message_text = c.message message_text = c.message
# Process text-based emotes (e.g., :face-purple-sweating:) # Process text-based emotes (e.g., :face-purple-sweating:)
@@ -61,15 +102,14 @@ def main():
# Apply emoji coloring using the new function # Apply emoji coloring using the new function
message_text = colour_emoji(message_text) message_text = colour_emoji(message_text)
# Simple color for username (can be expanded to unique colors per user) # Get persistent color for the user
username_style = Style(color="#4CAF50", bold=True) user_color = get_user_color(author_channel_id)
username_style = Style(color=user_color, bold=True)
# Format message for terminal # Format message for terminal
formatted_message = f"[{username_style}]{author_display_name}[/]: {message_text}" formatted_message = f"[{username_style}]{author_display_name}[/]: {message_text}"
# Calculate padding to fill terminal width # Calculate padding to fill terminal width
# rich handles rendering, so we need to calculate the visible width of the string
# and pad it. This is a simplified approach, rich's Panel might be better for complex layouts.
rendered_length = console.measure(formatted_message).maximum rendered_length = console.measure(formatted_message).maximum
padding = max(0, console.width - rendered_length) padding = max(0, console.width - rendered_length)
padded_message = f"{formatted_message}{' ' * padding}" padded_message = f"{formatted_message}{' ' * padding}"