diff --git a/.forgejo/workflows/pipeline.yaml b/.forgejo/workflows/pipeline.yaml index 87b1268..4adede5 100644 --- a/.forgejo/workflows/pipeline.yaml +++ b/.forgejo/workflows/pipeline.yaml @@ -37,7 +37,7 @@ jobs: mkdir -p ~/discord cp target/release/chattz ~/discord/discord chmod +x ~/discord/discord - mkdir -p ~/discord/static/uploads - find ~/discord/static -mindepth 1 -maxdepth 1 ! -name 'uploads' -exec rm -rf {} + + mkdir -p ~/discord/static + rm -rf ~/discord/static/* cp -r static/* ~/discord/static/ systemctl --user start discord \ No newline at end of file diff --git a/src/db.rs b/src/db.rs index d4364bc..2e26c94 100644 --- a/src/db.rs +++ b/src/db.rs @@ -139,23 +139,6 @@ pub async fn create_guild( Ok(map_guild(guild)) } -pub async fn get_guild_by_id(db: &DatabaseConnection, guild_id: Uuid) -> Result> { - let row = guilds::Entity::find_by_id(guild_id).one(db).await?; - Ok(row.map(map_guild)) -} - -pub async fn is_guild_owner( - db: &DatabaseConnection, - guild_id: Uuid, - user_id: Uuid, -) -> Result { - let guild = guilds::Entity::find_by_id(guild_id).one(db).await?; - match guild { - Some(g) => Ok(g.owner_user_id == user_id), - None => Ok(false), - } -} - pub async fn create_invite( db: &DatabaseConnection, guild_id: Uuid, @@ -629,16 +612,6 @@ pub async fn create_sound( Ok(map_sound(model)) } -pub async fn get_sound_by_id(db: &DatabaseConnection, id: Uuid) -> Result> { - let row = soundboard_sounds::Entity::find_by_id(id).one(db).await?; - Ok(row.map(map_sound)) -} - -pub async fn delete_sound(db: &DatabaseConnection, id: Uuid) -> Result<()> { - soundboard_sounds::Entity::delete_by_id(id).exec(db).await?; - Ok(()) -} - fn map_sound(model: soundboard_sounds::Model) -> SoundboardSound { SoundboardSound { id: model.id, diff --git a/src/handlers.rs b/src/handlers.rs index fd7a593..788688d 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -15,7 +15,6 @@ use crate::{ models::{Guild, SoundboardSound}, voice, }; -use tracing::info; pub fn routes() -> Router { Router::new() @@ -44,10 +43,6 @@ pub fn routes() -> Router { "/guilds/{guild_id}/sounds", get(list_sounds).post(upload_sound), ) - .route( - "/guilds/{guild_id}/sounds/{sound_id}", - post(delete_sound_post).delete(delete_sound), - ) .route("/channels", post(create_channel)) .route( "/channels/{channel_id}/messages", @@ -764,57 +759,6 @@ async fn upload_sound( Ok(Json(sound)) } -async fn delete_sound_post( - state: State, - user: AuthUser, - path: Path<(Uuid, Uuid)>, -) -> Result { - delete_sound(state, user, path).await -} - -async fn delete_sound( - State(state): State, - user: AuthUser, - Path((guild_id, sound_id)): Path<(Uuid, Uuid)>, -) -> Result { - ensure_guild_member(&state, guild_id, user.id).await?; - - let sound = db::get_sound_by_id(&state.db, sound_id) - .await - .map_err(|e| ApiError::internal(&e.to_string()))? - .ok_or_else(|| ApiError { - status: StatusCode::NOT_FOUND, - message: "sound not found".to_string(), - })?; - - if sound.guild_id != guild_id { - return Err(ApiError::bad_request("sound does not belong to this guild")); - } - - let is_owner = db::is_guild_owner(&state.db, guild_id, user.id) - .await - .map_err(|e| ApiError::internal(&e.to_string()))?; - - if sound.created_by_user_id != user.id && !is_owner { - return Err(ApiError { - status: StatusCode::FORBIDDEN, - message: "you do not have permission to delete this sound".to_string(), - }); - } - - // Delete file from disk - let relative_path = sound.file_path.trim_start_matches('/'); - if let Err(e) = tokio::fs::remove_file(relative_path).await { - info!("failed to delete sound file {}: {}", relative_path, e); - } - - db::delete_sound(&state.db, sound_id) - .await - .map_err(|e| ApiError::internal(&format!("failed to delete sound record: {e}")))?; - - Ok(StatusCode::NO_CONTENT) -} - async fn ensure_guild_member( state: &AppState, guild_id: Uuid, diff --git a/src/voice.rs b/src/voice.rs index a0a34f0..b15b81c 100644 --- a/src/voice.rs +++ b/src/voice.rs @@ -259,10 +259,7 @@ impl VoiceHub { return; }; - for (peer_id, peer) in room.iter() { - if *peer_id == user_id { - continue; - } + for peer in room.values() { let _ = peer.tx.send(ServerEvent::PlaySound { user_id, sound_url: sound_url.clone(), diff --git a/static/app.js b/static/app.js index acd46f9..f9aad1a 100644 --- a/static/app.js +++ b/static/app.js @@ -1049,46 +1049,13 @@ function renderSounds(sounds) { sounds.forEach(sound => { const item = document.createElement('div'); item.className = 'sound-item'; - - // Only show delete button if user is creator or owner - const canDelete = state.user && (state.user.id === sound.created_by_user_id || (state.guilds.find(g => g.id === state.selectedGuildId)?.owner_user_id === state.user.id)); - item.innerHTML = `
${sound.icon}
${sound.name}
- ${canDelete ? `` : ''} `; - - item.onclick = (e) => { - if (e.target.closest('.sound-delete')) { - e.stopPropagation(); - if (confirm(`Are you sure you want to delete "${sound.name}"?`)) { - deleteSound(sound.id); - } - return; - } - playRemoteSound(sound.file_path); - }; - + item.onclick = () => playRemoteSound(sound.file_path); el.soundboardGrid.appendChild(item); }); - lucide.createIcons(); -} - -async function deleteSound(soundId) { - if (!state.selectedGuildId) return; - try { - const response = await fetch(`/guilds/${state.selectedGuildId}/sounds/${soundId}`, { - method: 'DELETE' - }); - if (!response.ok) { - const err = await response.json(); - throw new Error(err.error || 'Delete failed'); - } - await loadSounds(); - } catch (err) { - alert(err.message); - } } function playRemoteSound(url) { diff --git a/static/styles.css b/static/styles.css index a6e26d9..7319228 100644 --- a/static/styles.css +++ b/static/styles.css @@ -729,32 +729,6 @@ select { transform: scale(0.95); } -.sound-delete { - position: absolute; - top: 4px; - right: 4px; - width: 18px; - height: 18px; - border-radius: 50%; - background: rgba(0, 0, 0, 0.6); - color: var(--text-muted); - display: grid; - place-items: center; - opacity: 0; - transition: all var(--transition); - z-index: 2; -} - -.sound-delete:hover { - background: var(--danger); - color: #fff; - transform: scale(1.1); -} - -.sound-item:hover .sound-delete { - opacity: 1; -} - .sound-icon { font-size: 24px; }