Files
MineGeo/supabase/migrations/20261027120223_party_chat_account_cooldowns.sql
pavel444-byte 1fc59d4ceb
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 8m22s
Fix party slow mode across account sessions
2026-10-27 17:05:56 +05:00

59 lines
3.8 KiB
PL/PgSQL

-- Serialize the backfill with room joins, leaves, and chat writes.
lock table public.multiplayer_rooms in exclusive mode;
create table public.party_chat_account_cooldowns (
room_id uuid not null references public.multiplayer_rooms(id) on delete cascade,
account_id uuid not null references public.profiles(id) on delete cascade,
last_message_at timestamptz not null,
primary key(room_id, account_id)
);
create index party_chat_account_cooldowns_account on public.party_chat_account_cooldowns(account_id);
alter table public.party_chat_account_cooldowns enable row level security;
revoke all on public.party_chat_account_cooldowns from public, anon, authenticated;
grant all on public.party_chat_account_cooldowns to service_role;
-- Include the retained browser cooldown even when a player's messages were deleted.
insert into public.party_chat_account_cooldowns(room_id, account_id, last_message_at)
select p.room_id, p.account_id, max(c.last_message_at)
from public.multiplayer_players p
join public.party_chat_cooldowns c on c.room_id=p.room_id and c.access_hash=p.access_hash
where p.account_id is not null
group by p.room_id, p.account_id;
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
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))
or (player.account_id is not null and exists(select 1 from public.party_chat_account_cooldowns
where room_id=p_room and account_id=player.account_id
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);
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;
if player.account_id is not null then
insert into public.party_chat_account_cooldowns(room_id,account_id,last_message_at)
values(p_room,player.account_id,clock_timestamp())
on conflict(room_id,account_id) do update set last_message_at=excluded.last_message_at;
end if;
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';