sort active users, validate models and voices, fix room links

modified:   app.py
	modified:   templates/base.html
	modified:   templates/chat.html
This commit is contained in:
Russell Ballestrini 2024-11-23 12:04:48 -05:00
parent 0f82305087
commit 5fa37da991
3 changed files with 34 additions and 7 deletions

4
app.py
View file

@ -176,12 +176,12 @@ class Room(db.Model):
def add_user(self, username): def add_user(self, username):
users = set(self.active_users.split(",")) if self.active_users else set() users = set(self.active_users.split(",")) if self.active_users else set()
users.add(username) users.add(username)
self.active_users = ",".join(users) self.active_users = ",".join(sorted(users))
def remove_user(self, username): def remove_user(self, username):
users = set(self.active_users.split(",")) if self.active_users else set() users = set(self.active_users.split(",")) if self.active_users else set()
users.discard(username) users.discard(username)
self.active_users = ",".join(users) self.active_users = ",".join(sorted(users))
def get_active_users(self): def get_active_users(self):
return self.active_users.split(",") if self.active_users else [] return self.active_users.split(",") if self.active_users else []

View file

@ -290,7 +290,7 @@
<ul id="rooms-list-ul"> <ul id="rooms-list-ul">
<!-- Loop through rooms and create list items for each room --> <!-- Loop through rooms and create list items for each room -->
{% for room in rooms %} {% for room in rooms %}
<a href="{{ url_for('chat', room_name=room.name) }}?username={{ username }}"> <a href="{{ url_for('chat', room_name=room.name) }}?{{ request.query_string.decode('utf-8')|safe }}">
<li data-room-id="{{ room.id }}"> <li data-room-id="{{ room.id }}">
<!-- Display the room title if available, otherwise the room name --> <!-- Display the room title if available, otherwise the room name -->
<b>{{ room.name }}</b> {% if room.title %}<br />{{ room.title }} {% endif %} <b>{{ room.name }}</b> {% if room.title %}<br />{{ room.title }} {% endif %}

View file

@ -65,6 +65,14 @@ const urlParams = new URLSearchParams(window.location.search);
const username = urlParams.get("username"); const username = urlParams.get("username");
const room_name = "{{ room_name }}"; const room_name = "{{ room_name }}";
// Global constants for valid voices and models
const VALID_VOICES = ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'];
const VALID_MODELS = [
'None', 'gemini-flash', 'gemini-flash-8b', 'gemini-pro', 'grok-beta',
'vllm/hermes-llama-3', 'gpt-4', 'gpt-4o-2024-08-06', 'gpt-mini',
'gpt-o1-mini', 'claude-haiku', 'claude-sonnet', 'claude-opus'
];
// Configuration for DOMPurify to specify which tags and attributes are allowed // Configuration for DOMPurify to specify which tags and attributes are allowed
const dompurify_config = { const dompurify_config = {
ADD_TAGS: ["iframe", "img"], ADD_TAGS: ["iframe", "img"],
@ -101,11 +109,19 @@ document.addEventListener('DOMContentLoaded', (event) => {
voiceSelect.addEventListener("change", updateQueryString); voiceSelect.addEventListener("change", updateQueryString);
}); });
// Function to update the query string with model and voice
// Function to validate and update the query string
function updateQueryString() { function updateQueryString() {
const model = document.getElementById("model-select").value; const sanitizedUsername = sanitizeUsername(username);
const voice = document.getElementById("voice-select").value; const modelSelect = document.getElementById("model-select");
const voiceSelect = document.getElementById("voice-select");
// Validate model and voice
const model = VALID_MODELS.includes(modelSelect.value) ? modelSelect.value : 'None';
const voice = VALID_VOICES.includes(voiceSelect.value) ? voiceSelect.value : 'onyx';
const newUrl = new URL(window.location.href); const newUrl = new URL(window.location.href);
newUrl.searchParams.set("username", sanitizedUsername);
newUrl.searchParams.set("model", model); newUrl.searchParams.set("model", model);
newUrl.searchParams.set("voice", voice); newUrl.searchParams.set("voice", voice);
window.history.replaceState({}, '', newUrl); window.history.replaceState({}, '', newUrl);
@ -185,9 +201,20 @@ socket.on('update_room_list', function(updatedRoom) {
} }
}); });
// Function to sanitize the username
function sanitizeUsername(username) {
// Split the username on commas and take the first part.
// The backend denormalizes the user list in the room table via csv.
return username.split(',')[0].trim();
}
// Socket event when the user connects // Socket event when the user connects
socket.on("connect", () => { socket.on("connect", () => {
socket.emit("join", {"username": username, "room_name": room_name}); // Sanitize the username before joining
const sanitizedUsername = sanitizeUsername(username);
socket.emit("join", {"username": sanitizedUsername, "room_name": room_name});
// Update the query string with the sanitized username
updateQueryString();
}); });
// Function to read text using TTS // Function to read text using TTS