-- Sharkey 2024.3.1 to TrashPoss 2024.04.1 migration script
-- by @kopper@brain.d.on-t.work
-- only tested with aidx, theoretical support for aid and meid. other id schemes are NOT supported.
-- servers which have migrated from firefish and trashposs to sharkey may encounter undefined behavior, as
--   - sharkey's migration steps do not attempt to clean up unused firefish-exclusive data, meaning your database schema may have columns this script doesn't expect
--   - re-generating createdAt data from cuid2 is untested (though it *may* end up working with the default length of 16 characters)
-- no warranty, you're on your own if anything breaks.
-- make sure to run this script from the same postgres user as trashposs, otherwise you'll encounter permission errors
BEGIN;

-- createdAt generation functions
-- https://github.com/PrivateGER/Sharkey/blob/a2f7d3c265e70966b539dc3805a30b025350cc9c/packages/backend/migration/1704279150928-add-created-time.js
CREATE FUNCTION base36_decode(IN base36 varchar) RETURNS bigint AS $$
			DECLARE
				a char[];
				ret bigint;
				i int;
				val int;
				chars varchar;
			BEGIN
				chars := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
				FOR i IN REVERSE char_length(base36)..1 LOOP
						a := a || substring(upper(base36) FROM i FOR 1)::char;
					END LOOP;
				i := 0;
				ret := 0;
				WHILE i < (array_length(a,1)) LOOP
						val := position(a[i+1] IN chars)-1;
						ret := ret + (val * (36 ^ i));
						i := i + 1;
					END LOOP;

				RETURN ret;
			END;
			$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE FUNCTION parseAId(id varchar)
				RETURNS timestamp AS
			$$
			DECLARE
				cutTimestamp varchar;
			BEGIN
				-- Conversion to timestamp (first eight characters)
				cutTimestamp := substring(id FROM 1 FOR 8);

				RETURN to_timestamp((base36_decode(cutTimestamp) + 946684800000) / 1000);
			END;
			$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE FUNCTION parseMeid(id varchar)
			RETURNS timestamp AS
			$$
			BEGIN
					RETURN to_timestamp(('x' || substring(id from 1 for 12))::bit(48)::bigint - x'800000000000'::bigint);
			END;
			$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE FUNCTION generate_created_at(id varchar)
			RETURNS timestamp AS
			$$
			BEGIN
				-- Check for aid (length 10, first 8 characters are base36)
				IF length(id) = 10 AND substring(id from 1 for 8) ~* '^[0-9A-Z]{8}$' THEN
					RETURN parseAId(id);
				-- Check for aidx (16 base36 characters)
				ELSIF length(id) = 16 AND id ~* '^[0-9A-Z]{16}$' THEN
					RETURN parseAId(id);
				-- Check for meid (24 hexadecimal characters)
				ELSIF length(id) = 24 AND id ~* '^[0-9A-F]{24}$' THEN
					RETURN parseMeid(id);
				ELSE
					RAISE EXCEPTION 'unrecognized id format: %', id;
				END IF;
			END;
			$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

ALTER TABLE abuse_user_report ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE abuse_user_report SET "createdAt" = generate_created_at(id);
ALTER TABLE abuse_user_report ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE access_token ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE access_token SET "createdAt" = generate_created_at(id);
ALTER TABLE access_token ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE announcement ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE announcement SET "createdAt" = generate_created_at(id);
ALTER TABLE announcement ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE announcement_read ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE announcement_read SET "createdAt" = generate_created_at(id);
ALTER TABLE announcement_read ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE antenna ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE antenna SET "createdAt" = generate_created_at(id);
ALTER TABLE antenna ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE app ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE app SET "createdAt" = generate_created_at(id);
ALTER TABLE app ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE auth_session ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE auth_session SET "createdAt" = generate_created_at(id);
ALTER TABLE auth_session ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE blocking ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE blocking SET "createdAt" = generate_created_at(id);
ALTER TABLE blocking ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE channel ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE channel SET "createdAt" = generate_created_at(id);
ALTER TABLE channel ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE channel_following ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE channel_following SET "createdAt" = generate_created_at(id);
ALTER TABLE channel_following ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE clip ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE clip SET "createdAt" = generate_created_at(id);
ALTER TABLE clip ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE drive_file ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE drive_file SET "createdAt" = generate_created_at(id);
ALTER TABLE drive_file ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE drive_folder ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE drive_folder SET "createdAt" = generate_created_at(id);
ALTER TABLE drive_folder ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE follow_request ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE follow_request SET "createdAt" = generate_created_at(id);
ALTER TABLE follow_request ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE following ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE following SET "createdAt" = generate_created_at(id);
ALTER TABLE following ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE gallery_like ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE gallery_like SET "createdAt" = generate_created_at(id);
ALTER TABLE gallery_like ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE gallery_post ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE gallery_post SET "createdAt" = generate_created_at(id);
ALTER TABLE gallery_post ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE moderation_log ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE moderation_log SET "createdAt" = generate_created_at(id);
ALTER TABLE moderation_log ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE muting ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE muting SET "createdAt" = generate_created_at(id);
ALTER TABLE muting ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE note ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE note SET "createdAt" = generate_created_at(id);
ALTER TABLE note ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE note_favorite ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE note_favorite SET "createdAt" = generate_created_at(id);
ALTER TABLE note_favorite ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE note_reaction ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE note_reaction SET "createdAt" = generate_created_at(id);
ALTER TABLE note_reaction ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE note_thread_muting ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE note_thread_muting SET "createdAt" = generate_created_at(id);
ALTER TABLE note_thread_muting ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE page ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE page SET "createdAt" = generate_created_at(id);
ALTER TABLE page ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE page_like ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE page_like SET "createdAt" = generate_created_at(id);
ALTER TABLE page_like ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE password_reset_request ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE password_reset_request SET "createdAt" = generate_created_at(id);
ALTER TABLE password_reset_request ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE poll_vote ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE poll_vote SET "createdAt" = generate_created_at(id);
ALTER TABLE poll_vote ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE promo_read ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE promo_read SET "createdAt" = generate_created_at(id);
ALTER TABLE promo_read ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE registration_ticket ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE registration_ticket SET "createdAt" = generate_created_at(id);
ALTER TABLE registration_ticket ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE registry_item ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE registry_item SET "createdAt" = generate_created_at(id);
ALTER TABLE registry_item ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE renote_muting ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE renote_muting SET "createdAt" = generate_created_at(id);
ALTER TABLE renote_muting ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE signin ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE signin SET "createdAt" = generate_created_at(id);
ALTER TABLE signin ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE sw_subscription ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE sw_subscription SET "createdAt" = generate_created_at(id);
ALTER TABLE sw_subscription ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE "user" ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE "user" SET "createdAt" = generate_created_at(id);
ALTER TABLE "user" ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE user_list ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE user_list SET "createdAt" = generate_created_at(id);
ALTER TABLE user_list ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE user_list_membership ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE user_list_membership SET "createdAt" = generate_created_at(id);
ALTER TABLE user_list_membership ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE user_note_pining ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE user_note_pining SET "createdAt" = generate_created_at(id);
ALTER TABLE user_note_pining ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE user_pending ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE user_pending SET "createdAt" = generate_created_at(id);
ALTER TABLE user_pending ALTER COLUMN "createdAt" SET NOT NULL;

ALTER TABLE webhook ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;
UPDATE webhook SET "createdAt" = generate_created_at(id);
ALTER TABLE webhook ALTER COLUMN "createdAt" SET NOT NULL;

-- createdAt cleanup
DROP FUNCTION base36_decode;
DROP FUNCTION parseAId;
DROP FUNCTION parseMeid;
DROP FUNCTION generate_created_at;

