Compare commits

..

3 Commits

Author SHA1 Message Date
4e95abf09f fix: update devil fruit extraction to handle redirects and ensure correct title retrieval
Some checks failed
Build Docker Image / build (push) Has been cancelled
2026-03-14 15:41:20 +01:00
66afda5101 Refactor code structure for improved readability and maintainability 2026-03-14 15:34:30 +01:00
a041a8caf5 Refactor database schema and update scraping logic for One Piece characters and arcs
- Updated database schema to include French names and adjusted field names for consistency.
- Modified scraping script to fetch and store French names for arcs and characters.
- Improved API calls to handle redirects and fetch additional data for characters.
- Enhanced data extraction methods for character attributes and devil fruits.
- Cleaned up code for better readability and maintainability.
2026-03-14 01:23:29 +01:00
25 changed files with 1475 additions and 11801 deletions

View File

@@ -1,156 +0,0 @@
CREATE TABLE `arc` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`startChapter` integer NOT NULL,
`endChapter` integer,
`url` text
);
--> statement-breakpoint
CREATE TABLE `character` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`gender` text,
`age` integer,
`affiliations` text,
`devilFruitId` text,
`hakiObservation` integer DEFAULT false,
`hakiArmament` integer DEFAULT false,
`hakiConqueror` integer DEFAULT false,
`bounty` integer DEFAULT 0,
`height` real,
`origin` text,
`firstAppearance` integer NOT NULL,
`pictureUrl` text,
`epithets` text,
`status` text,
`arcId` text,
`url` text,
`isInDailyMode` integer DEFAULT true,
FOREIGN KEY (`devilFruitId`) REFERENCES `devilFruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arcId`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `characterHistory` (
`id` text PRIMARY KEY NOT NULL,
`characterId` text,
`date` text,
`won` integer DEFAULT 0 NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`characterId`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `characterOverride` (
`characterId` text PRIMARY KEY NOT NULL,
`name` text,
`gender` text,
`age` integer,
`affiliations` text,
`devilFruitId` text,
`hakiObservation` integer,
`hakiArmament` integer,
`hakiConqueror` integer,
`bounty` integer,
`height` real,
`origin` text,
`firstAppearance` integer NOT NULL,
`pictureUrl` text,
`epithets` text,
`status` text,
`arcId` text,
`url` text,
`notes` text,
FOREIGN KEY (`characterId`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`devilFruitId`) REFERENCES `devilFruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arcId`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `characterScrapeValidation` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`gender` text,
`age` integer,
`affiliations` text,
`devilFruitId` text,
`hakiObservation` integer DEFAULT false,
`hakiArmament` integer DEFAULT false,
`hakiConqueror` integer DEFAULT false,
`bounty` integer,
`height` real,
`origin` text,
`firstAppearance` integer NOT NULL,
`pictureUrl` text,
`epithets` text,
`status` text,
`arcId` text,
`url` text,
FOREIGN KEY (`devilFruitId`) REFERENCES `devilFruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arcId`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `config` (
`key` text PRIMARY KEY NOT NULL,
`value` text
);
--> statement-breakpoint
CREATE TABLE `devilFruit` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`type` text,
`url` text
);
--> statement-breakpoint
CREATE UNIQUE INDEX `devilFruit_name_unique` ON `devilFruit` (`name`);--> statement-breakpoint
CREATE TABLE `account` (
`id` text PRIMARY KEY NOT NULL,
`account_id` text NOT NULL,
`provider_id` text NOT NULL,
`user_id` text NOT NULL,
`access_token` text,
`refresh_token` text,
`id_token` text,
`access_token_expires_at` integer,
`refresh_token_expires_at` integer,
`scope` text,
`password` text,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint
CREATE TABLE `session` (
`id` text PRIMARY KEY NOT NULL,
`expires_at` integer NOT NULL,
`token` text NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer NOT NULL,
`ip_address` text,
`user_agent` text,
`user_id` text NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint
CREATE TABLE `user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`email` text NOT NULL,
`email_verified` integer DEFAULT false NOT NULL,
`image` text,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
CREATE TABLE `verification` (
`id` text PRIMARY KEY NOT NULL,
`identifier` text NOT NULL,
`value` text NOT NULL,
`expires_at` integer NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
);
--> statement-breakpoint
CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);

View File

@@ -0,0 +1,194 @@
CREATE TABLE `arc` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`fr_name` text,
`start_chapter` integer NOT NULL,
`end_chapter` integer,
`url` text
);
--> statement-breakpoint
CREATE TABLE `character` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`fr_name` text,
`gender` text,
`age` integer,
`affiliations` text,
`devil_fruit_id` text,
`haki_observation` integer DEFAULT false,
`haki_armament` integer DEFAULT false,
`haki_conqueror` integer DEFAULT false,
`bounty` integer DEFAULT 0,
`height` real,
`origin` text,
`fr_origin` text,
`first_appearance` integer NOT NULL,
`picture_url` text,
`epithets` text,
`fr_epithets` text,
`status` text,
`arc_id` text,
`url` text,
`fr_url` text,
`is_in_daily_mode` integer DEFAULT false,
FOREIGN KEY (`devil_fruit_id`) REFERENCES `devil_fruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arc_id`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE TABLE `character_history` (
`id` text PRIMARY KEY NOT NULL,
`character_id` text,
`date` integer NOT NULL,
`won` integer DEFAULT 0 NOT NULL,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`character_id`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `character_history_date_unique` ON `character_history` (`date`);--> statement-breakpoint
CREATE TABLE `character_override` (
`character_id` text PRIMARY KEY NOT NULL,
`name` text,
`gender` text,
`age` integer,
`affiliations` text,
`devil_fruit_id` text,
`haki_observation` integer,
`haki_armament` integer,
`haki_conqueror` integer,
`bounty` integer,
`height` real,
`origin` text,
`first_appearance` integer,
`picture_url` text,
`epithets` text,
`status` text,
`arc_id` text,
`url` text,
`fr_url` text,
`notes` text,
FOREIGN KEY (`character_id`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`devil_fruit_id`) REFERENCES `devil_fruit`(`id`) ON UPDATE no action ON DELETE set null,
FOREIGN KEY (`arc_id`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE TABLE `character_scrape_validation` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`fr_name` text,
`gender` text,
`age` integer,
`affiliations` text,
`devil_fruit_id` text,
`haki_observation` integer DEFAULT false,
`haki_armament` integer DEFAULT false,
`haki_conqueror` integer DEFAULT false,
`bounty` integer,
`height` real,
`origin` text,
`fr_origin` text,
`first_appearance` integer NOT NULL,
`picture_url` text,
`epithets` text,
`fr_epithets` text,
`status` text,
`arc_id` text,
`url` text,
`fr_url` text,
FOREIGN KEY (`devil_fruit_id`) REFERENCES `devil_fruit`(`id`) ON UPDATE no action ON DELETE set null,
FOREIGN KEY (`arc_id`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE TABLE `config` (
`key` text PRIMARY KEY NOT NULL,
`value` text
);
--> statement-breakpoint
CREATE TABLE `devil_fruit` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`type` text,
`url` text
);
--> statement-breakpoint
CREATE UNIQUE INDEX `devil_fruit_name_unique` ON `devil_fruit` (`name`);--> statement-breakpoint
CREATE TABLE `friendship` (
`id` text PRIMARY KEY NOT NULL,
`requester_id` text NOT NULL,
`addressee_id` text NOT NULL,
`status` text DEFAULT 'pending' NOT NULL,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`requester_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`addressee_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `friendship_requester_id_addressee_id_unique` ON `friendship` (`requester_id`,`addressee_id`);--> statement-breakpoint
CREATE TABLE `user_character_history` (
`id` text PRIMARY KEY NOT NULL,
`user_id` text,
`character_history_id` text,
`try_count` integer NOT NULL,
`tried_character_ids` text,
`created_at` integer NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`character_history_id`) REFERENCES `character_history`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `user_character_history_user_id_character_history_id_unique` ON `user_character_history` (`user_id`,`character_history_id`);--> statement-breakpoint
CREATE TABLE `account` (
`id` text PRIMARY KEY NOT NULL,
`account_id` text NOT NULL,
`provider_id` text NOT NULL,
`user_id` text NOT NULL,
`access_token` text,
`refresh_token` text,
`id_token` text,
`access_token_expires_at` integer,
`refresh_token_expires_at` integer,
`scope` text,
`password` text,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint
CREATE TABLE `session` (
`id` text PRIMARY KEY NOT NULL,
`expires_at` integer NOT NULL,
`token` text NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer NOT NULL,
`ip_address` text,
`user_agent` text,
`user_id` text NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint
CREATE TABLE `user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`username` text NOT NULL,
`email` text NOT NULL,
`email_verified` integer DEFAULT false NOT NULL,
`image` text,
`is_admin` integer DEFAULT false NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `user_username_unique` ON `user` (`username`);--> statement-breakpoint
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
CREATE TABLE `verification` (
`id` text PRIMARY KEY NOT NULL,
`identifier` text NOT NULL,
`value` text NOT NULL,
`expires_at` integer NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
);
--> statement-breakpoint
CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);

View File

@@ -1,30 +0,0 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_characterOverride` (
`characterId` text PRIMARY KEY NOT NULL,
`name` text,
`gender` text,
`age` integer,
`affiliations` text,
`devilFruitId` text,
`hakiObservation` integer,
`hakiArmament` integer,
`hakiConqueror` integer,
`bounty` integer,
`height` real,
`origin` text,
`firstAppearance` integer,
`pictureUrl` text,
`epithets` text,
`status` text,
`arcId` text,
`url` text,
`notes` text,
FOREIGN KEY (`characterId`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`devilFruitId`) REFERENCES `devilFruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arcId`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_characterOverride`("characterId", "name", "gender", "age", "affiliations", "devilFruitId", "hakiObservation", "hakiArmament", "hakiConqueror", "bounty", "height", "origin", "firstAppearance", "pictureUrl", "epithets", "status", "arcId", "url", "notes") SELECT "characterId", "name", "gender", "age", "affiliations", "devilFruitId", "hakiObservation", "hakiArmament", "hakiConqueror", "bounty", "height", "origin", "firstAppearance", "pictureUrl", "epithets", "status", "arcId", "url", "notes" FROM `characterOverride`;--> statement-breakpoint
DROP TABLE `characterOverride`;--> statement-breakpoint
ALTER TABLE `__new_characterOverride` RENAME TO `characterOverride`;--> statement-breakpoint
PRAGMA foreign_keys=ON;

View File

@@ -1 +0,0 @@
ALTER TABLE `user` ADD `is_admin` integer DEFAULT false NOT NULL;

View File

@@ -1,16 +0,0 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_characterHistory` (
`id` text PRIMARY KEY NOT NULL,
`characterId` text,
`date` integer NOT NULL,
`won` integer DEFAULT 0 NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`characterId`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_characterHistory`("id", "characterId", "date", "won", "createdAt", "updatedAt") SELECT "id", "characterId", "date", "won", "createdAt", "updatedAt" FROM `characterHistory`;--> statement-breakpoint
DROP TABLE `characterHistory`;--> statement-breakpoint
ALTER TABLE `__new_characterHistory` RENAME TO `characterHistory`;--> statement-breakpoint
PRAGMA foreign_keys=ON;--> statement-breakpoint
CREATE UNIQUE INDEX `characterHistory_date_unique` ON `characterHistory` (`date`);

View File

@@ -1,9 +0,0 @@
CREATE TABLE `userCharacterHistory` (
`id` text PRIMARY KEY NOT NULL,
`userId` text,
`characterId` text,
`tryCount` integer NOT NULL,
`createdAt` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`characterId`) REFERENCES `character`(`id`) ON UPDATE no action ON DELETE no action
);

View File

@@ -1,15 +0,0 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_userCharacterHistory` (
`id` text PRIMARY KEY NOT NULL,
`userId` text,
`characterHistoryId` text,
`tryCount` integer NOT NULL,
`createdAt` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`characterHistoryId`) REFERENCES `characterHistory`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_userCharacterHistory`("id", "userId", "characterHistoryId", "tryCount", "createdAt") SELECT "id", "userId", "characterId", "tryCount", "createdAt" FROM `userCharacterHistory`;--> statement-breakpoint
DROP TABLE `userCharacterHistory`;--> statement-breakpoint
ALTER TABLE `__new_userCharacterHistory` RENAME TO `userCharacterHistory`;--> statement-breakpoint
PRAGMA foreign_keys=ON;

View File

@@ -1 +0,0 @@
CREATE UNIQUE INDEX `userCharacterHistory_userId_characterHistoryId_unique` ON `userCharacterHistory` (`userId`,`characterHistoryId`);

View File

@@ -1,29 +0,0 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_character` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`gender` text,
`age` integer,
`affiliations` text,
`devilFruitId` text,
`hakiObservation` integer DEFAULT false,
`hakiArmament` integer DEFAULT false,
`hakiConqueror` integer DEFAULT false,
`bounty` integer DEFAULT 0,
`height` real,
`origin` text,
`firstAppearance` integer NOT NULL,
`pictureUrl` text,
`epithets` text,
`status` text,
`arcId` text,
`url` text,
`isInDailyMode` integer DEFAULT false,
FOREIGN KEY (`devilFruitId`) REFERENCES `devilFruit`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`arcId`) REFERENCES `arc`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_character`("id", "name", "gender", "age", "affiliations", "devilFruitId", "hakiObservation", "hakiArmament", "hakiConqueror", "bounty", "height", "origin", "firstAppearance", "pictureUrl", "epithets", "status", "arcId", "url", "isInDailyMode") SELECT "id", "name", "gender", "age", "affiliations", "devilFruitId", "hakiObservation", "hakiArmament", "hakiConqueror", "bounty", "height", "origin", "firstAppearance", "pictureUrl", "epithets", "status", "arcId", "url", "isInDailyMode" FROM `character`;--> statement-breakpoint
DROP TABLE `character`;--> statement-breakpoint
ALTER TABLE `__new_character` RENAME TO `character`;--> statement-breakpoint
PRAGMA foreign_keys=ON;

View File

@@ -1,12 +0,0 @@
CREATE TABLE `friendship` (
`id` text PRIMARY KEY NOT NULL,
`requesterId` text NOT NULL,
`addresseeId` text NOT NULL,
`status` text DEFAULT 'pending' NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`requesterId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`addresseeId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `friendship_requesterId_addresseeId_unique` ON `friendship` (`requesterId`,`addresseeId`);

View File

@@ -1,51 +0,0 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
ALTER TABLE `user` ADD `username` text;--> statement-breakpoint
UPDATE `user`
SET `username` = `name`
WHERE `username` IS NULL OR trim(`username`) = '';--> statement-breakpoint
UPDATE `user`
SET `username` = `username` || '_' || substr(`id`, 1, 6)
WHERE `id` IN (
SELECT u1.`id`
FROM `user` u1
JOIN `user` u2
ON lower(u1.`username`) = lower(u2.`username`)
AND u1.`id` > u2.`id`
);--> statement-breakpoint
CREATE TABLE `__new_user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`username` text NOT NULL,
`email` text NOT NULL,
`email_verified` integer DEFAULT false NOT NULL,
`image` text,
`is_admin` integer DEFAULT false NOT NULL,
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
);--> statement-breakpoint
INSERT INTO `__new_user` (
`id`,
`name`,
`username`,
`email`,
`email_verified`,
`image`,
`is_admin`,
`created_at`,
`updated_at`
)
SELECT
`id`,
`name`,
`username`,
`email`,
`email_verified`,
`image`,
`is_admin`,
`created_at`,
`updated_at`
FROM `user`;--> statement-breakpoint
DROP TABLE `user`;--> statement-breakpoint
ALTER TABLE `__new_user` RENAME TO `user`;--> statement-breakpoint
CREATE UNIQUE INDEX `user_username_unique` ON `user` (`username`);--> statement-breakpoint
PRAGMA foreign_keys=ON;

View File

@@ -1,7 +1,7 @@
{ {
"version": "6", "version": "6",
"dialect": "sqlite", "dialect": "sqlite",
"id": "d1237d76-8f1c-4721-b8dd-d31082ed7b9a", "id": "8ffd14bd-bf33-410f-9778-92bc1abc8938",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"tables": { "tables": {
"arc": { "arc": {
@@ -21,15 +21,22 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"startChapter": { "fr_name": {
"name": "startChapter", "name": "fr_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"start_chapter": {
"name": "start_chapter",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"endChapter": { "end_chapter": {
"name": "endChapter", "name": "end_chapter",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -66,6 +73,13 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"fr_name": {
"name": "fr_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"gender": { "gender": {
"name": "gender", "name": "gender",
"type": "text", "type": "text",
@@ -87,31 +101,31 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"devilFruitId": { "devil_fruit_id": {
"name": "devilFruitId", "name": "devil_fruit_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"hakiObservation": { "haki_observation": {
"name": "hakiObservation", "name": "haki_observation",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false, "autoincrement": false,
"default": false "default": false
}, },
"hakiArmament": { "haki_armament": {
"name": "hakiArmament", "name": "haki_armament",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false, "autoincrement": false,
"default": false "default": false
}, },
"hakiConqueror": { "haki_conqueror": {
"name": "hakiConqueror", "name": "haki_conqueror",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -140,15 +154,22 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"firstAppearance": { "fr_origin": {
"name": "firstAppearance", "name": "fr_origin",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"first_appearance": {
"name": "first_appearance",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"pictureUrl": { "picture_url": {
"name": "pictureUrl", "name": "picture_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -161,6 +182,13 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"fr_epithets": {
"name": "fr_epithets",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": { "status": {
"name": "status", "name": "status",
"type": "text", "type": "text",
@@ -168,8 +196,8 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"arcId": { "arc_id": {
"name": "arcId", "name": "arc_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -182,23 +210,30 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"isInDailyMode": { "fr_url": {
"name": "isInDailyMode", "name": "fr_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"is_in_daily_mode": {
"name": "is_in_daily_mode",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false, "autoincrement": false,
"default": true "default": false
} }
}, },
"indexes": {}, "indexes": {},
"foreignKeys": { "foreignKeys": {
"character_devilFruitId_devilFruit_id_fk": { "character_devil_fruit_id_devil_fruit_id_fk": {
"name": "character_devilFruitId_devilFruit_id_fk", "name": "character_devil_fruit_id_devil_fruit_id_fk",
"tableFrom": "character", "tableFrom": "character",
"tableTo": "devilFruit", "tableTo": "devil_fruit",
"columnsFrom": [ "columnsFrom": [
"devilFruitId" "devil_fruit_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
@@ -206,17 +241,17 @@
"onDelete": "no action", "onDelete": "no action",
"onUpdate": "no action" "onUpdate": "no action"
}, },
"character_arcId_arc_id_fk": { "character_arc_id_arc_id_fk": {
"name": "character_arcId_arc_id_fk", "name": "character_arc_id_arc_id_fk",
"tableFrom": "character", "tableFrom": "character",
"tableTo": "arc", "tableTo": "arc",
"columnsFrom": [ "columnsFrom": [
"arcId" "arc_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
} }
}, },
@@ -224,8 +259,8 @@
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "checkConstraints": {}
}, },
"characterHistory": { "character_history": {
"name": "characterHistory", "name": "character_history",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@@ -234,8 +269,8 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"characterId": { "character_id": {
"name": "characterId", "name": "character_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -243,9 +278,9 @@
}, },
"date": { "date": {
"name": "date", "name": "date",
"type": "text", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"won": { "won": {
@@ -256,34 +291,42 @@
"autoincrement": false, "autoincrement": false,
"default": 0 "default": 0
}, },
"createdAt": { "created_at": {
"name": "createdAt", "name": "created_at",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"updatedAt": { "updated_at": {
"name": "updatedAt", "name": "updated_at",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
} }
}, },
"indexes": {}, "indexes": {
"character_history_date_unique": {
"name": "character_history_date_unique",
"columns": [
"date"
],
"isUnique": true
}
},
"foreignKeys": { "foreignKeys": {
"characterHistory_characterId_character_id_fk": { "character_history_character_id_character_id_fk": {
"name": "characterHistory_characterId_character_id_fk", "name": "character_history_character_id_character_id_fk",
"tableFrom": "characterHistory", "tableFrom": "character_history",
"tableTo": "character", "tableTo": "character",
"columnsFrom": [ "columnsFrom": [
"characterId" "character_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
}, },
@@ -291,11 +334,11 @@
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "checkConstraints": {}
}, },
"characterOverride": { "character_override": {
"name": "characterOverride", "name": "character_override",
"columns": { "columns": {
"characterId": { "character_id": {
"name": "characterId", "name": "character_id",
"type": "text", "type": "text",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true,
@@ -329,29 +372,29 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"devilFruitId": { "devil_fruit_id": {
"name": "devilFruitId", "name": "devil_fruit_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"hakiObservation": { "haki_observation": {
"name": "hakiObservation", "name": "haki_observation",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"hakiArmament": { "haki_armament": {
"name": "hakiArmament", "name": "haki_armament",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"hakiConqueror": { "haki_conqueror": {
"name": "hakiConqueror", "name": "haki_conqueror",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -378,15 +421,15 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"firstAppearance": { "first_appearance": {
"name": "firstAppearance", "name": "first_appearance",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"pictureUrl": { "picture_url": {
"name": "pictureUrl", "name": "picture_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -406,8 +449,8 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"arcId": { "arc_id": {
"name": "arcId", "name": "arc_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -420,6 +463,13 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"fr_url": {
"name": "fr_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"notes": { "notes": {
"name": "notes", "name": "notes",
"type": "text", "type": "text",
@@ -430,43 +480,43 @@
}, },
"indexes": {}, "indexes": {},
"foreignKeys": { "foreignKeys": {
"characterOverride_characterId_character_id_fk": { "character_override_character_id_character_id_fk": {
"name": "characterOverride_characterId_character_id_fk", "name": "character_override_character_id_character_id_fk",
"tableFrom": "characterOverride", "tableFrom": "character_override",
"tableTo": "character", "tableTo": "character",
"columnsFrom": [ "columnsFrom": [
"characterId" "character_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
"characterOverride_devilFruitId_devilFruit_id_fk": { "character_override_devil_fruit_id_devil_fruit_id_fk": {
"name": "characterOverride_devilFruitId_devilFruit_id_fk", "name": "character_override_devil_fruit_id_devil_fruit_id_fk",
"tableFrom": "characterOverride", "tableFrom": "character_override",
"tableTo": "devilFruit", "tableTo": "devil_fruit",
"columnsFrom": [ "columnsFrom": [
"devilFruitId" "devil_fruit_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
}, },
"characterOverride_arcId_arc_id_fk": { "character_override_arc_id_arc_id_fk": {
"name": "characterOverride_arcId_arc_id_fk", "name": "character_override_arc_id_arc_id_fk",
"tableFrom": "characterOverride", "tableFrom": "character_override",
"tableTo": "arc", "tableTo": "arc",
"columnsFrom": [ "columnsFrom": [
"arcId" "arc_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
} }
}, },
@@ -474,8 +524,8 @@
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "checkConstraints": {}
}, },
"characterScrapeValidation": { "character_scrape_validation": {
"name": "characterScrapeValidation", "name": "character_scrape_validation",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@@ -491,6 +541,13 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"fr_name": {
"name": "fr_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"gender": { "gender": {
"name": "gender", "name": "gender",
"type": "text", "type": "text",
@@ -512,31 +569,31 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"devilFruitId": { "devil_fruit_id": {
"name": "devilFruitId", "name": "devil_fruit_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"hakiObservation": { "haki_observation": {
"name": "hakiObservation", "name": "haki_observation",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false, "autoincrement": false,
"default": false "default": false
}, },
"hakiArmament": { "haki_armament": {
"name": "hakiArmament", "name": "haki_armament",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false, "autoincrement": false,
"default": false "default": false
}, },
"hakiConqueror": { "haki_conqueror": {
"name": "hakiConqueror", "name": "haki_conqueror",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -564,15 +621,22 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"firstAppearance": { "fr_origin": {
"name": "firstAppearance", "name": "fr_origin",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"first_appearance": {
"name": "first_appearance",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"pictureUrl": { "picture_url": {
"name": "pictureUrl", "name": "picture_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -585,6 +649,13 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"fr_epithets": {
"name": "fr_epithets",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": { "status": {
"name": "status", "name": "status",
"type": "text", "type": "text",
@@ -592,8 +663,8 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"arcId": { "arc_id": {
"name": "arcId", "name": "arc_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
@@ -605,34 +676,41 @@
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
},
"fr_url": {
"name": "fr_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
} }
}, },
"indexes": {}, "indexes": {},
"foreignKeys": { "foreignKeys": {
"characterScrapeValidation_devilFruitId_devilFruit_id_fk": { "character_scrape_validation_devil_fruit_id_devil_fruit_id_fk": {
"name": "characterScrapeValidation_devilFruitId_devilFruit_id_fk", "name": "character_scrape_validation_devil_fruit_id_devil_fruit_id_fk",
"tableFrom": "characterScrapeValidation", "tableFrom": "character_scrape_validation",
"tableTo": "devilFruit", "tableTo": "devil_fruit",
"columnsFrom": [ "columnsFrom": [
"devilFruitId" "devil_fruit_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
}, },
"characterScrapeValidation_arcId_arc_id_fk": { "character_scrape_validation_arc_id_arc_id_fk": {
"name": "characterScrapeValidation_arcId_arc_id_fk", "name": "character_scrape_validation_arc_id_arc_id_fk",
"tableFrom": "characterScrapeValidation", "tableFrom": "character_scrape_validation",
"tableTo": "arc", "tableTo": "arc",
"columnsFrom": [ "columnsFrom": [
"arcId" "arc_id"
], ],
"columnsTo": [ "columnsTo": [
"id" "id"
], ],
"onDelete": "no action", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
} }
}, },
@@ -664,8 +742,8 @@
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "checkConstraints": {}
}, },
"devilFruit": { "devil_fruit": {
"name": "devilFruit", "name": "devil_fruit",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@@ -697,8 +775,8 @@
} }
}, },
"indexes": { "indexes": {
"devilFruit_name_unique": { "devil_fruit_name_unique": {
"name": "devilFruit_name_unique", "name": "devil_fruit_name_unique",
"columns": [ "columns": [
"name" "name"
], ],
@@ -710,6 +788,183 @@
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "checkConstraints": {}
}, },
"friendship": {
"name": "friendship",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"requester_id": {
"name": "requester_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"addressee_id": {
"name": "addressee_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'pending'"
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"friendship_requester_id_addressee_id_unique": {
"name": "friendship_requester_id_addressee_id_unique",
"columns": [
"requester_id",
"addressee_id"
],
"isUnique": true
}
},
"foreignKeys": {
"friendship_requester_id_user_id_fk": {
"name": "friendship_requester_id_user_id_fk",
"tableFrom": "friendship",
"tableTo": "user",
"columnsFrom": [
"requester_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"friendship_addressee_id_user_id_fk": {
"name": "friendship_addressee_id_user_id_fk",
"tableFrom": "friendship",
"tableTo": "user",
"columnsFrom": [
"addressee_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"user_character_history": {
"name": "user_character_history",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"character_history_id": {
"name": "character_history_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"try_count": {
"name": "try_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"tried_character_ids": {
"name": "tried_character_ids",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"user_character_history_user_id_character_history_id_unique": {
"name": "user_character_history_user_id_character_history_id_unique",
"columns": [
"user_id",
"character_history_id"
],
"isUnique": true
}
},
"foreignKeys": {
"user_character_history_user_id_user_id_fk": {
"name": "user_character_history_user_id_user_id_fk",
"tableFrom": "user_character_history",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"user_character_history_character_history_id_character_history_id_fk": {
"name": "user_character_history_character_history_id_character_history_id_fk",
"tableFrom": "user_character_history",
"tableTo": "character_history",
"columnsFrom": [
"character_history_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"account": { "account": {
"name": "account", "name": "account",
"columns": { "columns": {
@@ -947,6 +1202,13 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": { "email": {
"name": "email", "name": "email",
"type": "text", "type": "text",
@@ -969,6 +1231,14 @@
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"is_admin": {
"name": "is_admin",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "integer", "type": "integer",
@@ -987,6 +1257,13 @@
} }
}, },
"indexes": { "indexes": {
"user_username_unique": {
"name": "user_username_unique",
"columns": [
"username"
],
"isUnique": true
},
"user_email_unique": { "user_email_unique": {
"name": "user_email_unique", "name": "user_email_unique",
"columns": [ "columns": [

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,71 +5,8 @@
{ {
"idx": 0, "idx": 0,
"version": "6", "version": "6",
"when": 1772325597983, "when": 1773447741334,
"tag": "0000_graceful_master_mold", "tag": "0000_keen_rockslide",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1772383366179,
"tag": "0001_nostalgic_hercules",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1772390182445,
"tag": "0002_large_gwen_stacy",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1772449624450,
"tag": "0003_wise_blonde_phantom",
"breakpoints": true
},
{
"idx": 4,
"version": "6",
"when": 1772480377099,
"tag": "0004_unique_lorna_dane",
"breakpoints": true
},
{
"idx": 5,
"version": "6",
"when": 1772562012631,
"tag": "0005_large_jane_foster",
"breakpoints": true
},
{
"idx": 6,
"version": "6",
"when": 1772562364830,
"tag": "0006_premium_mesmero",
"breakpoints": true
},
{
"idx": 7,
"version": "6",
"when": 1772735982970,
"tag": "0007_gray_shinko_yamashiro",
"breakpoints": true
},
{
"idx": 8,
"version": "6",
"when": 1772821532270,
"tag": "0008_skinny_warpath",
"breakpoints": true
},
{
"idx": 9,
"version": "6",
"when": 1772822823122,
"tag": "0009_true_gravity",
"breakpoints": true "breakpoints": true
} }
] ]

View File

@@ -4,6 +4,8 @@ import { sql, eq } from 'drizzle-orm';
import fs from 'fs'; import fs from 'fs';
import { arc, character, devilFruit, characterScrapeValidation, type DevilFruitType } from '../src/lib/server/db/schema'; import { arc, character, devilFruit, characterScrapeValidation, type DevilFruitType } from '../src/lib/server/db/schema';
type Status = 'Alive' | 'Dead' | 'Unknown';
type ArcRecord = { type ArcRecord = {
id: string; id: string;
name: string; name: string;
@@ -22,9 +24,11 @@ type DevilFruitRecord = {
type CharacterRecord = { type CharacterRecord = {
id: string; id: string;
name: string; name: string;
frName?: string | null;
gender?: string | null; gender?: string | null;
age?: number | null; age?: number | null;
affiliations?: string[] | string | null; affiliations?: string[] | string | null;
frAffiliations?: string[] | string | null;
devilFruitId?: string | null; devilFruitId?: string | null;
hakiObservation?: boolean; hakiObservation?: boolean;
hakiArmament?: boolean; hakiArmament?: boolean;
@@ -32,12 +36,15 @@ type CharacterRecord = {
bounty?: number | null; bounty?: number | null;
height?: number | null; height?: number | null;
origin?: string | null; origin?: string | null;
frOrigin?: string | null;
firstAppearance?: number; firstAppearance?: number;
pictureUrl?: string | null; pictureUrl?: string | null;
epithets?: string[] | string | null; epithets?: string[] | string | null;
status?: string | null; frEpithets?: string[] | string | null;
status?: Status | null;
arcId?: string | null; arcId?: string | null;
url?: string | null; url?: string | null;
frUrl?: string | null;
}; };
const DATABASE_URL = process.env.DATABASE_URL || 'file:local.db'; const DATABASE_URL = process.env.DATABASE_URL || 'file:local.db';
@@ -86,7 +93,7 @@ function toJsonArray(value: string[] | string | null | undefined): string[] | nu
function toDevilFruitType(value: DevilFruitType | string | null | undefined): DevilFruitType | null { function toDevilFruitType(value: DevilFruitType | string | null | undefined): DevilFruitType | null {
if (!value) return null; if (!value) return null;
if (value === 'Paramecia' || value === 'Zoan' || value === 'Logia' || value === 'Unknown') { if (value === 'Paramecia' || value === 'Zoan' || value === 'Logia' || value === 'Smile' || value === 'Unknown') {
return value; return value;
} }
return 'Unknown'; return 'Unknown';
@@ -115,59 +122,25 @@ function transformCharacterData(item: CharacterRecord) {
gender: toNullable(item.gender), gender: toNullable(item.gender),
age: toNullable(item.age), age: toNullable(item.age),
affiliations: toJsonArray(item.affiliations), affiliations: toJsonArray(item.affiliations),
frAffiliations: toJsonArray(item.frAffiliations),
devilFruitId: toNullable(item.devilFruitId), devilFruitId: toNullable(item.devilFruitId),
hakiObservation: !!item.hakiObservation, hakiObservation: !!item.hakiObservation,
hakiArmament: !!item.hakiArmament, hakiArmament: !!item.hakiArmament,
hakiConqueror: !!item.hakiConqueror, hakiConqueror: !!item.hakiConqueror,
bounty: item.bounty ?? 0, bounty: item.bounty ?? 0,
height: toNumber(item.height as any), height: toNumber(item.height as string | number | null),
origin: toNullable(item.origin), origin: toNullable(item.origin),
frOrigin: toNullable(item.frOrigin),
firstAppearance: item.firstAppearance ?? 0, firstAppearance: item.firstAppearance ?? 0,
pictureUrl: toNullable(item.pictureUrl), pictureUrl: toNullable(item.pictureUrl),
epithets: toJsonArray(item.epithets), epithets: toJsonArray(item.epithets),
frEpithets: toJsonArray(item.frEpithets),
status: toNullable(item.status), status: toNullable(item.status),
arcId: toNullable(item.arcId), arcId: toNullable(item.arcId),
url: toNullable(item.url) url: toNullable(item.url)
}; };
} }
function hasChanged(jsonData: any, dbData: any): boolean {
if (!dbData) return true;
// Print any differences for debugging
for (const key in jsonData) {
const jsonValue = jsonData[key];
const dbValue = dbData[key];
const jsonString = typeof jsonValue === 'object' ? JSON.stringify(jsonValue) : String(jsonValue);
const dbString = typeof dbValue === 'object' ? JSON.stringify(dbValue) : String(dbValue);
if (jsonString !== dbString) {
console.log(`\nField "${key}" changed for character ID ${jsonData.id}:`);
console.log(` JSON: ${jsonString}`);
console.log(` DB: ${dbString}`);
} }
// Compare each field
return (
jsonData.name != dbData.name ||
jsonData.gender != dbData.gender ||
jsonData.age != dbData.age ||
JSON.stringify(jsonData.affiliations) != JSON.stringify(dbData.affiliations) ||
jsonData.devilFruitId != dbData.devilFruitId ||
jsonData.hakiObservation != dbData.hakiObservation ||
jsonData.hakiArmament != dbData.hakiArmament ||
jsonData.hakiConqueror != dbData.hakiConqueror ||
jsonData.bounty != dbData.bounty ||
jsonData.height != dbData.height ||
jsonData.origin != dbData.origin ||
jsonData.firstAppearance != dbData.firstAppearance ||
jsonData.pictureUrl != dbData.pictureUrl ||
JSON.stringify(jsonData.epithets) != JSON.stringify(dbData.epithets) ||
jsonData.status != dbData.status ||
jsonData.arcId != dbData.arcId ||
jsonData.url != dbData.url
);
}
async function isCharacterTableEmpty(): Promise<boolean> { async function isCharacterTableEmpty(): Promise<boolean> {
const result = await db.select({ count: sql<number>`COUNT(*)` }).from(character); const result = await db.select({ count: sql<number>`COUNT(*)` }).from(character);
return result[0]?.count === 0; return result[0]?.count === 0;

File diff suppressed because it is too large Load Diff

View File

@@ -17,13 +17,14 @@ export const config = sqliteTable('config', {
export const arc = sqliteTable('arc', { export const arc = sqliteTable('arc', {
id: text('id').primaryKey(), id: text('id').primaryKey(),
name: text('name').notNull(), name: text('name').notNull(),
startChapter: integer('startChapter').notNull(), frName: text('fr_name'),
endChapter: integer('endChapter'), startChapter: integer('start_chapter').notNull(),
endChapter: integer('end_chapter'),
url: text('url') url: text('url')
}); });
// Define the devil fruit table schema // Define the devil fruit table schema
export const devilFruit = sqliteTable('devilFruit', { export const devilFruit = sqliteTable('devil_fruit', {
id: text('id').primaryKey(), id: text('id').primaryKey(),
name: text('name').notNull().unique(), name: text('name').notNull().unique(),
type: text('type').$type<DevilFruitType>(), type: text('type').$type<DevilFruitType>(),
@@ -34,91 +35,101 @@ export const devilFruit = sqliteTable('devilFruit', {
export const character = sqliteTable('character', { export const character = sqliteTable('character', {
id: text('id').primaryKey(), id: text('id').primaryKey(),
name: text('name').notNull(), name: text('name').notNull(),
frName: text('fr_name'),
gender: text('gender'), gender: text('gender'),
age: integer('age'), age: integer('age'),
affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(), affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(),
devilFruitId: text('devilFruitId').references(() => devilFruit.id), devilFruitId: text('devil_fruit_id').references(() => devilFruit.id),
hakiObservation: integer('hakiObservation', { mode: 'boolean' }).default(false), hakiObservation: integer('haki_observation', { mode: 'boolean' }).default(false),
hakiArmament: integer('hakiArmament', { mode: 'boolean' }).default(false), hakiArmament: integer('haki_armament', { mode: 'boolean' }).default(false),
hakiConqueror: integer('hakiConqueror', { mode: 'boolean' }).default(false), hakiConqueror: integer('haki_conqueror', { mode: 'boolean' }).default(false),
bounty: integer('bounty').default(0), bounty: integer('bounty').default(0),
height: real('height'), height: real('height'),
origin: text('origin'), origin: text('origin'),
firstAppearance: integer('firstAppearance').notNull(), frOrigin: text('fr_origin'),
pictureUrl: text('pictureUrl'), firstAppearance: integer('first_appearance').notNull(),
pictureUrl: text('picture_url'),
epithets: text('epithets', { mode: 'json' }).$type<string[]>(), epithets: text('epithets', { mode: 'json' }).$type<string[]>(),
frEpithets: text('fr_epithets', { mode: 'json' }).$type<string[]>(),
status: text('status').$type<Status | null>(), status: text('status').$type<Status | null>(),
arcId: text('arcId').references(() => arc.id), arcId: text('arc_id').references(() => arc.id, { onDelete: 'set null' }),
url: text('url'), url: text('url'),
isInDailyMode: integer('isInDailyMode', { mode: 'boolean' }).default(false) frUrl: text('fr_url'),
isInDailyMode: integer('is_in_daily_mode', { mode: 'boolean' }).default(false)
}); });
// Define the character override table schema // Define the character override table schema
export const characterOverride = sqliteTable('characterOverride', { export const characterOverride = sqliteTable('character_override', {
characterId: text('characterId').primaryKey().references(() => character.id), characterId: text('character_id').primaryKey().references(() => character.id, { onDelete: 'cascade' }),
name: text('name'), name: text('name'),
gender: text('gender'), gender: text('gender'),
age: integer('age'), age: integer('age'),
affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(), affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(),
devilFruitId: text('devilFruitId').references(() => devilFruit.id), devilFruitId: text('devil_fruit_id').references(() => devilFruit.id, { onDelete: 'set null' }),
hakiObservation: integer('hakiObservation', { mode: 'boolean' }), hakiObservation: integer('haki_observation', { mode: 'boolean' }),
hakiArmament: integer('hakiArmament', { mode: 'boolean' }), hakiArmament: integer('haki_armament', { mode: 'boolean' }),
hakiConqueror: integer('hakiConqueror', { mode: 'boolean' }), hakiConqueror: integer('haki_conqueror', { mode: 'boolean' }),
bounty: integer('bounty'), bounty: integer('bounty'),
height: real('height'), height: real('height'),
origin: text('origin'), origin: text('origin'),
firstAppearance: integer('firstAppearance'), firstAppearance: integer('first_appearance'),
pictureUrl: text('pictureUrl'), pictureUrl: text('picture_url'),
epithets: text('epithets', { mode: 'json' }).$type<string[]>(), epithets: text('epithets', { mode: 'json' }).$type<string[]>(),
status: text('status').$type<Status | null>(), status: text('status').$type<Status | null>(),
arcId: text('arcId').references(() => arc.id), arcId: text('arc_id').references(() => arc.id, { onDelete: 'set null' }),
url: text('url'), url: text('url'),
frUrl: text('fr_url'),
notes: text('notes') notes: text('notes')
}); });
// Define the character scrape validation table schema // Define the character scrape validation table schema
export const characterScrapeValidation = sqliteTable('characterScrapeValidation', { export const characterScrapeValidation = sqliteTable('character_scrape_validation', {
id: text('id').primaryKey(), id: text('id').primaryKey(),
name: text('name').notNull(), name: text('name').notNull(),
frName: text('fr_name'),
gender: text('gender'), gender: text('gender'),
age: integer('age'), age: integer('age'),
affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(), affiliations: text('affiliations', { mode: 'json' }).$type<string[]>(),
devilFruitId: text('devilFruitId').references(() => devilFruit.id), devilFruitId: text('devil_fruit_id').references(() => devilFruit.id, { onDelete: 'set null' }),
hakiObservation: integer('hakiObservation', { mode: 'boolean' }).default(false), hakiObservation: integer('haki_observation', { mode: 'boolean' }).default(false),
hakiArmament: integer('hakiArmament', { mode: 'boolean' }).default(false), hakiArmament: integer('haki_armament', { mode: 'boolean' }).default(false),
hakiConqueror: integer('hakiConqueror', { mode: 'boolean' }).default(false), hakiConqueror: integer('haki_conqueror', { mode: 'boolean' }).default(false),
bounty: integer('bounty'), bounty: integer('bounty'),
height: real('height'), height: real('height'),
origin: text('origin'), origin: text('origin'),
firstAppearance: integer('firstAppearance').notNull(), frOrigin: text('fr_origin'),
pictureUrl: text('pictureUrl'), firstAppearance: integer('first_appearance').notNull(),
pictureUrl: text('picture_url'),
epithets: text('epithets', { mode: 'json' }).$type<string[]>(), epithets: text('epithets', { mode: 'json' }).$type<string[]>(),
frEpithets: text('fr_epithets', { mode: 'json' }).$type<string[]>(),
status: text('status').$type<Status | null>(), status: text('status').$type<Status | null>(),
arcId: text('arcId').references(() => arc.id), arcId: text('arc_id').references(() => arc.id, { onDelete: 'set null' }),
url: text('url') url: text('url'),
frUrl: text('fr_url')
}); });
// Define the caracter history table schema // Define the character history table schema
export const characterHistory = sqliteTable('characterHistory', { export const characterHistory = sqliteTable('character_history', {
id: text('id') id: text('id')
.primaryKey() .primaryKey()
.$defaultFn(() => crypto.randomUUID()), .$defaultFn(() => crypto.randomUUID()),
characterId: text('characterId').references(() => character.id), characterId: text('character_id').references(() => character.id, { onDelete: 'cascade' }),
date: integer('date').notNull().unique(), date: integer('date').notNull().unique(),
won: integer('won').notNull().default(0), won: integer('won').notNull().default(0),
createdAt: integer('createdAt').notNull().$default(() => Date.now()), createdAt: integer('created_at').notNull().$default(() => Date.now()),
updatedAt: integer('updatedAt').notNull().$default(() => Date.now()), updatedAt: integer('updated_at').notNull().$default(() => Date.now()),
}); });
// Define the user character history table schema // Define the user character history table schema
export const userCharacterHistory = sqliteTable('userCharacterHistory', { export const userCharacterHistory = sqliteTable('user_character_history', {
id: text('id') id: text('id')
.primaryKey() .primaryKey()
.$defaultFn(() => crypto.randomUUID()), .$defaultFn(() => crypto.randomUUID()),
userId: text('userId').references(() => user.id), userId: text('user_id').references(() => user.id, { onDelete: 'cascade' }),
characterHistoryId: text('characterHistoryId').references(() => characterHistory.id), characterHistoryId: text('character_history_id').references(() => characterHistory.id, { onDelete: 'cascade' }),
tryCount: integer('tryCount').notNull(), tryCount: integer('try_count').notNull(),
createdAt: integer('createdAt').notNull().$default(() => Date.now()) triedCharacterIds: text('tried_character_ids', { mode: 'json' }).$type<string[]>(),
createdAt: integer('created_at').notNull().$default(() => Date.now())
}, (table) => [ }, (table) => [
unique().on(table.userId, table.characterHistoryId) unique().on(table.userId, table.characterHistoryId)
]); ]);
@@ -128,15 +139,15 @@ export const friendship = sqliteTable('friendship', {
id: text('id') id: text('id')
.primaryKey() .primaryKey()
.$defaultFn(() => crypto.randomUUID()), .$defaultFn(() => crypto.randomUUID()),
requesterId: text('requesterId') requesterId: text('requester_id')
.notNull() .notNull()
.references(() => user.id, { onDelete: 'cascade' }), .references(() => user.id, { onDelete: 'cascade' }),
addresseeId: text('addresseeId') addresseeId: text('addressee_id')
.notNull() .notNull()
.references(() => user.id, { onDelete: 'cascade' }), .references(() => user.id, { onDelete: 'cascade' }),
status: text('status').$type<FriendshipStatus>().notNull().default('pending'), status: text('status').$type<FriendshipStatus>().notNull().default('pending'),
createdAt: integer('createdAt').notNull().$default(() => Date.now()), createdAt: integer('created_at').notNull().$default(() => Date.now()),
updatedAt: integer('updatedAt').notNull().$default(() => Date.now()), updatedAt: integer('updated_at').notNull().$default(() => Date.now()),
}, (table) => [ }, (table) => [
unique().on(table.requesterId, table.addresseeId) unique().on(table.requesterId, table.addresseeId)
]); ]);