Files
sapiens-web3/shared/schema.ts
kimjaehyeon0101 fb1d150554 Add AI-powered chatbot for media outlets
Integrate an AI chatbot feature allowing users to interact with media outlets, fetch chat history, and generate AI responses using OpenAI.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9a264234-c5d7-4dcc-adf3-a954b149b30d
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/9a264234-c5d7-4dcc-adf3-a954b149b30d/d35d7YU
2025-10-15 02:06:25 +00:00

288 lines
10 KiB
TypeScript

import { sql } from 'drizzle-orm';
import {
index,
jsonb,
pgTable,
timestamp,
varchar,
text,
integer,
boolean,
decimal,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";
// Session storage table.
// (IMPORTANT) This table is mandatory for Replit Auth, don't drop it.
export const sessions = pgTable(
"sessions",
{
sid: varchar("sid").primaryKey(),
sess: jsonb("sess").notNull(),
expire: timestamp("expire").notNull(),
},
(table) => [index("IDX_session_expire").on(table.expire)],
);
// User storage table.
// (IMPORTANT) This table is mandatory for Replit Auth, don't drop it.
export const users = pgTable("users", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
email: varchar("email").unique(),
firstName: varchar("first_name"),
lastName: varchar("last_name"),
profileImageUrl: varchar("profile_image_url"),
role: varchar("role").default("user"), // user, admin, superadmin
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Media outlets (People, Topics, Companies)
export const mediaOutlets = pgTable("media_outlets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
name: varchar("name").notNull(),
slug: varchar("slug").notNull().unique(),
category: varchar("category").notNull(), // people, topics, companies
description: text("description"),
imageUrl: varchar("image_url"),
tags: text("tags").array(),
trafficScore: integer("traffic_score").default(0), // For sorting by traffic
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Articles within media outlets
export const articles = pgTable("articles", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
title: varchar("title").notNull(),
slug: varchar("slug").notNull(),
excerpt: text("excerpt"),
content: text("content").notNull(),
imageUrl: varchar("image_url"),
authorId: varchar("author_id"),
tags: text("tags").array(),
isPinned: boolean("is_pinned").default(false),
isFeatured: boolean("is_featured").default(false),
isSponsored: boolean("is_sponsored").default(false),
publishedMinutesAgo: integer("published_minutes_ago").notNull().default(sql`1 + floor(random() * 59)::int`),
publishedAt: timestamp("published_at").defaultNow(),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Prediction markets
export const predictionMarkets = pgTable("prediction_markets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
question: varchar("question"),
title: varchar("title").notNull(),
description: text("description"),
articleId: varchar("article_id"),
yesPrice: decimal("yes_price", { precision: 5, scale: 4 }).default("0.5"),
noPrice: decimal("no_price", { precision: 5, scale: 4 }).default("0.5"),
totalVolume: decimal("total_volume", { precision: 12, scale: 2 }).default("0"),
totalBets: integer("total_bets").default(0),
resolutionDate: timestamp("resolution_date"),
volume: decimal("volume", { precision: 12, scale: 2 }),
endDate: timestamp("end_date"),
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Auctions for media outlet management rights
export const auctions = pgTable("auctions", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
title: varchar("title").notNull(),
description: text("description"),
currentBid: decimal("current_bid", { precision: 10, scale: 2 }),
qualityScore: integer("quality_score"),
highestBidderId: varchar("highest_bidder_id"),
endDate: timestamp("end_date").notNull(),
duration: integer("duration"), // days
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Bids for auctions
export const bids = pgTable("bids", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
auctionId: varchar("auction_id").notNull(),
bidderId: varchar("bidder_id").notNull(),
amount: decimal("amount", { precision: 10, scale: 2 }).notNull(),
qualityScore: integer("quality_score"),
createdAt: timestamp("created_at").defaultNow(),
});
// Media outlet creation requests
export const mediaOutletRequests = pgTable("media_outlet_requests", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
name: varchar("name").notNull(),
category: varchar("category").notNull(),
description: text("description"),
requesterId: varchar("requester_id").notNull(),
status: varchar("status").default("pending"), // pending, approved, rejected
reviewedBy: varchar("reviewed_by"),
reviewedAt: timestamp("reviewed_at"),
createdAt: timestamp("created_at").defaultNow(),
});
// Comments on articles
export const comments = pgTable("comments", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
articleId: varchar("article_id").notNull(),
authorId: varchar("author_id").notNull(),
content: text("content").notNull(),
isPinned: boolean("is_pinned").default(false),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Prediction market bets
export const predictionBets = pgTable("prediction_bets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
marketId: varchar("market_id").notNull(),
userId: varchar("user_id").notNull(),
side: varchar("side", { enum: ["yes", "no"] }).notNull(),
amount: decimal("amount", { precision: 12, scale: 2 }).notNull(),
price: decimal("price", { precision: 5, scale: 4 }).notNull(), // Price at time of bet
createdAt: timestamp("created_at").defaultNow(),
});
// Community posts (DC Inside-style gallery posts)
export const communityPosts = pgTable("community_posts", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
authorId: varchar("author_id").notNull(),
title: varchar("title").notNull(),
content: text("content").notNull(),
imageUrl: varchar("image_url"),
viewCount: integer("view_count").default(0),
likeCount: integer("like_count").default(0),
replyCount: integer("reply_count").default(0),
isPinned: boolean("is_pinned").default(false),
isNotice: boolean("is_notice").default(false),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Community post replies
export const communityReplies = pgTable("community_replies", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
postId: varchar("post_id").notNull(),
authorId: varchar("author_id").notNull(),
content: text("content").notNull(),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Chatbot messages for media outlets
export const chatMessages = pgTable("chat_messages", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
userId: varchar("user_id").notNull(),
role: varchar("role").notNull(), // "user" or "assistant"
content: text("content").notNull(),
createdAt: timestamp("created_at").defaultNow(),
});
// Insert schemas
export const insertUserSchema = createInsertSchema(users).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertMediaOutletSchema = createInsertSchema(mediaOutlets).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertArticleSchema = createInsertSchema(articles).omit({
id: true,
publishedMinutesAgo: true,
createdAt: true,
updatedAt: true,
});
export const insertPredictionMarketSchema = createInsertSchema(predictionMarkets).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertAuctionSchema = createInsertSchema(auctions).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertBidSchema = createInsertSchema(bids).omit({
id: true,
createdAt: true,
});
export const insertMediaOutletRequestSchema = createInsertSchema(mediaOutletRequests).omit({
id: true,
createdAt: true,
});
export const insertCommentSchema = createInsertSchema(comments).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertPredictionBetSchema = createInsertSchema(predictionBets).omit({
id: true,
createdAt: true,
});
export const insertCommunityPostSchema = createInsertSchema(communityPosts).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertCommunityReplySchema = createInsertSchema(communityReplies).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertChatMessageSchema = createInsertSchema(chatMessages).omit({
id: true,
createdAt: true,
});
// Types
export type UpsertUser = typeof users.$inferInsert;
export type User = typeof users.$inferSelect;
export type InsertMediaOutlet = z.infer<typeof insertMediaOutletSchema>;
export type MediaOutlet = typeof mediaOutlets.$inferSelect;
export type InsertArticle = z.infer<typeof insertArticleSchema>;
export type Article = typeof articles.$inferSelect;
export type InsertPredictionMarket = z.infer<typeof insertPredictionMarketSchema>;
export type PredictionMarket = typeof predictionMarkets.$inferSelect;
export type InsertAuction = z.infer<typeof insertAuctionSchema>;
export type Auction = typeof auctions.$inferSelect;
export type InsertBid = z.infer<typeof insertBidSchema>;
export type Bid = typeof bids.$inferSelect;
export type InsertMediaOutletRequest = z.infer<typeof insertMediaOutletRequestSchema>;
export type MediaOutletRequest = typeof mediaOutletRequests.$inferSelect;
export type InsertComment = z.infer<typeof insertCommentSchema>;
export type Comment = typeof comments.$inferSelect;
export type InsertPredictionBet = z.infer<typeof insertPredictionBetSchema>;
export type PredictionBet = typeof predictionBets.$inferSelect;
export type InsertCommunityPost = z.infer<typeof insertCommunityPostSchema>;
export type CommunityPost = typeof communityPosts.$inferSelect;
export type InsertCommunityReply = z.infer<typeof insertCommunityReplySchema>;
export type CommunityReply = typeof communityReplies.$inferSelect;
export type InsertChatMessage = z.infer<typeof insertChatMessageSchema>;
export type ChatMessage = typeof chatMessages.$inferSelect;