-- the rest of the owl

CREATE EXTENSION IF NOT EXISTS pg_trgm;

ALTER TYPE antenna_src_enum ADD VALUE 'group';
ALTER TYPE antenna_src_enum ADD VALUE 'instances';
-- DIFFERENCE: sharkey antenna_src_enum contains 'users_blacklist', not present on trashposs

DROP TYPE meta_sensitivemediadetection_enum CASCADE;
DROP TYPE meta_sensitivemediadetectionsensitivity_enum CASCADE;

DROP TYPE muted_note_reason_enum CASCADE;

ALTER TYPE note_visibility_enum ADD VALUE 'hidden';
ALTER TYPE poll_notevisibility_enum ADD VALUE 'hidden';

DROP TYPE notification_type_enum CASCADE;
CREATE TYPE notification_type_enum AS ENUM (
    'follow',
    'mention',
    'reply',
    'renote',
    'quote',
    'reaction',
    'pollVote',
    'pollEnded',
    'receiveFollowRequest',
    'followRequestAccepted',
    'groupInvited',
    'app'
);

DROP TYPE user_profile_mutingnotificationtypes_enum CASCADE;
CREATE TYPE user_profile_mutingnotificationtypes_enum AS ENUM (
    'follow',
    'mention',
    'reply',
    'renote',
    'quote',
    'reaction',
    'pollVote',
    'pollEnded',
    'receiveFollowRequest',
    'followRequestAccepted',
    'groupInvited',
    'app'
);

DROP TYPE role_target_enum CASCADE;

ALTER TYPE user_profile_followingvisibility_enum RENAME TO user_profile_ffvisibility_enum;
DROP TYPE "user_profile_followersVisibility_enum" CASCADE;

CREATE FUNCTION note_replies(start_id character varying, max_depth integer, max_breadth integer) RETURNS TABLE(id character varying)
    LANGUAGE sql
    AS $$
                                SELECT DISTINCT id FROM (
                                        WITH RECURSIVE tree (id, ancestors, depth) AS (
                                                SELECT start_id, '{}'::VARCHAR[], 0
                                        UNION
                                                SELECT
                                                        note.id,
                                                        CASE
                                                                WHEN note."replyId" = tree.id THEN tree.ancestors || note."replyId"
                                                                ELSE tree.ancestors || note."renoteId"
                                                        END,
                                                        depth + 1
                                                FROM note, tree
                                                WHERE (
                                                        note."replyId" = tree.id
                                                        OR
                                                        (
                                                                -- get renotes but not pure renotes
                                                                note."renoteId" = tree.id
                                                                AND
                                                                (
                                                                        note.text IS NOT NULL
                                                                        OR
                                                                        CARDINALITY(note."fileIds") != 0
                                                                        OR
                                                                        note."hasPoll" = TRUE
                                                                )
                                                        )
                                                ) AND depth < max_depth
                                        )
                                        SELECT
                                                id,
                                                -- apply the limit per node
                                                row_number() OVER (PARTITION BY ancestors[array_upper(ancestors, 1)]) AS nth_child
                                        FROM tree
                                        WHERE depth > 0
                                ) AS recursive WHERE nth_child < max_breadth
                        $$;


DROP TABLE __chart__per_user_pv CASCADE;
DROP TABLE __chart_day__per_user_pv CASCADE;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredWithinWeek" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredWithinMonth" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredWithinYear" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredOutsideWeek" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredOutsideMonth" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___registeredOutsideYear" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN "___readWrite" TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN ___read TYPE smallint;
ALTER TABLE __chart__active_users ALTER COLUMN ___write TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredWithinWeek" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredWithinMonth" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredWithinYear" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredOutsideWeek" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredOutsideMonth" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___registeredOutsideYear" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN "___readWrite" TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN ___read TYPE smallint;
ALTER TABLE __chart_day__active_users ALTER COLUMN ___write TYPE smallint;

ALTER TABLE "drive_file" ALTER COLUMN "userHost" TYPE character varying(512);
ALTER TABLE "user" ALTER COLUMN "host" TYPE character varying(512);
ALTER TABLE "user_profile" ALTER COLUMN "userHost" TYPE character varying(512);
ALTER TABLE "user_publickey" ALTER COLUMN "keyId" TYPE character varying(512);
ALTER TABLE "emoji" ALTER COLUMN "host" TYPE character varying(512);
ALTER TABLE "note" ALTER COLUMN "userHost" TYPE character varying(512);
ALTER TABLE "note" ALTER COLUMN "replyUserHost" TYPE character varying(512);
ALTER TABLE "note" ALTER COLUMN "renoteUserHost" TYPE character varying(512);
ALTER TABLE "instance" ALTER COLUMN "host" TYPE character varying(512);
ALTER TABLE "instance" ALTER COLUMN "iconUrl" TYPE character varying(4096);
ALTER TABLE "instance" ALTER COLUMN "faviconUrl" TYPE character varying(4096);
ALTER TABLE "poll" ALTER COLUMN "userHost" TYPE character varying(512);
ALTER TABLE "abuse_user_report" ALTER COLUMN "targetUserHost" TYPE character varying(512);
ALTER TABLE "abuse_user_report" ALTER COLUMN "reporterHost" TYPE character varying(512);
ALTER TABLE "following" ALTER COLUMN "followeeHost" TYPE character varying(512);
ALTER TABLE "following" ALTER COLUMN "followerHost" TYPE character varying(512);
ALTER TABLE "follow_request" ALTER COLUMN "followeeHost" TYPE character varying(512);
ALTER TABLE "follow_request" ALTER COLUMN "followerHost" TYPE character varying(512);

DROP TABLE ad CASCADE;

ALTER TABLE announcement DROP COLUMN "display" CASCADE;
ALTER TABLE announcement DROP COLUMN "needConfirmationToRead" CASCADE;
ALTER TABLE announcement DROP COLUMN "isActive" CASCADE;
ALTER TABLE announcement DROP COLUMN "forExistingUsers" CASCADE;
ALTER TABLE announcement DROP COLUMN "userId" CASCADE;
ALTER TABLE announcement DROP COLUMN icon CASCADE;
ALTER TABLE announcement DROP COLUMN silence CASCADE;
ALTER TABLE announcement ADD COLUMN "showPopup" BOOLEAN DEFAULT false NOT NULL;
ALTER TABLE announcement ADD COLUMN "isGoodNews" BOOLEAN DEFAULT false NOT NULL;

ALTER TABLE antenna ADD COLUMN "userGroupJoiningId" CHARACTER VARYING(32);
ALTER TABLE antenna ADD COLUMN instances JSONB DEFAULT '[]'::jsonb NOT NULL;
ALTER TABLE antenna DROP COLUMN "lastUsedAt" CASCADE;
ALTER TABLE antenna DROP COLUMN "isActive" CASCADE;
ALTER TABLE antenna DROP COLUMN "localOnly" CASCADE;

CREATE TABLE attestation_challenge (
    id character varying(32) NOT NULL,
    "userId" character varying(32) NOT NULL,
    challenge character varying(64) NOT NULL,
    "createdAt" timestamp with time zone NOT NULL,
    "registrationChallenge" boolean DEFAULT false NOT NULL
);

DROP TABLE avatar_decoration CASCADE;
DROP TABLE bubble_game_record CASCADE;

ALTER TABLE channel DROP COLUMN "pinnedNoteIds" CASCADE; -- TODO: check to see if this needs to be migrated to channel_note_pining table
ALTER TABLE channel DROP COLUMN color CASCADE;
ALTER TABLE channel DROP COLUMN "isArchived" CASCADE;
ALTER TABLE channel DROP COLUMN "isSensitive" CASCADE;
ALTER TABLE channel DROP COLUMN "allowRenoteToExternal" CASCADE;

