feat: sync recent call and channel fixes

This commit is contained in:
A 2026-07-01 14:34:59 +08:00
parent e5e0080216
commit 866a87583e
65 changed files with 6680 additions and 229 deletions

View file

@ -0,0 +1,24 @@
DROP TABLE IF EXISTS public.group_call_chain_blocks;
DROP TABLE IF EXISTS public.group_call_invites;
DROP INDEX IF EXISTS public.group_calls_conference_random_uniq;
DROP INDEX IF EXISTS public.group_calls_invite_slug_uniq;
DROP INDEX IF EXISTS public.group_calls_active_channel_uniq;
CREATE UNIQUE INDEX IF NOT EXISTS group_calls_active_channel_uniq
ON public.group_calls USING btree (channel_id)
WHERE (state = 'active'::text);
ALTER TABLE public.group_call_participants
DROP COLUMN IF EXISTS join_block,
DROP COLUMN IF EXISTS public_key;
ALTER TABLE public.group_calls
DROP CONSTRAINT IF EXISTS group_calls_kind_check;
ALTER TABLE public.group_calls
DROP COLUMN IF EXISTS migrated_from_phone_call_id,
DROP COLUMN IF EXISTS random_id,
DROP COLUMN IF EXISTS invite_link,
DROP COLUMN IF EXISTS invite_slug,
DROP COLUMN IF EXISTS kind;

View file

@ -0,0 +1,58 @@
ALTER TABLE public.group_calls
ADD COLUMN IF NOT EXISTS kind text DEFAULT 'channel'::text NOT NULL,
ADD COLUMN IF NOT EXISTS invite_slug text DEFAULT ''::text NOT NULL,
ADD COLUMN IF NOT EXISTS invite_link text DEFAULT ''::text NOT NULL,
ADD COLUMN IF NOT EXISTS random_id bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS migrated_from_phone_call_id bigint DEFAULT 0 NOT NULL;
ALTER TABLE public.group_calls
DROP CONSTRAINT IF EXISTS group_calls_kind_check;
ALTER TABLE public.group_calls
ADD CONSTRAINT group_calls_kind_check CHECK (kind = ANY (ARRAY['channel'::text, 'conference'::text]));
ALTER TABLE public.group_call_participants
ADD COLUMN IF NOT EXISTS public_key bytea,
ADD COLUMN IF NOT EXISTS join_block bytea;
DROP INDEX IF EXISTS public.group_calls_active_channel_uniq;
CREATE UNIQUE INDEX IF NOT EXISTS group_calls_active_channel_uniq
ON public.group_calls USING btree (channel_id)
WHERE ((state = 'active'::text) AND (channel_id <> 0));
CREATE UNIQUE INDEX IF NOT EXISTS group_calls_invite_slug_uniq
ON public.group_calls USING btree (invite_slug)
WHERE (invite_slug <> ''::text);
CREATE UNIQUE INDEX IF NOT EXISTS group_calls_conference_random_uniq
ON public.group_calls USING btree (creator_user_id, random_id)
WHERE ((kind = 'conference'::text) AND (random_id <> 0));
CREATE TABLE IF NOT EXISTS public.group_call_invites (
call_id bigint NOT NULL REFERENCES public.group_calls(call_id) ON DELETE CASCADE,
inviter_user_id bigint NOT NULL,
invitee_user_id bigint NOT NULL,
message_id integer NOT NULL,
status text DEFAULT 'pending'::text NOT NULL,
video boolean DEFAULT false NOT NULL,
created_at integer NOT NULL,
updated_at integer DEFAULT 0 NOT NULL,
CONSTRAINT group_call_invites_status_check CHECK (status = ANY (ARRAY['pending'::text, 'accepted'::text, 'declined'::text, 'missed'::text, 'revoked'::text])),
CONSTRAINT group_call_invites_pkey PRIMARY KEY (call_id, invitee_user_id, message_id)
);
CREATE UNIQUE INDEX IF NOT EXISTS group_call_invites_msg_uniq
ON public.group_call_invites USING btree (invitee_user_id, message_id);
CREATE INDEX IF NOT EXISTS group_call_invites_call_idx
ON public.group_call_invites USING btree (call_id, invitee_user_id);
CREATE TABLE IF NOT EXISTS public.group_call_chain_blocks (
call_id bigint NOT NULL REFERENCES public.group_calls(call_id) ON DELETE CASCADE,
sub_chain_id integer DEFAULT 0 NOT NULL,
block_offset integer NOT NULL,
block bytea NOT NULL,
created_at integer NOT NULL,
CONSTRAINT group_call_chain_blocks_pkey PRIMARY KEY (call_id, sub_chain_id, block_offset)
);

View file

@ -0,0 +1,2 @@
-- Data repair only. Do not remove ManageRanks on rollback because later user edits
-- may have intentionally granted it.

View file

@ -0,0 +1,21 @@
UPDATE channel_members m
SET admin_rights = m.admin_rights || '{"ManageRanks": true}'::jsonb
FROM channels c
WHERE c.id = m.channel_id
AND NOT c.deleted
AND c.megagroup
AND NOT c.broadcast
AND m.status = 'active'
AND (
m.role = 'creator'
OR (
m.role = 'admin'
AND COALESCE((m.admin_rights ->> 'ChangeInfo')::boolean, false)
AND COALESCE((m.admin_rights ->> 'DeleteMessages')::boolean, false)
AND COALESCE((m.admin_rights ->> 'BanUsers')::boolean, false)
AND COALESCE((m.admin_rights ->> 'InviteUsers')::boolean, false)
AND COALESCE((m.admin_rights ->> 'PinMessages')::boolean, false)
AND COALESCE((m.admin_rights ->> 'AddAdmins')::boolean, false)
AND COALESCE((m.admin_rights ->> 'ManageCall')::boolean, false)
)
);

View file

@ -0,0 +1,4 @@
DROP INDEX IF EXISTS public.group_call_chain_blocks_author_idx;
ALTER TABLE public.group_call_chain_blocks
DROP COLUMN IF EXISTS author_user_id;

View file

@ -0,0 +1,5 @@
ALTER TABLE public.group_call_chain_blocks
ADD COLUMN IF NOT EXISTS author_user_id bigint DEFAULT 0 NOT NULL;
CREATE INDEX IF NOT EXISTS group_call_chain_blocks_author_idx
ON public.group_call_chain_blocks USING btree (call_id, sub_chain_id, author_user_id, block_offset);

View file

@ -0,0 +1 @@
-- No-op: discarded empty conference calls are terminal cleanup records.

View file

@ -0,0 +1,31 @@
WITH stale AS (
SELECT c.call_id
FROM public.group_calls c
WHERE c.kind = 'conference'::text
AND c.state = 'active'::text
AND EXISTS (
SELECT 1
FROM public.group_call_participants p
WHERE p.call_id = c.call_id
)
AND NOT EXISTS (
SELECT 1
FROM public.group_call_participants p
WHERE p.call_id = c.call_id
AND NOT p.left_call
)
)
UPDATE public.group_calls c
SET state = 'discarded'::text,
discarded_at = CASE
WHEN c.discarded_at = 0 THEN EXTRACT(EPOCH FROM now())::integer
ELSE c.discarded_at
END,
duration = CASE
WHEN c.duration = 0 THEN GREATEST(0, EXTRACT(EPOCH FROM now())::integer - c.created_at)
ELSE c.duration
END,
participants_count = 0,
version = c.version + 1
FROM stale
WHERE c.call_id = stale.call_id;