diff --git a/backend/MCP_Execution_Server/src/routes/user.routes.ts b/backend/MCP_Execution_Server/src/routes/user.routes.ts index 510ea1b..27b5044 100644 --- a/backend/MCP_Execution_Server/src/routes/user.routes.ts +++ b/backend/MCP_Execution_Server/src/routes/user.routes.ts @@ -67,5 +67,25 @@ export function userRouter(userService: UserService): Router { } }, ); + + router.post( + "/unsubscribe/user", + async (req: Request, res: Response, next: NextFunction): Promise => { + const { fid } = req.body; + + if (!fid) { + res.status(400).json({ error: "Missing User FID" }); + return; + } + + try { + const result = await userService.unsubscribeUser(fid); + res.status(200).json({ success: true, data: result }); + } catch (error) { + console.error("Error in /unsubscribe/user:", error); + next(error); + } + }, + ); return router; } diff --git a/backend/MCP_Execution_Server/src/services/db.service.ts b/backend/MCP_Execution_Server/src/services/db.service.ts index e0ac523..a089aba 100644 --- a/backend/MCP_Execution_Server/src/services/db.service.ts +++ b/backend/MCP_Execution_Server/src/services/db.service.ts @@ -1,172 +1,221 @@ - import { createClient } from "@supabase/supabase-js"; import type { SupabaseClient } from "@supabase/supabase-js"; export class DBService { - supabase: SupabaseClient; - constructor(SUPABASE_URL: string, SUPABASE_ANON_KEY: string) { - this.supabase = createClient( - SUPABASE_URL, - SUPABASE_ANON_KEY - ); + supabase: SupabaseClient; + constructor(SUPABASE_URL: string, SUPABASE_ANON_KEY: string) { + this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); + } + + async fetchSubscriberCount() { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("fid") + .eq("is_subscribed", true); + if (error) throw error; + return { success: true, data: data.length }; + } catch (err: any) { + console.error("fetchSubscriberCount error", err); + return { success: false, error: err.message || err, data: 0 }; } + } - async fetchSubscriberCount() { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("fid").eq("is_subscribed", true); - if (error) throw error; - return { success: true, data: data.length }; - } catch (err: any) { - console.error("fetchSubscriberCount error", err); - return { success: false, error: err.message || err, data: 0 }; - } + async getUser(fid: number) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("*") + .eq("fid", fid); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("getUser error", err); + return { success: false, error: err.message || err }; } + } - async getUser(fid: number) { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("*").eq("fid", fid); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("getUser error", err); - return { success: false, error: err.message || err }; - } + async isSubscribed(fid: number) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("fid") + .eq("fid", fid) + .eq("is_subscribed", true) + .maybeSingle(); + if (error) throw error; + return { success: true, subscribed: !!data }; + } catch (err: any) { + console.error("checkSubscribedUser error", err); + return { success: false, error: err.message || err }; } + } - async isSubscribed(fid: number) { - try { - const { data, error } = await this.supabase - .from("user_embeddings") - .select("fid") - .eq("fid", fid) - .eq("is_subscribed", true) - .maybeSingle(); - if (error) throw error; - return { success: true, subscribed: !!data }; - } catch (err: any) { - console.error("checkSubscribedUser error", err); - return { success: false, error: err.message || err }; - } + async unsubscribeFID(fid: number) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .update({ is_subscribed: false }) + .eq("fid", fid); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("unsubscribeFID error", err); + return { success: false, error: err.message || err }; } + } - async isRegistered(fid: number) { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("fid").eq("fid", fid).maybeSingle(); - if (error) throw error; - return { success: true, registered: !!data }; - } catch (err: any) { - console.error("isRegistered error", err); - return { success: false, error: err.message || err }; - } + async isRegistered(fid: number) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("fid") + .eq("fid", fid) + .maybeSingle(); + if (error) throw error; + return { success: true, registered: !!data }; + } catch (err: any) { + console.error("isRegistered error", err); + return { success: false, error: err.message || err }; } + } - async registerAndSubscribeFID(fid: string, summary: any, embeddings: any) { - try { - const { data, error } = await this.supabase.from("user_embeddings").insert({ - fid, - summary, - embeddings, - is_subscribed: true - }); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("registerUser error", err); - return { success: false, error: err.message || err }; - } + async registerAndSubscribeFID(fid: string, summary: any, embeddings: any) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .insert({ + fid, + summary, + embeddings, + is_subscribed: true, + }); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("registerUser error", err); + return { success: false, error: err.message || err }; } + } - async onlySubscribeFID(fid: string) { - try { - const { data, error } = await this.supabase.from("user_embeddings").update({ is_subscribed: true }).eq("fid", fid); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("onlySubscribeFID error", err); - return { success: false, error: err.message || err }; - } + async onlySubscribeFID(fid: string) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .update({ is_subscribed: true }) + .eq("fid", fid); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("onlySubscribeFID error", err); + return { success: false, error: err.message || err }; } + } - async onlyRegisterFID(fid: string, summary: any, embeddings: any) { - try { - const { data, error } = await this.supabase.from("user_embeddings").insert({ - fid, - summary, - embeddings, - is_subscribed: false - }); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("registerUser error", err); - return { success: false, error: err.message || err }; - } + async onlyRegisterFID(fid: string, summary: any, embeddings: any) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .insert({ + fid, + summary, + embeddings, + is_subscribed: false, + }); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("registerUser error", err); + return { success: false, error: err.message || err }; } + } - async fetchSubscribedFIDs() { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("fid").eq("is_subscribed", true); - if (error) throw error; - const fids = data.map((user: any) => user.fid); - return { success: true, data: fids }; - } catch (err: any) { - console.error("fetchSubscribedFIDs error", err); - return { success: false, error: err.message || err, data: [] }; - } + async fetchSubscribedFIDs() { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("fid") + .eq("is_subscribed", true); + if (error) throw error; + const fids = data.map((user: any) => user.fid); + return { success: true, data: fids }; + } catch (err: any) { + console.error("fetchSubscribedFIDs error", err); + return { success: false, error: err.message || err, data: [] }; } + } - async checkFIDStatus(fid: number) { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("fid, is_subscribed").eq("fid", fid).maybeSingle(); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("checkFIDStatus error", err); - return { success: false, error: err.message || err }; - } + async checkFIDStatus(fid: number) { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("fid, is_subscribed") + .eq("fid", fid) + .maybeSingle(); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("checkFIDStatus error", err); + return { success: false, error: err.message || err }; } + } - async fetchAllFIDs() { - try { - const { data, error } = await this.supabase.from("user_embeddings").select("*"); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("fetchAllFIDs error", err); - return { success: false, error: err.message || err }; - } + async fetchAllFIDs() { + try { + const { data, error } = await this.supabase + .from("user_embeddings") + .select("*"); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("fetchAllFIDs error", err); + return { success: false, error: err.message || err }; } + } - async fetchSimilarFIDs(cast_embeddings: any, match_threshold: number, match_count: number) { - try { - const { data, error } = await this.supabase.rpc("match_users_by_embedding", { query_embedding: cast_embeddings, match_threshold, match_count }); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("fetchSimilarFIDs error", err); - return { success: false, error: err.message || err }; - } + async fetchSimilarFIDs( + cast_embeddings: any, + match_threshold: number, + match_count: number, + ) { + try { + const { data, error } = await this.supabase.rpc( + "match_users_by_embedding", + { query_embedding: cast_embeddings, match_threshold, match_count }, + ); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("fetchSimilarFIDs error", err); + return { success: false, error: err.message || err }; } + } - async addCastReply(cast_hash: string) { - try { - const { data, error } = await this.supabase.from("cast_replies").insert([{ cast_hash }]); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("addCastReply error", err); - return { success: false, error: err.message || err }; - } + async addCastReply(cast_hash: string) { + try { + const { data, error } = await this.supabase + .from("cast_replies") + .insert([{ cast_hash }]); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("addCastReply error", err); + return { success: false, error: err.message || err }; } + } - async isCastReplyExists(cast_hash: string) { - try { - const { data, error } = await this.supabase.from("cast_replies").select("cast_hash").eq("cast_hash", cast_hash).maybeSingle(); - if (error) throw error; - return { success: true, data }; - } catch (err: any) { - console.error("isCastReplyExists error", err); - return { success: false, error: err.message || err }; - } + async isCastReplyExists(cast_hash: string) { + try { + const { data, error } = await this.supabase + .from("cast_replies") + .select("cast_hash") + .eq("cast_hash", cast_hash) + .maybeSingle(); + if (error) throw error; + return { success: true, data }; + } catch (err: any) { + console.error("isCastReplyExists error", err); + return { success: false, error: err.message || err }; } + } } diff --git a/backend/MCP_Execution_Server/src/services/user.service.ts b/backend/MCP_Execution_Server/src/services/user.service.ts index 9ac00de..95d7920 100644 --- a/backend/MCP_Execution_Server/src/services/user.service.ts +++ b/backend/MCP_Execution_Server/src/services/user.service.ts @@ -25,7 +25,17 @@ export class UserService { return { success: false, error: err.message || err }; } } - + + async unsubscribeUser(fid: number) { + try { + const { success, data } = await this.db.unsubscribeFID(fid); + if (!success) throw new Error("Failed to unsubscribe user"); + return { success: true, data }; + } catch (err: any) { + console.error("unsubscribeUser error", err); + return { success: false, error: err.message || err }; + } + } async checkSubscribedUser(fid: number) { try { const { success, subscribed } = await this.db.isSubscribed(fid);