DROP TABLE channel_favorite CASCADE;

ALTER TABLE clip DROP COLUMN "lastClippedAt" CASCADE;

DROP TABLE clip_favorite CASCADE;

ALTER TABLE drive_file DROP COLUMN "maybeSensitive" CASCADE;
ALTER TABLE drive_file DROP COLUMN "maybePorn" CASCADE;

ALTER TABLE emoji DROP COLUMN "localOnly" CASCADE;
ALTER TABLE emoji DROP COLUMN "isSensitive" CASCADE;
ALTER TABLE emoji DROP COLUMN "roleIdsThatCanBeUsedThisEmojiAsReaction" CASCADE;
ALTER TABLE emoji ADD COLUMN width INTEGER;
ALTER TABLE emoji ADD COLUMN height INTEGER;

DROP TABLE flash CASCADE;
DROP TABLE flash_like CASCADE;

ALTER TABLE follow_request DROP COLUMN "withReplies" CASCADE;

ALTER TABLE following DROP COLUMN notify CASCADE;
ALTER TABLE following DROP COLUMN "withReplies" CASCADE;
ALTER TABLE following DROP COLUMN "isFollowerHibernated" CASCADE;

CREATE TABLE html_note_cache_entry (
    "noteId" character varying(32) NOT NULL,
    "updatedAt" timestamp with time zone,
    content text
);

CREATE TABLE html_user_cache_entry (
    "userId" character varying(32) NOT NULL,
    "updatedAt" timestamp with time zone,
    bio text,
    fields jsonb DEFAULT '[]'::jsonb NOT NULL
);

ALTER TABLE instance RENAME COLUMN "firstRetrievedAt" TO "caughtAt";
ALTER TABLE instance ADD COLUMN "latestRequestSentAt" TIMESTAMP WITH TIME ZONE; -- TODO: may want to set to now() or something
ALTER TABLE instance ADD COLUMN "latestStatus" INTEGER;
ALTER TABLE instance DROP COLUMN "isNSFW" CASCADE;
ALTER TABLE instance DROP COLUMN "moderationNote" CASCADE;

ALTER TABLE instance ADD COLUMN "lastCommunicatedAt" TIMESTAMP WITH TIME ZONE;
UPDATE instance SET "lastCommunicatedAt" = COALESCE("latestRequestReceivedAt", NOW());
ALTER TABLE instance ALTER COLUMN "lastCommunicatedAt" SET NOT NULL;

ALTER TABLE meta ALTER COLUMN name TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "maintainerName" TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "maintainerEmail" TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "disableRegistration" SET DEFAULT false;
ALTER TABLE meta ALTER COLUMN langs TYPE character varying(64)[];
ALTER TABLE meta ALTER COLUMN "hiddenTags" TYPE character varying(256)[];
ALTER TABLE meta ALTER COLUMN "blockedHosts" TYPE character varying(256)[];
ALTER TABLE meta ALTER COLUMN "mascotImageUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "mascotImageUrl" SET DEFAULT '/static-assets/badges/info.png';
ALTER TABLE meta ADD COLUMN "errorImageUrl" character varying(512) DEFAULT '/static-assets/badges/error.png';
ALTER TABLE meta ALTER COLUMN "bannerUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "iconUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "recaptchaSiteKey" TYPE character varying(64);
ALTER TABLE meta ALTER COLUMN "recaptchaSecretKey" TYPE character varying(64);
ALTER TABLE meta ALTER COLUMN "summalyProxy" TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN email TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "smtpHost" TYPE character varying(128);
ALTER TABLE meta ADD COLUMN "enableGithubIntegration" boolean DEFAULT false NOT NULL;
ALTER TABLE meta ADD COLUMN "githubClientId" character varying(128);
ALTER TABLE meta ADD COLUMN "githubClientSecret" character varying(128);
ALTER TABLE meta ADD COLUMN "enableDiscordIntegration" boolean DEFAULT false NOT NULL;
ALTER TABLE meta ADD COLUMN "discordClientId" character varying(128);
ALTER TABLE meta ADD COLUMN "discordClientSecret" character varying(128);
ALTER TABLE meta ALTER COLUMN "pinnedUsers" TYPE character varying(256)[];
ALTER TABLE meta ALTER COLUMN "termsOfServiceUrl" TYPE character varying(512);
ALTER TABLE meta RENAME COLUMN "termsOfServiceUrl" TO "ToSUrl";
ALTER TABLE meta ALTER COLUMN "repositoryUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://iceshrimp.dev/Crimekillz/trashposs';
ALTER TABLE meta ALTER COLUMN "repositoryUrl" SET NOT NULL;
ALTER TABLE meta ALTER COLUMN "feedbackUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://iceshrimp.dev/Crimekillz/trashposs/issues/new';
ALTER TABLE meta ALTER COLUMN "objectStorageBucket" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStoragePrefix" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStorageBaseUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStorageEndpoint" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStorageRegion" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStorageAccessKey" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "objectStorageSecretKey" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "hcaptchaSiteKey" TYPE character varying(64);
ALTER TABLE meta ALTER COLUMN "hcaptchaSecretKey" TYPE character varying(64);
ALTER TABLE meta ADD COLUMN "pinnedPages" character varying(512)[] DEFAULT '{/featured,/channels,/explore,/pages,/about-trashposs}'::character varying[] NOT NULL;
ALTER TABLE meta ALTER COLUMN "backgroundImageUrl" TYPE character varying(512);
ALTER TABLE meta ALTER COLUMN "logoImageUrl" TYPE character varying(512);
ALTER TABLE meta ADD COLUMN "pinnedClipId" character varying(32);
ALTER TABLE meta ADD COLUMN "allowedHosts" character varying(256)[] DEFAULT '{}'::character varying[] NOT NULL;
ALTER TABLE meta ADD COLUMN "secureMode" boolean DEFAULT true NOT NULL;
ALTER TABLE meta ADD COLUMN "privateMode" boolean DEFAULT false NOT NULL;
ALTER TABLE meta ALTER COLUMN "deeplAuthKey" TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "themeColor" TYPE character varying(512);
ALTER TABLE meta DROP COLUMN "setSensitiveFlagAutomatically" CASCADE;
ALTER TABLE meta ADD COLUMN "customMOTD" character varying(256)[] DEFAULT '{}'::character varying[] NOT NULL;
ALTER TABLE meta ADD COLUMN "customSplashIcons" character varying(256)[] DEFAULT '{}'::character varying[] NOT NULL;
ALTER TABLE meta DROP COLUMN "enableSensitiveMediaDetectionForVideos" CASCADE;
ALTER TABLE meta DROP COLUMN "enableTurnstile" CASCADE;
ALTER TABLE meta DROP COLUMN "turnstileSiteKey" CASCADE;
ALTER TABLE meta DROP COLUMN "turnstileSecretKey" CASCADE;
ALTER TABLE meta DROP COLUMN policies CASCADE;
ALTER TABLE meta DROP COLUMN "sensitiveWords" CASCADE;
ALTER TABLE meta DROP COLUMN "enableChartsForRemoteUser" CASCADE;
ALTER TABLE meta DROP COLUMN "enableChartsForFederatedInstances" CASCADE;
ALTER TABLE meta DROP COLUMN "serverRules" CASCADE;
ALTER TABLE meta DROP COLUMN "preservedUsernames" CASCADE;
ALTER TABLE meta DROP COLUMN "serverErrorImageUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "notFoundImageUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "infoImageUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "cacheRemoteSensitiveFiles" CASCADE;
ALTER TABLE meta DROP COLUMN "app192IconUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "app512IconUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "manifestJsonOverride" CASCADE;
ALTER TABLE meta DROP COLUMN "shortName" CASCADE;
ALTER TABLE meta DROP COLUMN "enableAchievements" CASCADE;
ALTER TABLE meta DROP COLUMN "impressumUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "privacyPolicyUrl" CASCADE;
ALTER TABLE meta DROP COLUMN "perLocalUserUserTimelineCacheMax" CASCADE;
ALTER TABLE meta DROP COLUMN "perRemoteUserUserTimelineCacheMax" CASCADE;
ALTER TABLE meta DROP COLUMN "perUserHomeTimelineCacheMax" CASCADE;
ALTER TABLE meta DROP COLUMN "perUserListTimelineCacheMax" CASCADE;
ALTER TABLE meta DROP COLUMN "notesPerOneAd" CASCADE;
ALTER TABLE meta ALTER COLUMN "silencedHosts" TYPE character varying(256)[];
ALTER TABLE meta DROP COLUMN "approvalRequiredForSignup" CASCADE;
ALTER TABLE meta DROP COLUMN "enableBotTrending" CASCADE;
ALTER TABLE meta DROP COLUMN "enableFanoutTimeline" CASCADE;
ALTER TABLE meta RENAME COLUMN "defaultLike" TO "defaultReaction";
ALTER TABLE meta ALTER COLUMN "defaultReaction" TYPE character varying(256);
ALTER TABLE meta ALTER COLUMN "defaultReaction" SET NOT NULL;
ALTER TABLE meta ALTER COLUMN "defaultReaction" SET DEFAULT '⭐';
ALTER TABLE meta DROP COLUMN "enableFanoutTimelineDbFallback" CASCADE;
ALTER TABLE meta DROP COLUMN "verifymailAuthKey" CASCADE;
ALTER TABLE meta DROP COLUMN "enableVerifymailApi" CASCADE;
ALTER TABLE meta RENAME COLUMN "bubbleInstances" TO "recommendedInstances";
ALTER TABLE meta DROP COLUMN "bannedEmailDomains" CASCADE;
ALTER TABLE meta DROP COLUMN "truemailInstance" CASCADE;
ALTER TABLE meta DROP COLUMN "truemailAuthKey" CASCADE;
ALTER TABLE meta DROP COLUMN "enableTruemailApi" CASCADE;
ALTER TABLE meta DROP COLUMN "enableMcaptcha" CASCADE;
ALTER TABLE meta DROP COLUMN "mcaptchaSitekey" CASCADE;
ALTER TABLE meta DROP COLUMN "mcaptchaSecretKey" CASCADE;
ALTER TABLE meta DROP COLUMN "mcaptchaInstanceUrl" CASCADE;
ALTER TABLE meta RENAME COLUMN "donationUrl" TO "donationLink";
ALTER TABLE meta ALTER COLUMN "donationLink" TYPE character varying(256);
ALTER TABLE meta DROP COLUMN "deeplFreeMode" CASCADE;
ALTER TABLE meta DROP COLUMN "deeplFreeInstance" CASCADE;
ALTER TABLE meta DROP COLUMN "prohibitedWords" CASCADE;
ALTER TABLE meta ADD COLUMN "libreTranslateApiUrl" character varying(512);
ALTER TABLE meta ADD COLUMN "libreTranslateApiKey" character varying(128);
ALTER TABLE meta ADD COLUMN "experimentalFeatures" jsonb DEFAULT '{}'::jsonb NOT NULL;
ALTER TABLE meta ADD COLUMN "autofollowedAccount" character varying(128);
ALTER TABLE meta DROP COLUMN "enableServiceWorker" CASCADE;
ALTER TABLE meta DROP COLUMN "proxyAccountId" CASCADE;

