This commit is contained in:
Omer Sabic 2024-05-06 18:53:30 +02:00
parent 933db8828b
commit 6cb3d035e6
15 changed files with 1536 additions and 35 deletions

View File

@ -0,0 +1 @@
ALTER TABLE "articles" ADD COLUMN "created_at" timestamp;

View File

@ -0,0 +1 @@
ALTER TABLE "articles" ALTER COLUMN "created_at" SET DEFAULT now();

View File

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS "signups" (
"email" text NOT NULL,
"site_id" uuid NOT NULL,
"created_at" timestamp DEFAULT now()
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "signups" ADD CONSTRAINT "signups_site_id_sites_id_fk" FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@ -0,0 +1 @@
ALTER TABLE "articles" ADD COLUMN "is_public" boolean;

View File

@ -0,0 +1 @@
ALTER TABLE "articles" ALTER COLUMN "is_public" SET DEFAULT true;

View File

@ -0,0 +1,227 @@
{
"id": "8177d5c3-dd38-41fc-83ae-a544aa8dc9a4",
"prevId": "10737e50-695f-41a3-94b4-e34439850a06",
"version": "5",
"dialect": "pg",
"tables": {
"articles": {
"name": "articles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"source_video_id": {
"name": "source_video_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"seo_slug": {
"name": "seo_slug",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"articles_site_id_sites_id_fk": {
"name": "articles_site_id_sites_id_fk",
"tableFrom": "articles",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"google_access_token": {
"name": "google_access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"google_refresh_token": {
"name": "google_refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sites": {
"name": "sites",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sites_user_id_users_id_fk": {
"name": "sites_user_id_users_id_fk",
"tableFrom": "sites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"google_id": {
"name": "google_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"channel_id": {
"name": "channel_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"uploads_playlist_id": {
"name": "uploads_playlist_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

View File

@ -0,0 +1,228 @@
{
"id": "35af811f-9d91-4524-b269-c7e3f8eb0ce8",
"prevId": "8177d5c3-dd38-41fc-83ae-a544aa8dc9a4",
"version": "5",
"dialect": "pg",
"tables": {
"articles": {
"name": "articles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"source_video_id": {
"name": "source_video_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"seo_slug": {
"name": "seo_slug",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"articles_site_id_sites_id_fk": {
"name": "articles_site_id_sites_id_fk",
"tableFrom": "articles",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"google_access_token": {
"name": "google_access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"google_refresh_token": {
"name": "google_refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sites": {
"name": "sites",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sites_user_id_users_id_fk": {
"name": "sites_user_id_users_id_fk",
"tableFrom": "sites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"google_id": {
"name": "google_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"channel_id": {
"name": "channel_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"uploads_playlist_id": {
"name": "uploads_playlist_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

View File

@ -0,0 +1,271 @@
{
"id": "55d4edf3-4ec8-4c89-ae81-2c9199efea11",
"prevId": "35af811f-9d91-4524-b269-c7e3f8eb0ce8",
"version": "5",
"dialect": "pg",
"tables": {
"articles": {
"name": "articles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"source_video_id": {
"name": "source_video_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"seo_slug": {
"name": "seo_slug",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"articles_site_id_sites_id_fk": {
"name": "articles_site_id_sites_id_fk",
"tableFrom": "articles",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"google_access_token": {
"name": "google_access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"google_refresh_token": {
"name": "google_refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"signups": {
"name": "signups",
"schema": "",
"columns": {
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"signups_site_id_sites_id_fk": {
"name": "signups_site_id_sites_id_fk",
"tableFrom": "signups",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sites": {
"name": "sites",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sites_user_id_users_id_fk": {
"name": "sites_user_id_users_id_fk",
"tableFrom": "sites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"google_id": {
"name": "google_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"channel_id": {
"name": "channel_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"uploads_playlist_id": {
"name": "uploads_playlist_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

View File

@ -0,0 +1,277 @@
{
"id": "bd993656-45ee-4b6d-9875-e47a5674f46e",
"prevId": "55d4edf3-4ec8-4c89-ae81-2c9199efea11",
"version": "5",
"dialect": "pg",
"tables": {
"articles": {
"name": "articles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"source_video_id": {
"name": "source_video_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"seo_slug": {
"name": "seo_slug",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_public": {
"name": "is_public",
"type": "boolean",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"articles_site_id_sites_id_fk": {
"name": "articles_site_id_sites_id_fk",
"tableFrom": "articles",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"google_access_token": {
"name": "google_access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"google_refresh_token": {
"name": "google_refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"signups": {
"name": "signups",
"schema": "",
"columns": {
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"signups_site_id_sites_id_fk": {
"name": "signups_site_id_sites_id_fk",
"tableFrom": "signups",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sites": {
"name": "sites",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sites_user_id_users_id_fk": {
"name": "sites_user_id_users_id_fk",
"tableFrom": "sites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"google_id": {
"name": "google_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"channel_id": {
"name": "channel_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"uploads_playlist_id": {
"name": "uploads_playlist_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

View File

@ -0,0 +1,278 @@
{
"id": "06039986-7308-452a-9a12-12c317b3f75b",
"prevId": "bd993656-45ee-4b6d-9875-e47a5674f46e",
"version": "5",
"dialect": "pg",
"tables": {
"articles": {
"name": "articles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"source_video_id": {
"name": "source_video_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"seo_slug": {
"name": "seo_slug",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_public": {
"name": "is_public",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"articles_site_id_sites_id_fk": {
"name": "articles_site_id_sites_id_fk",
"tableFrom": "articles",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"google_access_token": {
"name": "google_access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"google_refresh_token": {
"name": "google_refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"signups": {
"name": "signups",
"schema": "",
"columns": {
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"site_id": {
"name": "site_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"signups_site_id_sites_id_fk": {
"name": "signups_site_id_sites_id_fk",
"tableFrom": "signups",
"tableTo": "sites",
"columnsFrom": [
"site_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sites": {
"name": "sites",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sites_user_id_users_id_fk": {
"name": "sites_user_id_users_id_fk",
"tableFrom": "sites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"google_id": {
"name": "google_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"channel_id": {
"name": "channel_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"uploads_playlist_id": {
"name": "uploads_playlist_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

View File

@ -57,6 +57,41 @@
"when": 1714378789934, "when": 1714378789934,
"tag": "0007_familiar_thor_girl", "tag": "0007_familiar_thor_girl",
"breakpoints": true "breakpoints": true
},
{
"idx": 8,
"version": "5",
"when": 1714739422527,
"tag": "0008_jittery_piledriver",
"breakpoints": true
},
{
"idx": 9,
"version": "5",
"when": 1714739443139,
"tag": "0009_opposite_slayback",
"breakpoints": true
},
{
"idx": 10,
"version": "5",
"when": 1714739875253,
"tag": "0010_same_famine",
"breakpoints": true
},
{
"idx": 11,
"version": "5",
"when": 1714856795946,
"tag": "0011_serious_tenebrous",
"breakpoints": true
},
{
"idx": 12,
"version": "5",
"when": 1714859887333,
"tag": "0012_nervous_penance",
"breakpoints": true
} }
] ]
} }

View File

@ -1,4 +1,4 @@
import { date, foreignKey, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"; import { boolean, date, foreignKey, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
export const users = pgTable("users", { export const users = pgTable("users", {
id: uuid("id").defaultRandom().primaryKey(), id: uuid("id").defaultRandom().primaryKey(),
@ -15,13 +15,13 @@ export const sessions = pgTable("sessions", {
access_token: text("google_access_token"), access_token: text("google_access_token"),
refresh_token: text("google_refresh_token"), refresh_token: text("google_refresh_token"),
expires_at: timestamp("expires_at") expires_at: timestamp("expires_at")
}) });
export const sites = pgTable("sites", { export const sites = pgTable("sites", {
id: uuid("id").defaultRandom().primaryKey(), id: uuid("id").defaultRandom().primaryKey(),
user_id: uuid("user_id").references(() => users.id), user_id: uuid("user_id").references(() => users.id),
name: text("name") name: text("name")
}) });
export const articles = pgTable("articles", { export const articles = pgTable("articles", {
id: uuid("id").defaultRandom().primaryKey(), id: uuid("id").defaultRandom().primaryKey(),
@ -29,5 +29,13 @@ export const articles = pgTable("articles", {
content: text("content"), content: text("content"),
source_video_id: text("source_video_id"), source_video_id: text("source_video_id"),
title: text("title"), title: text("title"),
seo_slug: text("seo_slug") seo_slug: text("seo_slug"),
}) is_public: boolean("is_public").default(true),
created_at: timestamp("created_at").defaultNow()
});
export const signups = pgTable("signups", {
email: text("email").notNull(),
site_id: uuid("site_id").references(() => sites.id).notNull(),
created_at: timestamp("created_at").defaultNow()
});

View File

@ -1,9 +1,10 @@
import { eq } from "drizzle-orm"; import { eq, getTableColumns, or } from "drizzle-orm";
import { db } from "../db/index.js"; import { db } from "../db/index.js";
import { authMiddleware, authMiddlewareFn } from "../modules/middleware.js"; import { authMiddleware, authMiddlewareFn } from "../modules/middleware.js";
import { getAccessToken, getCaptionText, getChannelInfo, getVideoCaptions, parseTextFromCaptions } from "../utils/youtube.js"; import { getAccessToken, getCaptionText, getChannelInfo, getVideoCaptions, parseTextFromCaptions } from "../utils/youtube.js";
import { articles as articlesTable, sites } from "../db/schemas.js"; import { articles, articles as articlesTable, signups as signupsTable, sites, users } from "../db/schemas.js";
import { createBlogFromCaptions } from "../utils/ai.js"; import { createBlogFromCaptions } from "../utils/ai.js";
import { createArticleSlug } from "../utils/index.js";
/** /**
* *
@ -15,7 +16,7 @@ export const blogRoutes = (fastify, _, done) => {
fastify.get("/", async (request, response) => { fastify.get("/", async (request, response) => {
try { try {
const mine = request.query.mine != 'false' || true; const mine = request.query.mine != 'false' ?? true;
const blog_id = request.query.blog_id; const blog_id = request.query.blog_id;
if (!mine && !blog_id) { if (!mine && !blog_id) {
response.send({ response.send({
@ -24,30 +25,93 @@ export const blogRoutes = (fastify, _, done) => {
}) })
} }
let clause; let clause;
let site;
if (mine) { if (mine) {
if (!(await authMiddlewareFn(request, response))) return; if (!(await authMiddlewareFn(request, response))) return;
clause = eq(sites.user_id, request.session.user_id); [site] = await db.select().from(sites).where(eq(sites.user_id, request.session.user_id));
}
else {
[site] = await db.select().from(sites).where(eq(sites.id, request.query.blog_id));
} }
clause = eq(articlesTable.site_id, site.id);
if (mine == false) { if (mine == false) {
clause = eq(sites.user_id, request.query.blog_id); clause = eq(articlesTable.site_id, request.query.blog_id);
} }
// const access_token = await getAccessToken(fastify, request); // const access_token = await getAccessToken(fastify, request);
// const channel = await getChannelInfo(access_token); // const channel = await getChannelInfo(access_token);
const results = await db.select({ id: articlesTable.id, title: articlesTable.title, seo_slug: articlesTable.seo_slug }).from(articlesTable).where(clause).limit(10);
const articles = await db.select().from(articlesTable).leftJoin(sites, articlesTable.site_id == sites.id).where(clause); // console.log(articles)
response.send({ response.send({
success: true, success: true,
articles articles: results,
site,
}); });
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); });
fastify.get("/article", {
schema: {
querystring: {
id: {
type: "string"
}
}
}
}, async (req, reply) => {
const [result] = await db.select().from(articlesTable).where(or(eq(articlesTable.seo_slug, req.query.id), eq(articlesTable.id, req.query.id)));
reply.send({
success: true,
article: result
});
});
fastify.put("/article", {
schema: {
body: {
type: "object",
properties: {
id: {
type: "string"
},
is_public: {
type: "boolean"
},
content: {
type: "string"
},
title: {
type: "string"
},
},
required: ["id"]
}
}
}, async (req, reply) => {
const [article] = await db.select(getTableColumns(articles)).from(articles).leftJoin(sites, eq(sites.id, articles.site_id)).where(eq(sites.user_id, req.session.user_id));
if (!article) {
reply.status(404).send({
success: false,
message: "This article does not exist."
});
return;
}
if (Object.keys(req.body).length > 1) {
await db.update(articles).set(JSON.parse(JSON.stringify({ ...req.body, id: undefined }))).where(eq(articles.id, req.body.id)).limit(1);
}
reply.send({
success: true
});
return;
});
fastify.post("/create", { fastify.post("/create", {
schema: { schema: {
body: { body: {
@ -74,30 +138,78 @@ export const blogRoutes = (fastify, _, done) => {
const captions = await getVideoCaptions(access_token, req.body.video_id); const captions = await getVideoCaptions(access_token, req.body.video_id);
const preferred_caption_id = captions.find(x => x.snippet.language == 'en').id; const preferred_caption_id = captions.find(x => x.snippet.language == 'en').id;
reply.send({
success: true
});
const caption_body = await getCaptionText(access_token, preferred_caption_id); const caption_body = await getCaptionText(access_token, preferred_caption_id);
const caption_text = parseTextFromCaptions(caption_body).substring(28); const caption_text = parseTextFromCaptions(caption_body).substring(28);
console.log(caption_text);
const blog_content = await createBlogFromCaptions(caption_text, req.body); const blog_content = await createBlogFromCaptions(caption_text, req.body);
const blog_content_json = JSON.parse(blog_content);
// TODO: once I add multiple sites per user, this should come from the client // TODO: once I add multiple sites per user, this should come from the client
const site = await db.select().from(sites).where(eq(sites.user_id, req.session.user_id)); const site = await db.select().from(sites).where(eq(sites.user_id, req.session.user_id));
const article = await db.insert(articlesTable).values({ await db.insert(articlesTable).values({
site_id: site[0].id, site_id: site[0].id,
content: blog_content, title: blog_content_json.title,
source_video_id: req.body.video_id content: blog_content_json.content,
source_video_id: req.body.video_id,
seo_slug: createArticleSlug(blog_content_json.title)
}).returning({ id: articlesTable.id }); }).returning({ id: articlesTable.id });
reply.send({
success: true,
article_id: article[0].id
});
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}) });
fastify.register(authMiddleware); fastify.get("/signups", {
preValidation: authMiddlewareFn
}, async (req, reply) => {
const site = await db.select().from(sites).where(eq(sites.user_id, req.session.user_id));
if (site[0]?.user_id != req.session.user_id) {
reply.status(403).send({ success: false });
return;
}
const signups = await db.select().from(signupsTable).where(eq(signupsTable.site_id, site[0].id));
reply.send({
success: true,
signups
});
});
fastify.post("/signup", {
schema: {
body: {
site_id: {
type: "string"
},
email: {
type: "string",
format: "email"
}
}
}
}, async (req, reply) => {
const inserted = await db.insert(signupsTable).values({
email: req.body.email,
site_id: req.body.site_id
});
if (inserted.rowCount != 1) {
reply.status(400).send({
success: false,
message: "Problem when signing up email"
});
return;
}
reply.send({
success: true
});
});
done(); done();
}; };

View File

@ -23,13 +23,14 @@ async function cf_prompt(prompt, model = defaultModel) {
return res; return res;
} }
async function promptGPT(prompt, model = "gpt-3-turbo") { async function promptGPT(prompt, {model = "gpt-3.5-turbo", max_tokens = 1024}) {
const options = { const options = {
method: 'POST', method: 'POST',
headers: { Authorization: 'Bearer pk-hevZzgTruHUMITZDvBqcIaLXWYtkxuTLkQkYecEfszfNHNBT', "Content-Type": "application/json" }, headers: { Authorization: 'Bearer sk-proj-P3cSwYJjZgnSRzil9vsAT3BlbkFJ9mqryDKqGJ2p0rm3z557', "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify({
"model": "pai-001-light", "model": "gpt-3.5-turbo",
"max_tokens": 512, "max_tokens": max_tokens,
"response_format": { "type": "json_object" },
"messages": [ "messages": [
{ {
"role": "user", "role": "user",
@ -39,8 +40,8 @@ async function promptGPT(prompt, model = "gpt-3-turbo") {
}) })
}; };
console.log("prompting pai-001...") console.log("prompting gpt-3.5-turbo...")
const res = await fetch('https://api.pawan.krd/pai-001/v1/chat/completions', options) const res = await fetch('https://api.openai.com/v1/chat/completions', options)
.then(response => { .then(response => {
return response.json(); return response.json();
}) })
@ -62,9 +63,16 @@ export async function createBlogFromCaptions(captions, {
format, format,
tone tone
} = {length: 500, language: "English", format: "summary", tone: "informal"}) { } = {length: 500, language: "English", format: "summary", tone: "informal"}) {
const prompt = `Please convert the following video transcript into a blog post. The approximate length should be around ${length || 500} characters, written in ${language || "English"}. The desired format of the blog post is a ${format || "summary"}. Please ensure the blog post has a ${tone || "informal"} tone throughout. Use markdown to format the article. You must always respond in the following json fromat: {"title": string, "content": string, "seo_friendly_slug": string}. \nHere is the transcript: ` // const prompt = `Convert the following video transcript into a blog post. The approximate length should be around ${length || 500} characters, written in ${language || "English"}. The desired format of the blog post is a ${format || "summary"}. Please ensure the blog post has a ${tone || "informal"} tone throughout. Use markdown to format the article. You must always respond in the following json fromat: {"title": string, "content": string, "seo_friendly_slug": string}. \nHere is the transcript: `
const prompt = `Convert the following video transcript into an engaging blog post. You must always respond in the following json fromat: {"title": string, "content": string, "seo_friendly_slug": string}. Do not include the title inside the content, it should only be reserved for the body of the article. Use markdown to format the article. \nHere is the transcript: `;
const result = await promptGPT(prompt + captions); const result = await promptGPT(prompt + captions, {
length: wordsToTokens(length)
});
console.log(result); console.log(result);
return result; return result;
} }
function wordsToTokens(n) {
return Math.ceil(n/0.75);
}

View File

@ -1,3 +1,45 @@
export * from "./env.js"; export * from "./env.js";
export * from "./logger.js"; export * from "./logger.js";
export * from "./redis.js"; export * from "./redis.js";
export * from "./ai.js";
export * from "./token.js";
export * from "./youtube.js";
/**
*
* @param {string} title
* @returns {string}
*/
export function createArticleSlug(title) {
const maxLength = 20;
const slug = title.toLowerCase().replace(/[^a-z0-9\s-]/g, '').trim().replace(/\s+/g, '-');
const randomChars = "-" + generateRandomChars(6);
// If slug is shorter than or equal to 12 characters, return it directly
if (slug.length <= maxLength) {
return slug + randomChars;
}
// Find the last space within the first 12 characters
const lastSpaceIndex = slug.substring(0, maxLength).lastIndexOf('-');
// If no space found, truncate slug to 12 characters
const truncatedSlug = lastSpaceIndex !== -1 ? slug.substring(0, lastSpaceIndex) : slug.substring(0, maxLength);
// Generate 6 random characters
// Concatenate the truncated slug and random characters
const finalSlug = truncatedSlug + randomChars;
return finalSlug;
}
function generateRandomChars(length) {
let result = '';
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}