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