-- DIFFERENCE: sharkey swPublicKey and swPrivateKey are nullable.
ALTER TABLE meta ALTER COLUMN "swPublicKey" TYPE character varying(128);
ALTER TABLE meta ALTER COLUMN "swPrivateKey" TYPE character varying(128);

ALTER TABLE meta ADD COLUMN "localDriveCapacityMb" integer DEFAULT 1024 NOT NULL;
ALTER TABLE meta ADD COLUMN "remoteDriveCapacityMb" integer DEFAULT 32 NOT NULL;
ALTER TABLE meta ADD COLUMN "disableLocalTimeline" boolean DEFAULT false NOT NULL; 
ALTER TABLE meta ADD COLUMN "disableGlobalTimeline" boolean DEFAULT false NOT NULL;
ALTER TABLE meta ADD COLUMN "disableRecommendedTimeline" boolean DEFAULT true NOT NULL;

ALTER TABLE note ADD COLUMN score integer DEFAULT 0 NOT NULL;
ALTER TABLE note DROP COLUMN "reactionAcceptance" CASCADE;
ALTER TABLE note DROP COLUMN "clippedCount" CASCADE;
ALTER TABLE note DROP COLUMN "reactionAndUserPairCache" CASCADE;

ALTER TABLE note_edit RENAME COLUMN "newText" TO text;
ALTER TABLE note_edit DROP COLUMN "oldText" CASCADE;
ALTER TABLE note_edit DROP COLUMN "oldDate" CASCADE;

CREATE TABLE notification ( 
    id character varying(32) NOT NULL,
    "createdAt" timestamp with time zone NOT NULL,
    "notifieeId" character varying(32) NOT NULL,
    "notifierId" character varying(32),
    "isRead" boolean DEFAULT false NOT NULL,   
    "noteId" character varying(32),
    reaction character varying(128),
    choice integer,
    "followRequestId" character varying(32),
    type notification_type_enum NOT NULL,
    "userGroupInvitationId" character varying(32),
    "customBody" character varying(2048),
    "customHeader" character varying(256),
    "customIcon" character varying(1024),
    "appAccessTokenId" character varying(32)
);


CREATE TABLE oauth_app (
    id character varying(32) NOT NULL,
    "createdAt" timestamp with time zone NOT NULL,
    "clientId" character varying(64) NOT NULL,
    "clientSecret" character varying(64) NOT NULL,
    name character varying(128) NOT NULL,
    website character varying(256),
    scopes character varying(64)[] NOT NULL,
    "redirectUris" character varying(512)[] NOT NULL
);


CREATE TABLE oauth_token (
    id character varying(32) NOT NULL,
    "createdAt" timestamp with time zone NOT NULL,
    "appId" character varying(32) NOT NULL,
    "userId" character varying(32) NOT NULL,
    code character varying(64) NOT NULL,
    token character varying(64) NOT NULL,
    active boolean NOT NULL,
    scopes character varying(64)[] NOT NULL,
    "redirectUri" character varying(512) NOT NULL
);

ALTER TABLE page ADD COLUMN "isPublic" boolean NOT NULL;

ALTER TABLE registration_ticket DROP COLUMN "expiresAt" CASCADE;
ALTER TABLE registration_ticket DROP COLUMN "usedAt" CASCADE;
ALTER TABLE registration_ticket DROP COLUMN "pendingUserId" CASCADE;
ALTER TABLE registration_ticket DROP COLUMN "createdById" CASCADE;
ALTER TABLE registration_ticket DROP COLUMN "usedById" CASCADE;

DROP TABLE retention_aggregation CASCADE;
DROP TABLE reversi_game CASCADE;
DROP TABLE reversi_matching CASCADE;
DROP TABLE role CASCADE;
DROP TABLE role_assignment CASCADE;

