Add tournament and multiplayer community chat moderation
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 12m17s
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 12m17s
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
-- Wait for in-flight room actions and block new ones until backfill and function
|
||||
-- replacement are committed, so accepted messages cannot fall between them.
|
||||
lock table public.multiplayer_rooms in exclusive mode;
|
||||
|
||||
-- Player rows and their messages disappear when a player leaves a lobby.
|
||||
-- Keep the cooldown on the room's existing access identity instead.
|
||||
create table public.party_chat_cooldowns (
|
||||
room_id uuid not null references public.multiplayer_rooms(id) on delete cascade,
|
||||
access_hash text not null,
|
||||
last_message_at timestamptz not null,
|
||||
primary key (room_id, access_hash)
|
||||
);
|
||||
alter table public.party_chat_cooldowns enable row level security;
|
||||
revoke all on public.party_chat_cooldowns from public, anon, authenticated;
|
||||
grant all on public.party_chat_cooldowns to service_role;
|
||||
|
||||
-- Preserve the cooldown of players who are already in a room at deployment.
|
||||
insert into public.party_chat_cooldowns (room_id, access_hash, last_message_at)
|
||||
select m.room_id, p.access_hash, max(m.created_at)
|
||||
from public.multiplayer_messages m
|
||||
join public.multiplayer_players p on p.room_id=m.room_id and p.id=m.player_id
|
||||
join public.multiplayer_rooms r on r.id=m.room_id
|
||||
where r.tournament_id is null
|
||||
group by m.room_id, p.access_hash;
|
||||
|
||||
create or replace function public.multiplayer_chat(p_room uuid,p_access_hash text,p_text text default null,p_client_id uuid default null)
|
||||
returns jsonb language plpgsql security invoker set search_path='' as $$
|
||||
declare room public.multiplayer_rooms; player public.multiplayer_players; result jsonb; duplicate_message boolean;
|
||||
begin
|
||||
-- The room lock also serializes joining, leaving, and concurrent chat sends.
|
||||
select * into room from public.multiplayer_rooms where id=p_room for update;
|
||||
select * into player from public.multiplayer_players where room_id=p_room and access_hash=p_access_hash and not has_left;
|
||||
duplicate_message := player.id is not null and p_client_id is not null and exists(
|
||||
select 1 from public.multiplayer_messages where room_id=p_room and player_id=player.id and client_id=p_client_id
|
||||
);
|
||||
if player.id is not null and p_text is not null and room.chat_slow_seconds>0 and player.id<>room.host_player_id
|
||||
and not exists(select 1 from public.party_moderators where room_id=p_room and player_id=player.id)
|
||||
and not duplicate_message
|
||||
and exists(select 1 from public.party_chat_cooldowns where room_id=p_room and access_hash=p_access_hash
|
||||
and last_message_at>clock_timestamp()-make_interval(secs=>room.chat_slow_seconds))
|
||||
then raise exception 'Chat slow mode: wait before sending another message'; end if;
|
||||
result:=public.multiplayer_chat_unchecked(p_room,p_access_hash,p_text,p_client_id);
|
||||
-- Only accepted new messages advance the cooldown; reads and retries do not.
|
||||
if player.id is not null and p_text is not null and p_client_id is not null and not duplicate_message then
|
||||
insert into public.party_chat_cooldowns(room_id,access_hash,last_message_at)
|
||||
values(p_room,p_access_hash,clock_timestamp())
|
||||
on conflict(room_id,access_hash) do update set last_message_at=excluded.last_message_at;
|
||||
end if;
|
||||
return jsonb_set(result,'{messages}',coalesce((select jsonb_agg(msg || jsonb_build_object('tag',tag.tag) order by ord)
|
||||
from jsonb_array_elements(result->'messages') with ordinality x(msg,ord)
|
||||
left join public.party_tags tag on tag.room_id=p_room and tag.player_id=(msg->>'playerId')::uuid),'[]'::jsonb));
|
||||
end; $$;
|
||||
revoke all on function public.multiplayer_chat(uuid,text,text,uuid) from public,anon,authenticated;
|
||||
grant execute on function public.multiplayer_chat(uuid,text,text,uuid) to service_role;
|
||||
notify pgrst,'reload schema';
|
||||
Reference in New Issue
Block a user