owpengram-server/deploy/migrations/0104_star_gift_craft_capability.up.sql
A 14bf7d1e20 feat: sync official star gift lifecycle tooling
Sync telesrv 4c0e2d9 (feat: complete official star gift lifecycle and admin tooling).

Public adjustments: skipped private docs/deploy-nginx/README source changes, kept iamxvbaba/td public dependency, replaced local/private sample IP and orange seed label.
2026-07-19 03:11:35 +08:00

109 lines
4.4 KiB
SQL

-- Craft is a protocol capability, not a generic property of every collectible.
-- A non-zero craft_chance_permille is valid only when the immutable official
-- collectible revision contains at least one crafted model. Earlier versions
-- advertised the default chance for every upgrade, including official sets
-- such as Fresh Socks whose snapshot has no crafted model at all.
--
-- Repair the aggregate and every durable private-message projection together.
-- Each visible message edit advances pts and is recoverable through both live
-- outbox delivery and updates.getDifference.
DO $$
DECLARE
gift_box record;
next_pts integer;
event_date integer := EXTRACT(EPOCH FROM clock_timestamp())::integer;
repaired_media jsonb;
BEGIN
UPDATE public.unique_star_gifts unique_gift
SET craft_chance_permille = 0,
updated_at = now()
WHERE unique_gift.craft_chance_permille > 0
AND NOT EXISTS (
SELECT 1
FROM public.star_gift_collectible_models model
WHERE model.collectible_revision_id = unique_gift.collectible_revision_id
AND model.crafted
);
UPDATE public.peer_star_gifts saved_gift
SET can_craft_at = 0
FROM public.unique_star_gifts unique_gift
WHERE unique_gift.id = saved_gift.unique_gift_id
AND unique_gift.craft_chance_permille = 0
AND NOT EXISTS (
SELECT 1
FROM public.star_gift_collectible_models model
WHERE model.collectible_revision_id = unique_gift.collectible_revision_id
AND model.crafted
);
FOR gift_box IN
SELECT box.owner_user_id,
box.box_id,
box.peer_type,
box.peer_id,
box.message_sender_id,
box.private_message_id,
box.media
FROM public.message_boxes box
JOIN public.unique_star_gifts unique_gift
ON unique_gift.id = (box.media #>> '{service_action,star_gift_unique,gift,ID}')::bigint
WHERE box.media #>> '{service_action,kind}' = 'star_gift_unique'
AND jsonb_typeof(box.media #> '{service_action,star_gift_unique,gift,CraftChancePermille}') = 'number'
AND (box.media #>> '{service_action,star_gift_unique,gift,CraftChancePermille}')::integer > 0
AND NOT EXISTS (
SELECT 1
FROM public.star_gift_collectible_models model
WHERE model.collectible_revision_id = unique_gift.collectible_revision_id
AND model.crafted
)
ORDER BY box.owner_user_id, box.box_id
LOOP
repaired_media := gift_box.media
#- '{service_action,star_gift_unique,gift,CraftChancePermille}'
#- '{service_action,star_gift_unique,can_craft_at}';
INSERT INTO public.user_update_watermarks (user_id, contiguous_pts)
VALUES (gift_box.owner_user_id, 0)
ON CONFLICT (user_id) DO NOTHING;
UPDATE public.user_update_watermarks
SET contiguous_pts = contiguous_pts + 1,
updated_at = now()
WHERE user_id = gift_box.owner_user_id
RETURNING contiguous_pts INTO next_pts;
UPDATE public.message_boxes
SET media = repaired_media,
pts = next_pts
WHERE owner_user_id = gift_box.owner_user_id
AND box_id = gift_box.box_id
AND NOT deleted;
UPDATE public.private_messages
SET media = media
#- '{service_action,star_gift_unique,gift,CraftChancePermille}'
#- '{service_action,star_gift_unique,can_craft_at}',
sender_snapshot = sender_snapshot
#- '{message,Media,service_action,star_gift_unique,gift,CraftChancePermille}'
#- '{message,Media,service_action,star_gift_unique,can_craft_at}'
WHERE sender_user_id = gift_box.message_sender_id
AND id = gift_box.private_message_id;
INSERT INTO public.user_update_events (
user_id, pts, pts_count, date, event_type,
message_box_id, peer_type, peer_id
) VALUES (
gift_box.owner_user_id, next_pts, 1, event_date, 'edit_message',
gift_box.box_id, gift_box.peer_type, gift_box.peer_id
);
INSERT INTO public.dispatch_outbox (
target_user_id, pts, event_type,
exclude_auth_key_id, exclude_session_id
) VALUES (
gift_box.owner_user_id, next_pts, 'edit_message', 0, 0
);
END LOOP;
END
$$;