ALTER TABLE "user" RENAME COLUMN "isRoot" TO "isAdmin";
ALTER TABLE "user" ADD COLUMN "isModerator" boolean DEFAULT false NOT NULL;
ALTER TABLE "user" ADD COLUMN "driveCapacityOverrideMb" integer;
ALTER TABLE "user" DROP COLUMN "movedAt" CASCADE;
ALTER TABLE "user" DROP COLUMN "isHibernated" CASCADE;
ALTER TABLE "user" DROP COLUMN "backgroundId" CASCADE;
ALTER TABLE "user" DROP COLUMN "backgroundUrl" CASCADE;
ALTER TABLE "user" DROP COLUMN "backgroundBlurhash" CASCADE;
ALTER TABLE "user" DROP COLUMN approved CASCADE;
ALTER TABLE "user" DROP COLUMN "signupReason" CASCADE;
ALTER TABLE "user" DROP COLUMN "avatarDecorations" CASCADE;
ALTER TABLE "user" DROP COLUMN noindex CASCADE;

ALTER TABLE user_list ADD COLUMN "hideFromHomeTl" boolean DEFAULT false NOT NULL;
ALTER TABLE user_list DROP COLUMN "isPublic" CASCADE;

DROP TABLE user_list_favorite CASCADE;

ALTER TABLE user_list_membership RENAME TO user_list_joining;
ALTER TABLE user_list_joining DROP COLUMN "withReplies" CASCADE;
ALTER TABLE user_list_joining DROP COLUMN "userListUserId" CASCADE;

DROP TABLE user_memo CASCADE;

ALTER TABLE user_pending DROP COLUMN reason CASCADE;

ALTER TABLE user_profile ADD COLUMN integrations jsonb DEFAULT '{}'::jsonb NOT NULL;
ALTER TABLE user_profile ADD COLUMN "mutingNotificationTypes" user_profile_mutingnotificationtypes_enum[] DEFAULT '{}'::user_profile_mutingnotificationtypes_enum[] NOT NULL;
ALTER TABLE user_profile ALTER COLUMN "emailNotificationTypes" SET DEFAULT '["follow", "receiveFollowRequest", "groupInvited"]'::jsonb;
ALTER TABLE user_profile ALTER COLUMN "publicReactions" SET DEFAULT false;
ALTER TABLE user_profile ADD COLUMN mentions jsonb DEFAULT '[]'::jsonb NOT NULL;
ALTER TABLE user_profile DROP COLUMN "autoSensitive" CASCADE;
ALTER TABLE user_profile DROP COLUMN achievements CASCADE;
ALTER TABLE user_profile DROP COLUMN "loggedInDates" CASCADE;
ALTER TABLE user_profile DROP COLUMN "twoFactorBackupSecret" CASCADE;
ALTER TABLE user_profile DROP COLUMN listenbrainz CASCADE;
ALTER TABLE user_profile DROP COLUMN "verifiedLinks" CASCADE;
ALTER TABLE user_profile DROP COLUMN "notificationRecieveConfig" CASCADE;
ALTER TABLE user_profile DROP COLUMN "hardMutedWords" CASCADE;
ALTER TABLE user_profile RENAME COLUMN "followingVisibility" TO "ffVisibility";

ALTER TABLE user_security_key ALTER COLUMN "lastUsed" DROP DEFAULT;
ALTER TABLE user_security_key DROP COLUMN counter CASCADE;
ALTER TABLE user_security_key DROP COLUMN "credentialDeviceType" CASCADE;
ALTER TABLE user_security_key DROP COLUMN "credentialBackedUp" CASCADE;
ALTER TABLE user_security_key DROP COLUMN transports CASCADE;

-- primary keys
ALTER TABLE ONLY attestation_challenge ADD CONSTRAINT "PK_d0ba6786e093f1bcb497572a6b5" PRIMARY KEY (id, "userId");
ALTER TABLE ONLY html_note_cache_entry ADD CONSTRAINT "PK_6ef86ec901b2017cbe82d3a8286" PRIMARY KEY ("noteId");
ALTER TABLE ONLY html_user_cache_entry ADD CONSTRAINT "PK_920b9474e3c9cae3f3c37c057e1" PRIMARY KEY ("userId");
ALTER TABLE ONLY notification ADD CONSTRAINT "PK_705b6c7cdf9b2c2ff7ac7872cb7" PRIMARY KEY (id);
ALTER TABLE ONLY oauth_app ADD CONSTRAINT "PK_3256b97c0a3ee2d67240805dca4" PRIMARY KEY (id);
ALTER TABLE ONLY oauth_token ADD CONSTRAINT "PK_7e6a25a3cc4395d1658f5b89c73" PRIMARY KEY (id);

-- indices
CREATE INDEX "IDX_01f4581f114e0ebd2bbb876f0b" ON note_reaction USING btree ("createdAt");
CREATE INDEX "IDX_02878d441ceae15ce060b73daf" ON drive_folder USING btree ("createdAt");
CREATE INDEX "IDX_048a757923ed8b157e9895da53" ON app USING btree ("createdAt");
CREATE INDEX "IDX_080ab397c379af09b9d2169e5b" ON notification USING btree ("isRead");
CREATE INDEX "IDX_0fb627e1c2f753262a74f0562d" ON poll_vote USING btree ("createdAt");
CREATE INDEX "IDX_118ec703e596086fc4515acb39" ON announcement USING btree ("createdAt");
CREATE INDEX "IDX_11e71f2511589dcc8a4d3214f9" ON channel_following USING btree ("createdAt");
CREATE INDEX "IDX_25dfc71b0369b003a4cd434d0b" ON note USING btree ("attachedFileTypes");
CREATE INDEX "IDX_2cbeb4b389444bcf4379ef4273" ON oauth_token USING btree (token);
CREATE INDEX "IDX_2cd3b2a6b4cf0b910b260afe08" ON instance USING btree ("caughtAt");
CREATE INDEX "IDX_33f33cc8ef29d805a97ff4628b" ON notification USING btree (type);
CREATE INDEX "IDX_3b4e96eec8d36a8bbb9d02aa71" ON notification USING btree ("notifierId");
CREATE INDEX "IDX_3c601b70a1066d2c8b517094cb" ON notification USING btree ("notifieeId");
CREATE INDEX "IDX_47efb914aed1f72dd39a306c7b" ON attestation_challenge USING btree (challenge);
CREATE INDEX "IDX_51c063b6a133a9cb87145450f5" ON note USING btree ("fileIds");
CREATE INDEX "IDX_54ebcb6d27222913b908d56fd8" ON note USING btree (mentions);
CREATE INDEX "IDX_582f8fab771a9040a12961f3e7" ON following USING btree ("createdAt");
CREATE INDEX "IDX_605472305f26818cc93d1baaa7" ON user_list_joining USING btree ("userListId");
CREATE UNIQUE INDEX "IDX_65b61f406c811241e1315a2f82" ON oauth_app USING btree ("clientId");
CREATE INDEX "IDX_71cb7b435b7c0d4843317e7e16" ON channel USING btree ("createdAt");
CREATE INDEX "IDX_796a8c03959361f97dc2be1d5c" ON note USING btree ("visibleUserIds");
CREATE INDEX "IDX_88937d94d7443d9a99a76fa5c0" ON note USING btree (tags);
CREATE INDEX "IDX_8977c6037a7bc2cb0c84b6d4db" ON "user" USING btree ("isSuspended");
CREATE INDEX "IDX_8f1a239bd077c8864a20c62c2c" ON gallery_post USING btree ("createdAt");
CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON user_list_joining USING btree ("userId", "userListId");
CREATE INDEX "IDX_b11a5e627c41d4dc3170f1d370" ON notification USING btree ("createdAt");
CREATE INDEX "IDX_b9a354f7941c1e779f3b33aea6" ON blocking USING btree ("createdAt");
CREATE INDEX "IDX_c8dfad3b72196dd1d6b5db168a" ON drive_file USING btree ("createdAt");
CREATE INDEX "IDX_d1259a2c2b7bb413ff449e8711" ON renote_muting USING btree ("createdAt");
CREATE INDEX "IDX_d844bfc6f3f523a05189076efa" ON user_list_joining USING btree ("userId");
CREATE INDEX "IDX_db2098070b2b5a523c58181f74" ON abuse_user_report USING btree ("createdAt");
CREATE INDEX "IDX_dc5fe174a8b59025055f0ec136" ON oauth_token USING btree (code);
CREATE INDEX "IDX_e11e649824a45d8ed01d597fd9" ON "user" USING btree ("createdAt");
CREATE INDEX "IDX_e22bf6bda77b6adc1fd9e75c8c" ON notification USING btree ("appAccessTokenId");
CREATE INDEX "IDX_e7c0567f5261063592f022e9b5" ON note USING btree ("createdAt");
CREATE INDEX "IDX_f1a461a618fa1755692d0e0d59" ON attestation_challenge USING btree ("userId");
CREATE INDEX "IDX_f86d57fbca33c7a4e6897490cc" ON muting USING btree ("createdAt");
CREATE INDEX "IDX_fbb4297c927a9b85e9cefa2eb1" ON page USING btree ("createdAt");
CREATE INDEX "IDX_note_createdAt_userId" ON note USING btree ("createdAt", "userId");
CREATE INDEX "IDX_note_id_userHost" ON note USING btree (id, "userHost");
CREATE INDEX "IDX_note_url" ON note USING btree (url);
CREATE INDEX "IDX_note_userId_id" ON note USING btree ("userId", id);
CREATE INDEX note_text_fts_idx ON note USING gin (text gin_trgm_ops);

