Add MCP server and enhance AI content tools

Implement self-hosted MCP server for admin actions, update AI generation tools in admin dashboard, and refine mobile app stores and components.
This commit is contained in:
jjbrunton committed 2026-01-10 19:24:06 +00:00
1 parent b0f1700e40
commit 4e40b92b16
71 files changed
+10511 -1008

No files matched your search

+30 -16
View File
@@ -42,15 +42,15 @@ const getIntensityDisplay = (pack: QuestionPack) => {
const min = isValidIntensity(pack.min_intensity) ? pack.min_intensity : null;
const max = isValidIntensity(pack.max_intensity) ? pack.max_intensity : null;
const avg = typeof pack.avg_intensity === "number" ? clampIntensity(pack.avg_intensity) : null;
const fallback = avg ?? (pack.is_explicit ? 5 : 2);
const flameCount = max ?? avg ?? (pack.is_explicit ? 5 : 2);
const label = min && max
? min === max
? INTENSITY_LABELS[min]
: `${INTENSITY_LABELS[min]} - ${INTENSITY_LABELS[max]}`
: INTENSITY_LABELS[flameCount];
const minCount = min ?? max ?? fallback;
const maxCount = max ?? min ?? fallback;
const label = minCount === maxCount
? INTENSITY_LABELS[minCount]
: `${INTENSITY_LABELS[minCount]} - ${INTENSITY_LABELS[maxCount]}`;
return { flameCount, label };
return { minCount, maxCount, label };
};
@@ -100,14 +100,19 @@ function PackRow({ pack, isEnabled, isPremiumLocked, isExpanded, onToggle, onPre
</Text>
<View style={styles.packIntensityRow}>
<View style={styles.packIntensityFlames}>
{Array.from({ length: 5 }).map((_, index) => (
<Ionicons
key={`intensity-${pack.id}-${index}`}
name={index < intensityDisplay.flameCount ? "flame" : "flame-outline"}
size={12}
color={index < intensityDisplay.flameCount ? colors.primary : colors.textTertiary}
/>
))}
{Array.from({ length: 5 }).map((_, index) => {
const level = index + 1;
const isInRange = level >= intensityDisplay.minCount && level <= intensityDisplay.maxCount;
return (
<Ionicons
key={`intensity-${pack.id}-${index}`}
name={isInRange ? "flame" : "flame-outline"}
size={12}
color={isInRange ? colors.primary : colors.textTertiary}
/>
);
})}
</View>
<Text style={styles.packIntensityText}>{intensityDisplay.label}</Text>
</View>
@@ -462,7 +467,15 @@ export default function QuestionPacksScreen() {
{(packsByCategory.get("uncategorized")?.length || 0) > 0 && (
<CategorySection
category={{ id: "uncategorized", name: "Other", description: null, icon: "📁", sort_order: 999, created_at: "" }}
category={{
id: "uncategorized",
name: "Other",
description: null,
icon: "📁",
sort_order: 999,
created_at: "",
is_public: true
}}
packs={packsByCategory.get("uncategorized") || []}
enabledPackIds={enabledPackIds}
hasPremiumAccess={hasPremiumAccess}
@@ -727,6 +740,7 @@ const styles = StyleSheet.create({
},
packIntensityFlames: {
flexDirection: "row",
alignItems: "center",
gap: 2,
},
packIntensityText: {
+1 -1
View File
@@ -71,7 +71,7 @@ export default function PackDetailsScreen() {
try {
const { data, error } = await supabase
.from("questions")
.select("*")
.select("id, pack_id, text, partner_text, intensity, allowed_couple_genders, target_user_genders, created_at")
.eq("pack_id", id)
.order("created_at");
@@ -26,11 +26,11 @@ export interface IntensitySliderProps {
}
const INTENSITY_LEVELS: Array<{ level: IntensityLevel; label: string; emoji: string; description: string }> = [
{ level: 1, label: 'Gentle', emoji: '💭', description: 'Conversations & emotional connection' },
{ level: 2, label: 'Warm', emoji: '💕', description: 'Cuddling, kisses & flirty moments' },
{ level: 3, label: 'Playful', emoji: '😏', description: 'Making out & suggestive content' },
{ level: 4, label: 'Steamy', emoji: '🔥', description: 'Intimate activities & explicit content' },
{ level: 5, label: 'Intense', emoji: '🌶️', description: 'Advanced intimacy & fantasies' },
{ level: 1, label: 'Gentle', emoji: '💭', description: 'Pure emotional connection & non-sexual bonding' },
{ level: 2, label: 'Warm', emoji: '💕', description: 'Romantic atmosphere & affectionate touch' },
{ level: 3, label: 'Playful', emoji: '😏', description: 'Light sexual exploration & sensual discovery' },
{ level: 4, label: 'Steamy', emoji: '🔥', description: 'Explicit sexual activities & moderate adventure' },
{ level: 5, label: 'Intense', emoji: '🌶️', description: 'Advanced/BDSM/Extreme exploration' },
];
const HEAT_COLORS = [
+36 -25
View File
@@ -45,36 +45,47 @@ export const usePacksStore = create<PacksState>((set, get) => ({
const maxIntensity = getUserMaxIntensity();
// Fetch categories
const { data: categories } = await supabase
.from("categories")
.select("*")
.order("sort_order");
// Fetch packs with category info and question count
let query = supabase
.from("question_packs")
.select("*, category:categories(*), questions(count)")
.eq("is_public", true)
.order("sort_order");
// Fetch categories
const { data: categories } = await supabase
.from("categories")
.select("*")
.order("sort_order");
// Hide categories explicitly marked non-public, but keep null for compatibility.
const visibleCategories = (categories ?? []).filter(category => category.is_public !== false);
const visibleCategoryIds = new Set(visibleCategories.map(category => category.id));
// Fetch packs with category info and question count
let query = supabase
.from("question_packs")
.select("*, category:categories(*), questions(count)")
.eq("is_public", true)
.order("sort_order");
// Filter out packs above user's intensity preference
if (maxIntensity < 5) {
query = query.or(`max_intensity.is.null,max_intensity.lte.${maxIntensity}`);
}
const { data: packs } = await query;
// Also fetch enabled packs if logged in
await get().fetchEnabledPacks();
set({
packs: packs ?? [],
categories: categories ?? [],
isLoading: false
});
},
const { data: packs } = await query;
const visiblePacks = (packs ?? []).filter(pack => {
if (pack.category?.is_public === false) return false;
if (pack.category_id && visibleCategoryIds.size > 0 && !visibleCategoryIds.has(pack.category_id)) {
return false;
}
return true;
});
// Also fetch enabled packs if logged in
await get().fetchEnabledPacks();
set({
packs: visiblePacks,
categories: visibleCategories,
isLoading: false
});
},
fetchEnabledPacks: async () => {
const coupleId = useAuthStore.getState().user?.couple_id;
+3 -3
View File
@@ -93,7 +93,7 @@ export const useResponsesStore = create<ResponsesState>((set, get) => ({
if (refresh) {
const { count, error: countError } = await supabase
.from("responses")
.select("*", { count: "exact", head: true })
.select("*, question:questions!inner(pack:question_packs!inner(id))", { count: "exact", head: true })
.eq("user_id", userId);
if (!countError) {
@@ -109,13 +109,13 @@ export const useResponsesStore = create<ResponsesState>((set, get) => ({
question_id,
answer,
created_at,
question:questions(
question:questions!inner(
id,
text,
partner_text,
intensity,
pack_id,
pack:question_packs(id, name, icon)
pack:question_packs!inner(id, name, icon)
)
`)
.eq("user_id", userId)
+10 -8
View File
@@ -28,14 +28,16 @@ export interface Couple {
}
// Category for grouping packs
export interface Category {
id: string;
name: string;
description: string | null;
icon: string | null;
sort_order: number;
created_at: string;
}
export interface Category {
id: string;
name: string;
description: string | null;
icon: string | null;
sort_order: number;
created_at: string;
is_public: boolean;
}
// Question pack
export interface QuestionPack {
+385 -16
View File
@@ -47,49 +47,106 @@ export type Database = {
ai_config: {
Row: {
cherry_pick_ensure_intensity_distribution: boolean | null
classifier_enabled: boolean | null
classifier_model: string | null
classifier_prompt: string | null
classifier_temperature: number | null
council_enabled: boolean | null
council_generator_model: string | null
council_generators: Json | null
council_reviewer_model: string | null
council_reviewer_temperature: number | null
council_selection_mode: string | null
default_model: string | null
default_temperature: number | null
heuristic_keyword_triggers: string | null
heuristic_min_text_length: number
heuristic_record_reason: boolean
heuristic_skip_if_no_alnum: boolean
heuristic_skip_media_without_text: boolean
heuristic_use_default_keywords: boolean
heuristic_use_default_whitelist: boolean
heuristic_whitelist: string | null
heuristic_whitelist_max_length: number
heuristics_enabled: boolean
id: string
model_fix: string | null
model_generate: string | null
model_polish: string | null
openrouter_api_key: string | null
temperature_fix: number | null
temperature_generate: number | null
temperature_polish: number | null
updated_at: string | null
updated_by: string | null
}
Insert: {
cherry_pick_ensure_intensity_distribution?: boolean | null
classifier_enabled?: boolean | null
classifier_model?: string | null
classifier_prompt?: string | null
classifier_temperature?: number | null
council_enabled?: boolean | null
council_generator_model?: string | null
council_generators?: Json | null
council_reviewer_model?: string | null
council_reviewer_temperature?: number | null
council_selection_mode?: string | null
default_model?: string | null
default_temperature?: number | null
heuristic_keyword_triggers?: string | null
heuristic_min_text_length?: number
heuristic_record_reason?: boolean
heuristic_skip_if_no_alnum?: boolean
heuristic_skip_media_without_text?: boolean
heuristic_use_default_keywords?: boolean
heuristic_use_default_whitelist?: boolean
heuristic_whitelist?: string | null
heuristic_whitelist_max_length?: number
heuristics_enabled?: boolean
id?: string
model_fix?: string | null
model_generate?: string | null
model_polish?: string | null
openrouter_api_key?: string | null
temperature_fix?: number | null
temperature_generate?: number | null
temperature_polish?: number | null
updated_at?: string | null
updated_by?: string | null
}
Update: {
cherry_pick_ensure_intensity_distribution?: boolean | null
classifier_enabled?: boolean | null
classifier_model?: string | null
classifier_prompt?: string | null
classifier_temperature?: number | null
council_enabled?: boolean | null
council_generator_model?: string | null
council_generators?: Json | null
council_reviewer_model?: string | null
council_reviewer_temperature?: number | null
council_selection_mode?: string | null
default_model?: string | null
default_temperature?: number | null
heuristic_keyword_triggers?: string | null
heuristic_min_text_length?: number
heuristic_record_reason?: boolean
heuristic_skip_if_no_alnum?: boolean
heuristic_skip_media_without_text?: boolean
heuristic_use_default_keywords?: boolean
heuristic_use_default_whitelist?: boolean
heuristic_whitelist?: string | null
heuristic_whitelist_max_length?: number
heuristics_enabled?: boolean
id?: string
model_fix?: string | null
model_generate?: string | null
model_polish?: string | null
openrouter_api_key?: string | null
temperature_fix?: number | null
temperature_generate?: number | null
temperature_polish?: number | null
updated_at?: string | null
updated_by?: string | null
}
@@ -124,6 +181,7 @@ export type Database = {
action: Database["public"]["Enums"]["audit_action"]
admin_role: Database["public"]["Enums"]["admin_role"]
admin_user_id: string
admin_username: string | null
changed_fields: string[] | null
created_at: string | null
id: string
@@ -136,6 +194,7 @@ export type Database = {
action: Database["public"]["Enums"]["audit_action"]
admin_role: Database["public"]["Enums"]["admin_role"]
admin_user_id: string
admin_username?: string | null
changed_fields?: string[] | null
created_at?: string | null
id?: string
@@ -148,6 +207,7 @@ export type Database = {
action?: Database["public"]["Enums"]["audit_action"]
admin_role?: Database["public"]["Enums"]["admin_role"]
admin_user_id?: string
admin_username?: string | null
changed_fields?: string[] | null
created_at?: string | null
id?: string
@@ -164,6 +224,7 @@ export type Database = {
description: string | null
icon: string | null
id: string
is_public: boolean
name: string
sort_order: number | null
}
@@ -172,6 +233,7 @@ export type Database = {
description?: string | null
icon?: string | null
id?: string
is_public?: boolean
name: string
sort_order?: number | null
}
@@ -180,6 +242,7 @@ export type Database = {
description?: string | null
icon?: string | null
id?: string
is_public?: boolean
name?: string
sort_order?: number | null
}
@@ -268,6 +331,139 @@ export type Database = {
}
Relationships: []
}
dare_messages: {
Row: {
content: string
created_at: string
id: string
read_at: string | null
sender_id: string
sent_dare_id: string
}
Insert: {
content: string
created_at?: string
id?: string
read_at?: string | null
sender_id: string
sent_dare_id: string
}
Update: {
content?: string
created_at?: string
id?: string
read_at?: string | null
sender_id?: string
sent_dare_id?: string
}
Relationships: [
{
foreignKeyName: "dare_messages_sender_id_fkey"
columns: ["sender_id"]
isOneToOne: false
referencedRelation: "profiles"
referencedColumns: ["id"]
},
{
foreignKeyName: "dare_messages_sent_dare_id_fkey"
columns: ["sent_dare_id"]
isOneToOne: false
referencedRelation: "sent_dares"
referencedColumns: ["id"]
},
]
}
dare_packs: {
Row: {
avg_intensity: number | null
category_id: string | null
created_at: string
description: string | null
icon: string | null
id: string
is_explicit: boolean
is_premium: boolean
is_public: boolean
max_intensity: number | null
min_intensity: number | null
name: string
sort_order: number
}
Insert: {
avg_intensity?: number | null
category_id?: string | null
created_at?: string
description?: string | null
icon?: string | null
id?: string
is_explicit?: boolean
is_premium?: boolean
is_public?: boolean
max_intensity?: number | null
min_intensity?: number | null
name: string
sort_order?: number
}
Update: {
avg_intensity?: number | null
category_id?: string | null
created_at?: string
description?: string | null
icon?: string | null
id?: string
is_explicit?: boolean
is_premium?: boolean
is_public?: boolean
max_intensity?: number | null
min_intensity?: number | null
name?: string
sort_order?: number
}
Relationships: [
{
foreignKeyName: "dare_packs_category_id_fkey"
columns: ["category_id"]
isOneToOne: false
referencedRelation: "categories"
referencedColumns: ["id"]
},
]
}
dares: {
Row: {
created_at: string
id: string
intensity: number
pack_id: string
suggested_duration_hours: number | null
text: string
}
Insert: {
created_at?: string
id?: string
intensity?: number
pack_id: string
suggested_duration_hours?: number | null
text: string
}
Update: {
created_at?: string
id?: string
intensity?: number
pack_id?: string
suggested_duration_hours?: number | null
text?: string
}
Relationships: [
{
foreignKeyName: "dares_pack_id_fkey"
columns: ["pack_id"]
isOneToOne: false
referencedRelation: "dare_packs"
referencedColumns: ["id"]
},
]
}
feature_interests: {
Row: {
created_at: string
@@ -378,22 +574,22 @@ export type Database = {
}
match_archives: {
Row: {
archived_at: string | null
id: string
match_id: string
user_id: string
archived_at: string | null
}
Insert: {
archived_at?: string | null
id?: string
match_id: string
user_id: string
archived_at?: string | null
}
Update: {
archived_at?: string | null
id?: string
match_id?: string
user_id?: string
archived_at?: string | null
}
Relationships: [
{
@@ -403,13 +599,6 @@ export type Database = {
referencedRelation: "matches"
referencedColumns: ["id"]
},
{
foreignKeyName: "match_archives_user_id_fkey"
columns: ["user_id"]
isOneToOne: false
referencedRelation: "users"
referencedColumns: ["id"]
},
]
}
matches: {
@@ -456,22 +645,22 @@ export type Database = {
}
message_deletions: {
Row: {
deleted_at: string | null
id: string
message_id: string
user_id: string
deleted_at: string | null
}
Insert: {
deleted_at?: string | null
id?: string
message_id: string
user_id: string
deleted_at?: string | null
}
Update: {
deleted_at?: string | null
id?: string
message_id?: string
user_id?: string
deleted_at?: string | null
}
Relationships: [
{
@@ -481,23 +670,66 @@ export type Database = {
referencedRelation: "messages"
referencedColumns: ["id"]
},
]
}
message_reports: {
Row: {
created_at: string | null
id: string
message_id: string
reason: Database["public"]["Enums"]["report_reason"]
reporter_id: string
reviewed_at: string | null
reviewed_by: string | null
status: string
}
Insert: {
created_at?: string | null
id?: string
message_id: string
reason: Database["public"]["Enums"]["report_reason"]
reporter_id: string
reviewed_at?: string | null
reviewed_by?: string | null
status?: string
}
Update: {
created_at?: string | null
id?: string
message_id?: string
reason?: Database["public"]["Enums"]["report_reason"]
reporter_id?: string
reviewed_at?: string | null
reviewed_by?: string | null
status?: string
}
Relationships: [
{
foreignKeyName: "message_deletions_user_id_fkey"
columns: ["user_id"]
foreignKeyName: "message_reports_message_id_fkey"
columns: ["message_id"]
isOneToOne: false
referencedRelation: "users"
referencedRelation: "messages"
referencedColumns: ["id"]
},
{
foreignKeyName: "message_reports_reporter_profile_fk"
columns: ["reporter_id"]
isOneToOne: false
referencedRelation: "profiles"
referencedColumns: ["id"]
},
]
}
messages: {
Row: {
category: string | null
content: string | null
created_at: string | null
deleted_at: string | null
delivered_at: string | null
encrypted_content: string | null
encryption_iv: string | null
flag_reason: string | null
id: string
keys_metadata: Json | null
match_id: string
@@ -506,17 +738,20 @@ export type Database = {
media_path: string | null
media_type: string | null
media_viewed_at: string | null
moderation_status: string | null
read_at: string | null
user_id: string
version: number | null
}
Insert: {
category?: string | null
content?: string | null
created_at?: string | null
deleted_at?: string | null
delivered_at?: string | null
encrypted_content?: string | null
encryption_iv?: string | null
flag_reason?: string | null
id?: string
keys_metadata?: Json | null
match_id: string
@@ -525,17 +760,20 @@ export type Database = {
media_path?: string | null
media_type?: string | null
media_viewed_at?: string | null
moderation_status?: string | null
read_at?: string | null
user_id: string
version?: number | null
}
Update: {
category?: string | null
content?: string | null
created_at?: string | null
deleted_at?: string | null
delivered_at?: string | null
encrypted_content?: string | null
encryption_iv?: string | null
flag_reason?: string | null
id?: string
keys_metadata?: Json | null
match_id?: string
@@ -544,6 +782,7 @@ export type Database = {
media_path?: string | null
media_type?: string | null
media_viewed_at?: string | null
moderation_status?: string | null
read_at?: string | null
user_id?: string
version?: number | null
@@ -597,6 +836,7 @@ export type Database = {
gender: string | null
id: string
is_premium: boolean | null
max_intensity: number | null
name: string | null
onboarding_completed: boolean | null
public_key_jwk: Json | null
@@ -613,6 +853,7 @@ export type Database = {
gender?: string | null
id: string
is_premium?: boolean | null
max_intensity?: number | null
name?: string | null
onboarding_completed?: boolean | null
public_key_jwk?: Json | null
@@ -629,6 +870,7 @@ export type Database = {
gender?: string | null
id?: string
is_premium?: boolean | null
max_intensity?: number | null
name?: string | null
onboarding_completed?: boolean | null
public_key_jwk?: Json | null
@@ -649,6 +891,7 @@ export type Database = {
}
question_packs: {
Row: {
avg_intensity: number | null
category_id: string | null
created_at: string | null
description: string | null
@@ -657,10 +900,13 @@ export type Database = {
is_explicit: boolean
is_premium: boolean | null
is_public: boolean | null
max_intensity: number | null
min_intensity: number | null
name: string
sort_order: number | null
}
Insert: {
avg_intensity?: number | null
category_id?: string | null
created_at?: string | null
description?: string | null
@@ -669,10 +915,13 @@ export type Database = {
is_explicit?: boolean
is_premium?: boolean | null
is_public?: boolean | null
max_intensity?: number | null
min_intensity?: number | null
name: string
sort_order?: number | null
}
Update: {
avg_intensity?: number | null
category_id?: string | null
created_at?: string | null
description?: string | null
@@ -681,6 +930,8 @@ export type Database = {
is_explicit?: boolean
is_premium?: boolean | null
is_public?: boolean | null
max_intensity?: number | null
min_intensity?: number | null
name?: string
sort_order?: number | null
}
@@ -850,6 +1101,86 @@ export type Database = {
}
Relationships: []
}
sent_dares: {
Row: {
accepted_at: string | null
completed_at: string | null
couple_id: string
created_at: string
custom_dare_intensity: number | null
custom_dare_text: string | null
dare_id: string | null
expires_at: string | null
id: string
recipient_id: string
sender_id: string
sender_notes: string | null
sent_at: string
status: Database["public"]["Enums"]["dare_status"]
}
Insert: {
accepted_at?: string | null
completed_at?: string | null
couple_id: string
created_at?: string
custom_dare_intensity?: number | null
custom_dare_text?: string | null
dare_id?: string | null
expires_at?: string | null
id?: string
recipient_id: string
sender_id: string
sender_notes?: string | null
sent_at?: string
status?: Database["public"]["Enums"]["dare_status"]
}
Update: {
accepted_at?: string | null
completed_at?: string | null
couple_id?: string
created_at?: string
custom_dare_intensity?: number | null
custom_dare_text?: string | null
dare_id?: string | null
expires_at?: string | null
id?: string
recipient_id?: string
sender_id?: string
sender_notes?: string | null
sent_at?: string
status?: Database["public"]["Enums"]["dare_status"]
}
Relationships: [
{
foreignKeyName: "sent_dares_couple_id_fkey"
columns: ["couple_id"]
isOneToOne: false
referencedRelation: "couples"
referencedColumns: ["id"]
},
{
foreignKeyName: "sent_dares_dare_id_fkey"
columns: ["dare_id"]
isOneToOne: false
referencedRelation: "dares"
referencedColumns: ["id"]
},
{
foreignKeyName: "sent_dares_recipient_id_fkey"
columns: ["recipient_id"]
isOneToOne: false
referencedRelation: "profiles"
referencedColumns: ["id"]
},
{
foreignKeyName: "sent_dares_sender_id_fkey"
columns: ["sender_id"]
isOneToOne: false
referencedRelation: "profiles"
referencedColumns: ["id"]
},
]
}
subscriptions: {
Row: {
cancel_reason: string | null
@@ -964,6 +1295,14 @@ export type Database = {
}[]
}
get_auth_user_couple_id: { Args: never; Returns: string }
get_couple_dare_stats: {
Args: { p_couple_id: string }
Returns: {
total_dares_active: number
total_dares_completed: number
total_dares_sent: number
}[]
}
get_daily_response_limit_status: {
Args: never
Returns: {
@@ -1018,6 +1357,15 @@ export type Database = {
text: string
}[]
}
get_user_dare_stats: {
Args: { p_user_id: string }
Returns: {
dares_completed_as_recipient: number
dares_completed_as_sender: number
dares_received_count: number
dares_sent_count: number
}[]
}
get_user_media_files: {
Args: { user_id: string }
Returns: {
@@ -1053,11 +1401,22 @@ export type Database = {
Args: { p_code: string; p_email: string }
Returns: Json
}
update_question_pack_intensity_stats: {
Args: { target_pack_id: string }
Returns: undefined
}
}
Enums: {
admin_role: "pack_creator" | "super_admin"
answer_type: "yes" | "no" | "maybe"
audit_action: "INSERT" | "UPDATE" | "DELETE"
dare_status:
| "pending"
| "active"
| "completed"
| "expired"
| "declined"
| "cancelled"
feedback_status:
| "new"
| "reviewed"
@@ -1066,6 +1425,7 @@ export type Database = {
| "closed"
feedback_type: "bug" | "feature_request" | "general" | "question"
match_type: "yes_yes" | "yes_maybe" | "maybe_maybe"
report_reason: "harassment" | "spam" | "inappropriate_content" | "other"
subscription_status:
| "active"
| "cancelled"
@@ -1202,9 +1562,18 @@ export const Constants = {
admin_role: ["pack_creator", "super_admin"],
answer_type: ["yes", "no", "maybe"],
audit_action: ["INSERT", "UPDATE", "DELETE"],
dare_status: [
"pending",
"active",
"completed",
"expired",
"declined",
"cancelled",
],
feedback_status: ["new", "reviewed", "in_progress", "resolved", "closed"],
feedback_type: ["bug", "feature_request", "general", "question"],
match_type: ["yes_yes", "yes_maybe", "maybe_maybe"],
report_reason: ["harassment", "spam", "inappropriate_content", "other"],
subscription_status: [
"active",
"cancelled",