DROP INDEX "IDX_NOTE_FILE_IDS" CASCADE; -- the trashposs index is a btree, this one is gin, so can't just rename!
DROP INDEX "IDX_de22cd2b445eee31ae51cdbe99" CASCADE; -- ON public.user_profile USING btree (substr((birthday)::text, 6, 5));
DROP INDEX "IDX_f7b9d338207e40e768e4a5265a" CASCADE; -- ON public.instance USING btree ("caughtAt");

-- foreign keys
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710" FOREIGN KEY ("notifierId") REFERENCES "user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_3c601b70a1066d2c8b517094cb9" FOREIGN KEY ("notifieeId") REFERENCES "user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY oauth_token ADD CONSTRAINT "FK_6d3ef28ea647b1449ba79690874" FOREIGN KEY ("appId") REFERENCES oauth_app(id) ON DELETE CASCADE;
ALTER TABLE ONLY html_note_cache_entry ADD CONSTRAINT "FK_6ef86ec901b2017cbe82d3a8286" FOREIGN KEY ("noteId") REFERENCES note(id) ON DELETE CASCADE;
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_769cb6b73a1efe22ddf733ac453" FOREIGN KEY ("noteId") REFERENCES note(id) ON DELETE CASCADE;
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_8fe87814e978053a53b1beb7e98" FOREIGN KEY ("userGroupInvitationId") REFERENCES user_group_invitation(id) ON DELETE CASCADE;
ALTER TABLE ONLY html_user_cache_entry ADD CONSTRAINT "FK_920b9474e3c9cae3f3c37c057e1" FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_bd7fab507621e635b32cd31892c" FOREIGN KEY ("followRequestId") REFERENCES follow_request(id) ON DELETE CASCADE;
ALTER TABLE ONLY antenna ADD CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb" FOREIGN KEY ("userGroupJoiningId") REFERENCES user_group_joining(id) ON DELETE CASCADE;
ALTER TABLE ONLY notification ADD CONSTRAINT "FK_e22bf6bda77b6adc1fd9e75c8c9" FOREIGN KEY ("appAccessTokenId") REFERENCES access_token(id) ON DELETE CASCADE;
ALTER TABLE ONLY attestation_challenge ADD CONSTRAINT "FK_f1a461a618fa1755692d0e0d592" FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY oauth_token ADD CONSTRAINT "FK_f6b4b1ac66b753feab5d831ba04" FOREIGN KEY ("userId") REFERENCES "user"(id) ON DELETE CASCADE;

-- comments
COMMENT ON COLUMN abuse_user_report."createdAt" IS 'The created date of the AbuseUserReport.';
COMMENT ON COLUMN access_token."createdAt" IS 'The created date of the AccessToken.';
COMMENT ON COLUMN announcement."createdAt" IS 'The created date of the Announcement.';
COMMENT ON COLUMN announcement_read."createdAt" IS 'The created date of the AnnouncementRead.';
COMMENT ON COLUMN antenna."createdAt" IS 'The created date of the Antenna.';
COMMENT ON COLUMN app."createdAt" IS 'The created date of the App.';
COMMENT ON COLUMN attestation_challenge.challenge IS 'Hex-encoded sha256 hash of the challenge.';
COMMENT ON COLUMN attestation_challenge."createdAt" IS 'The date challenge was created for expiry purposes.';
COMMENT ON COLUMN attestation_challenge."registrationChallenge" IS 'Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.';
COMMENT ON COLUMN auth_session."createdAt" IS 'The created date of the AuthSession.';
COMMENT ON COLUMN blocking."createdAt" IS 'The created date of the Blocking.';
COMMENT ON COLUMN channel."createdAt" IS 'The created date of the Channel.';
COMMENT ON COLUMN channel_following."createdAt" IS 'The created date of the ChannelFollowing.';
COMMENT ON COLUMN clip."createdAt" IS 'The created date of the Clip.';
COMMENT ON COLUMN drive_file."createdAt" IS 'The created date of the DriveFile.';
COMMENT ON COLUMN drive_folder."createdAt" IS 'The created date of the DriveFolder.';
COMMENT ON COLUMN emoji.width IS 'Image width';
COMMENT ON COLUMN emoji.height IS 'Image height';
COMMENT ON COLUMN follow_request."createdAt" IS 'The created date of the FollowRequest.';
COMMENT ON COLUMN following."createdAt" IS 'The created date of the Following.';
COMMENT ON COLUMN gallery_post."createdAt" IS 'The created date of the GalleryPost.';
COMMENT ON COLUMN meta."localDriveCapacityMb" IS 'Drive capacity of a local user (MB)';
COMMENT ON COLUMN meta."remoteDriveCapacityMb" IS 'Drive capacity of a remote user (MB)';
COMMENT ON COLUMN moderation_log."createdAt" IS 'The created date of the ModerationLog.';
COMMENT ON COLUMN muting."createdAt" IS 'The created date of the Muting.';
COMMENT ON COLUMN note."createdAt" IS 'The created date of the Note.';
COMMENT ON COLUMN note_favorite."createdAt" IS 'The created date of the NoteFavorite.';
COMMENT ON COLUMN note_reaction."createdAt" IS 'The created date of the NoteReaction.';
COMMENT ON COLUMN notification."createdAt" IS 'The created date of the Notification.';
COMMENT ON COLUMN notification."notifieeId" IS 'The ID of recipient user of the Notification.';
COMMENT ON COLUMN notification."notifierId" IS 'The ID of sender user of the Notification.';
COMMENT ON COLUMN notification."isRead" IS 'Whether the notification was read.';
COMMENT ON COLUMN notification.type IS 'The type of the Notification.';
COMMENT ON COLUMN oauth_app."createdAt" IS 'The created date of the OAuth application';
COMMENT ON COLUMN oauth_app."clientId" IS 'The client id of the OAuth application';
COMMENT ON COLUMN oauth_app."clientSecret" IS 'The client secret of the OAuth application';
COMMENT ON COLUMN oauth_app.name IS 'The name of the OAuth application';
COMMENT ON COLUMN oauth_app.website IS 'The website of the OAuth application';
COMMENT ON COLUMN oauth_app.scopes IS 'The scopes requested by the OAuth application';
COMMENT ON COLUMN oauth_app."redirectUris" IS 'The redirect URIs of the OAuth application';
COMMENT ON COLUMN oauth_token."createdAt" IS 'The created date of the OAuth token';
COMMENT ON COLUMN oauth_token.code IS 'The auth code for the OAuth token';
COMMENT ON COLUMN oauth_token.token IS 'The OAuth token';
COMMENT ON COLUMN oauth_token.active IS 'Whether or not the token has been activated';
COMMENT ON COLUMN oauth_token.scopes IS 'The scopes requested by the OAuth token';
COMMENT ON COLUMN oauth_token."redirectUri" IS 'The redirect URI of the OAuth token';
COMMENT ON COLUMN page."createdAt" IS 'The created date of the Page.';
COMMENT ON COLUMN poll_vote."createdAt" IS 'The created date of the PollVote.';
COMMENT ON COLUMN promo_read."createdAt" IS 'The created date of the PromoRead.';
COMMENT ON COLUMN registry_item."createdAt" IS 'The created date of the RegistryItem.';
COMMENT ON COLUMN renote_muting."createdAt" IS 'The created date of the Muting.';
COMMENT ON COLUMN signin."createdAt" IS 'The created date of the Signin.';
COMMENT ON COLUMN "user"."createdAt" IS 'The created date of the User.';
COMMENT ON COLUMN "user"."isSilenced" IS 'Whether the User is silenced.';
COMMENT ON COLUMN "user"."isAdmin" IS 'Whether the User is the admin.';
COMMENT ON COLUMN "user"."isModerator" IS 'Whether the User is a moderator.';
COMMENT ON COLUMN "user"."driveCapacityOverrideMb" IS 'Overrides user drive capacity limit';
COMMENT ON COLUMN "user"."speakAsCat" IS 'Whether to speak as a cat if isCat.';
COMMENT ON COLUMN "user"."avatarUrl" IS 'The URL of the avatar DriveFile';
COMMENT ON COLUMN "user"."avatarBlurhash" IS 'The blurhash of the avatar DriveFile';
COMMENT ON COLUMN "user"."bannerUrl" IS 'The URL of the banner DriveFile';
COMMENT ON COLUMN "user"."bannerBlurhash" IS 'The blurhash of the banner DriveFile';
COMMENT ON COLUMN user_list."createdAt" IS 'The created date of the UserList.';
COMMENT ON COLUMN user_list."hideFromHomeTl" IS 'Whether posts from list members should be hidden from the home timeline.';
COMMENT ON COLUMN user_list_joining."createdAt" IS 'The created date of the UserListJoining.';
COMMENT ON COLUMN user_note_pining."createdAt" IS 'The created date of the UserNotePinings.';
COMMENT ON COLUMN user_security_key."publicKey" IS 'Variable-length public key used to verify attestations (hex-encoded).';
COMMENT ON COLUMN user_security_key."lastUsed" IS 'The date of the last time the UserSecurityKey was successfully validated.';
COMMENT ON COLUMN webhook."createdAt" IS 'The created date of the Antenna.';

-- lie to typeorm
TRUNCATE migrations;
COPY migrations (id, "timestamp", name) FROM stdin;
1	1000000000000	Init1000000000000
2	1556348509290	Pages1556348509290
3	1556746559567	UserProfile1556746559567
4	1557476068003	PinnedUsers1557476068003
5	1557761316509	AddSomeUrls1557761316509
6	1557932705754	ObjectStorageSetting1557932705754
7	1558072954435	PageLike1558072954435
8	1558103093633	UserGroup1558103093633
9	1558257926829	UserGroupInvite1558257926829
10	1558266512381	UserListJoining1558266512381
11	1561706992953	webauthn1561706992953
12	1561873850023	ChartIndexes1561873850023
13	1562422242907	PasswordLessLogin1562422242907
14	1562444565093	PinnedPage1562444565093
15	1562448332510	PageTitleHideOption1562448332510
16	1562869971568	ModerationLog1562869971568
17	1563757595828	UsedUsername1563757595828
18	1565634203341	room1565634203341
19	1571220798684	CustomEmojiCategory1571220798684
20	1572760203493	nodeinfo1572760203493
21	1576269851876	TalkFederationId1576269851876
22	1576869585998	ProxyRemoteFiles1576869585998
23	1579267006611	v121579267006611
24	1579270193251	v1221579270193251
25	1579282808087	v1231579282808087
26	1579544426412	v1241579544426412
27	1579977526288	v1251579977526288
28	1579993013959	v1261579993013959
29	1580069531114	v1271580069531114
30	1580148575182	v1281580148575182
31	1580154400017	v1291580154400017
32	1580276619901	v12101580276619901
33	1580331224276	v12111580331224276
34	1580508795118	v12121580508795118
35	1580543501339	v12131580543501339
36	1580864313253	v12141580864313253
37	1581526429287	userGroupInvitation1581526429287
38	1581695816408	userGroupAntenna1581695816408
39	1581708415836	driveUserFolderIdIndex1581708415836
40	1581979837262	promo1581979837262
41	1582019042083	featuredInjecttion1582019042083
42	1582210532752	antennaExclude1582210532752
43	1582875306439	noteReactionLength1582875306439
44	1585361548360	miauth1585361548360
45	1585385921215	customNotification1585385921215
46	1585772678853	apUrl1585772678853
47	1586624197029	AddObjectStorageUseProxy1586624197029
48	1586641139527	remoteReaction1586641139527
49	1586708940386	pageAiScript1586708940386
50	1588044505511	hCaptcha1588044505511
51	1589023282116	pubRelay1589023282116
52	1595075960584	blurhash1595075960584
53	1595077605646	blurhashForAvatarBanner1595077605646
54	1595676934834	instanceIconUrl1595676934834
55	1595771249699	wordMute1595771249699
56	1595782306083	wordMute21595782306083
57	1596548170836	channel1596548170836
58	1596786425167	channel21596786425167
59	1597230137744	objectStorageSetPublicRead1597230137744
60	1597236229720	IncludingNotificationTypes1597236229720
61	1597385880794	addSensitiveIndex1597385880794
62	1597459042300	channelUnread1597459042300
63	1597893996136	ChannelNoteIdDescIndex1597893996136
64	1600353287890	mutingNotificationTypes1600353287890
65	1603094348345	refineAbuseUserReport1603094348345
66	1603095701770	refineAbuseUserReport21603095701770
67	1603776877564	instanceThemeColor1603776877564
68	1603781553011	instanceFavicon1603781553011
69	1604821689616	deleteAutoWatch1604821689616
70	1605408848373	clipDescription1605408848373
71	1605408971051	comments1605408971051
72	1605585339718	instancePinnedPages1605585339718
73	1605965516823	instanceImages1605965516823
74	1606191203881	noCrawle1606191203881
75	1607151207216	instancePinnedClip1607151207216
76	1607353487793	isExplorable1607353487793
77	1610277136869	registry1610277136869
78	1610277585759	registry21610277585759
79	1610283021566	registry31610283021566
80	1611354329133	followersUri1611354329133
81	1611397665007	gallery1611397665007
82	1611547387175	objectStorageS3ForcePathStyle1611547387175
83	1612619156584	announcementEmail1612619156584
84	1613155914446	emailNotificationTypes1613155914446
85	1613181457597	userLang1613181457597
86	1613503367223	useBigintForDriveUsage1613503367223
87	1615965918224	chartV21615965918224
88	1615966519402	chartV221615966519402
89	1618637372000	userLastActiveDate1618637372000
90	1618639857000	userHideOnlineStatus1618639857000
91	1619942102890	passwordReset1619942102890
92	1620019354680	ad1620019354680
93	1620364649428	ad21620364649428
94	1621479946000	addNoteIndexes1621479946000
95	1622679304522	userProfileDescriptionLength1622679304522
96	1622681548499	logMessageLength1622681548499
97	1626509500668	fixRemoteFileProxy1626509500668
98	1626733991004	allowlistSecureMode1626733991004
99	1629004542760	chartReindex1629004542760
100	1629024377804	deeplIntegration1629024377804
101	1629288472000	fixChannelUserId1629288472000
102	1629512953000	isUserDeleted1629512953000
103	1629778475000	deeplIntegration21629778475000
104	1629833361000	addShowTLReplies1629833361000
105	1629968054000	userInstanceBlocks1629968054000
106	1633068642000	emailRequiredForSignup1633068642000
107	1633071909016	userPending1633071909016
108	1634486652000	userPublicReactions1634486652000
109	1634902659689	deleteLog1634902659689
110	1635500777168	noteThreadMute1635500777168
111	1636197624383	ffVisibility1636197624383
112	1636697408073	removeViaMobile1636697408073
113	1637320813000	forwardedReport1637320813000
114	1639325650583	chartV31639325650583
115	1642611822809	emojiUrl1642611822809
116	1642613870898	driveFileWebpublicType1642613870898
117	1643963705770	chartV41643963705770
118	1643966656277	chartV51643966656277
119	1643967331284	chartV61643967331284
120	1644010796173	convertHardMutes1644010796173
121	1644058404077	chartV71644058404077
122	1644059847460	chartV81644059847460
123	1644060125705	chartV91644060125705
124	1644073149413	chartV101644073149413
125	1644095659741	chartV111644095659741
126	1644328606241	chartV121644328606241
127	1644331238153	chartV131644331238153
128	1644344266289	chartV141644344266289
129	1644395759931	instanceThemeColor1644395759931
130	1644481657998	chartV151644481657998
131	1644551208096	followingIndexes1644551208096
132	1645340161439	removeMaxNoteTextLength1645340161439
133	1645599900873	federationChartPubsub1645599900873
134	1646143552768	instanceDefaultTheme1646143552768
135	1646387162108	muteExpiresAt1646387162108
136	1646549089451	pollEndedNotification1646549089451
137	1646633030285	chartFederationActive1646633030285
138	1646655454495	removeInstanceDriveColumns1646655454495
139	1646732390560	chartFederationActiveSubPub1646732390560
140	1648548247382	webhook1648548247382
141	1648816172177	webhook21648816172177
142	1651224615271	foreignKeyReports1651224615271
143	1652859567549	uniformThemecolor1652859567549
144	1655368940105	nsfwDetection1655368940105
145	1655371960534	nsfwDetection21655371960534
146	1655388169582	nsfwDetection31655388169582
147	1655393015659	nsfwDetection41655393015659
148	1655813815729	driveCapacityOverrideMb1655813815729
149	1655918165614	userIp1655918165614
150	1656122560740	fileIp1656122560740
151	1656251734807	nsfwDetection51656251734807
152	1656328812281	ip21656328812281
153	1656408772602	nsfwDetection61656408772602
154	1656772790599	userModerationNote1656772790599
155	1657346559800	activeEmailValidation1657346559800
156	1658203170545	calckey1658203170545
157	1658656633972	noteRepliesFunction1658656633972
158	1658939464003	CustomMOTD1658939464003
159	1658941974648	CustomSplashIcons1658941974648
160	1658981842728	FixFirefish1658981842728
161	1659042130648	RecommendedTimeline1659042130648
162	1660068273737	GuestTimeline1660068273737
163	1665091090561	addRenoteMuting1665091090561
164	1668828368510	Page1668828368510
165	1668831378728	FixFirefishAgain1668831378728
166	1669138716634	whetherPushNotifyToSendReadMessage1669138716634
167	1669288094000	addMovedToAndKnownAs1669288094000
168	1671199573000	addFkAbuseUserReportTargetUserIdToUserId1671199573000
169	1671388343000	FirefishRepoMove1671388343000
170	1672882664294	DefaultReaction1672882664294
171	1673336077243	PollChoiceLength1673336077243
172	1676093997212	AntennaInstances1676093997212
173	1677935903517	DriveComment1677935903517
174	1678426061773	tweakVarcharLength1678426061773
175	1678945242650	addPropsForCustomEmoji1678945242650
176	1679269929000	FixRepo1679269929000
177	1680375641101	CleanCharts1680375641101
178	1680426269172	SpeakAsCat1680426269172
179	1682753227899	NoteEdit1682753227899
180	1682777547198	LibreTranslate1682777547198
181	1682891890317	InstanceSilence1682891890317
182	1682891891317	AddHiddenPosts1682891891317
183	1683682889948	PreventAiLearning1683682889948
184	1683980686995	ExperimentalFeatures1683980686995
185	1684206886988	RemoveShowTimelineReplies1684206886988
186	1684494870830	EmojiSize1684494870830
187	1688280713783	AddMetaOptions1688280713783
188	1688845537045	AnnouncementPopup1688845537045
189	1689136347561	DonationLink1689136347561
190	1689739513827	FirefishRepo1689739513827
191	1689965609061	IceshrimpRepo1689965609061
192 1689965609062	TrashpossRepo1689965609062
193	1695747439252	DropReversi1695747439252
194	1695748502971	IndexNoteUrl1695748502971
195	1695748874491	DropAds1695748874491
196	1695749386779	InstanceAccountDomainCleanup1695749386779
197	1695749948350	MoveAntennaToCache1695749948350
198	1695861526125	IndexNoteUserId1695861526125
199	1697216726757	AutoGenerateVapidKeys1697216726757
200	1697226201723	AddOAuthTables1697226201723
201	1697246035867	IncreaseOAuthRedirecturisLength1697246035867
202	1697286869039	IncreaseOauthTokenRedirecturisLength1697286869039
203	1697289658422	ResyncWithOrm1697289658422
204	1697302438587	AddUserProfileMentions1697302438587
205	1697649475796	SecureModeDefaults1697649475796
206	1697663824168	RemoveNsfwDetection1697663824168
207	1697665612162	RemoveProxyAccount1697665612162
208	1697733603329	UserListOptions1697733603329
209	1700331070890	NoteTextFtsIdx1700331070890
210	1700517975122	UserAvatarBannerRefactor1700517975122
211	1700623165718	AddNoteIdUserhostIdx1700623165718
212	1700686908916	AddAutofollowedAccount1700686908916
213	1700962939886	AddHtmlCache1700962939886
214	1701069578019	RemoveTwitterIntegration1701069578019
215	1701108527387	ReworkHardMutes1701108527387
216	1701118152149	IncreaseHostCharLimit1701118152149
217	1702680809638	AddNoteCreatedatUseridIdx1702680809638
218	1702744857694	UserIssuspendedIdx1702744857694
\.

SELECT pg_catalog.setval('public.migrations_id_seq', 217, true);

-- this is just for my personal fork, you won't need it
DROP FUNCTION IF EXISTS kopper_fts_reindex_file_comment CASCADE;
DROP FUNCTION IF EXISTS kopper_fts_reindex_note CASCADE;
DROP FUNCTION IF EXISTS kopper_fts_generate_search_vector CASCADE;
ALTER TABLE note DROP COLUMN IF EXISTS kopper_fts_search_vector CASCADE;

COMMIT; -- cross your fingers
