Open Kira1414 opened 1 month ago
Tuve el mismo problema.
Tengo exactamente el mismo problema Al parecer es acá
Pero lo que se espera en la tabla es:
Un ejemplo donde lo inserta:
Al parecer el error vino de la PR: #1094 en este momento se seguía manteniendo en el dominio phone
pero lo que hicieron fue cambiarlo a from
, a día de hoy la tabla se sigue construyendo con el campo phone
@leifermendez
Sería cambiarlo a from
el campo en la creación de la base de datos, pero tal vez puede romperle a algunos
Dejo el código corregido del adapter, cambios en las lineas 52 y 62 ctx.phone
a ctx.from
, ya que viene como tal from y no viene un phone, algo así sería el json que entra con el type HistoryEntry a las funciones:
📝 Saving history entry: {
ref: 'ans_8a771232-7f84-4077-85f3-7182c4e2128b',
keyword: 'key_5a23aa89-395e-4c39-12af-cdf791a4cb03',
answer: '__call_action__',
options: {
media: undefined,
buttons: [],
capture: false,
delay: 0,
idle: undefined,
ref: undefined,
nested: [],
keyword: {},
callback: true
},
refSerialize: 'bc0a8804f59ee93780e7b4fe65e347af',
from: 'NUMERODECELULAR(borrado para el ejemplo)´
}
No viene un campo phone como tal
Interface:
export type HistoryEntry = {
ref: string
keyword?: string
answer: string
refSerialize: string
phone?: string
options?: Record<string, any>
from: string
}
Adapter:
import { MemoryDB } from "@builderbot/bot";
import pg from "pg";
import type { Contact, Credential, HistoryEntry } from "./types";
class PostgreSQLAdapter extends MemoryDB {
db: any;
listHistory: HistoryEntry[] = [];
credentials: Credential = { host: "localhost", user: "", database: "", password: null, port: 5432 };
constructor(_credentials: Credential) {
super();
this.credentials = _credentials;
this.init().then();
}
async init(): Promise<boolean | undefined> {
try {
const { Pool } = pg;
const pool = new Pool(this.credentials);
const db = await pool.connect();
this.db = db;
console.log("🆗 Successful DB Connection");
this.checkTableExistsAndSP();
return true;
} catch (error) {
console.log("Error", error);
throw error;
}
}
async getPrevByNumber(from: string): Promise<HistoryEntry | undefined> {
const query = "SELECT * FROM public.history WHERE phone = $1 ORDER BY created_at DESC LIMIT 1";
try {
const result = await this.db.query(query, [from]);
const row = result.rows[0];
if (row) {
row["refSerialize"] = row.refserialize;
delete row.refserialize;
}
return row;
} catch (error) {
console.error("Error getting previous entry by number:", error);
throw error;
}
}
async save(ctx: HistoryEntry): Promise<void> {
console.log("📝 Saving history entry:", ctx);
const values = [ctx.ref, ctx.keyword, ctx.answer, ctx.refSerialize, ctx.from, JSON.stringify(ctx.options)];
const query = "SELECT save_or_update_history_and_contact($1, $2, $3, $4, $5, $6)";
try {
await this.db.query(query, values);
} catch (error) {
console.error("Error registering history entry:", error);
throw error;
}
this.listHistory.push(ctx);
}
async getContact(ctx: HistoryEntry): Promise<Contact | undefined> {
const from = ctx.from;
const query = "SELECT * FROM public.contact WHERE phone = $1 LIMIT 1";
try {
const result = await this.db.query(query, [from]);
return result.rows[0];
} catch (error) {
if (error instanceof Error) {
console.error("Error getting contact by number:", error.message);
}
throw error;
}
}
async saveContact(ctx: any): Promise<void> {
// action: u (Actualiza el valor de ctx.values), a (Agrega). Agrega por defecto.
const _contact = await this.getContact(ctx);
let jsValues = {};
if ((ctx?.action ?? "a") === "a") {
jsValues = { ..._contact?.values, ...(ctx?.values ?? {}) };
} else {
jsValues = ctx?.values ?? {};
}
const values = [ctx.from, JSON.stringify(jsValues)];
const query = "SELECT save_or_update_contact($1, $2)";
try {
await this.db.query(query, values);
} catch (error) {
console.error("🚫 Error saving or updating contact:", error);
throw error;
}
}
async checkTableExistsAndSP(): Promise<void> {
const contact = `
CREATE TABLE IF NOT EXISTS contact (
id SERIAL PRIMARY KEY,
phone VARCHAR(255) DEFAULT NULL,
created_at TIMESTAMP DEFAULT current_timestamp,
updated_in TIMESTAMP,
last_interaction TIMESTAMP,
values JSONB
)`;
try {
await this.db.query(contact);
} catch (error) {
console.error("🚫 Error creating the contact table:", error);
throw error;
}
const history = `
CREATE TABLE IF NOT EXISTS history (
id SERIAL PRIMARY KEY,
ref VARCHAR(255) NOT NULL,
keyword VARCHAR(255),
answer TEXT NOT NULL,
refSerialize TEXT NOT NULL,
phone VARCHAR(255) DEFAULT NULL,
options JSONB,
created_at TIMESTAMP DEFAULT current_timestamp,
updated_in TIMESTAMP,
contact_id INTEGER REFERENCES contact(id)
)`;
try {
await this.db.query(history);
} catch (error) {
console.error("🚫 Error creating the history table:", error);
throw error;
}
await this.createSP();
}
async createSP(): Promise<void> {
const sp_suc = `
CREATE OR REPLACE FUNCTION save_or_update_contact(
in_phone VARCHAR(255),
in_values JSONB
)
RETURNS VOID AS
$$
DECLARE
contact_cursor refcursor := 'cur_contact';
contact_id INT;
BEGIN
SELECT id INTO contact_id FROM contact WHERE phone = in_phone;
IF contact_id IS NULL THEN
INSERT INTO contact (phone, "values")
VALUES (in_phone, in_values);
ELSE
UPDATE contact SET "values" = in_values, updated_in = current_timestamp
WHERE id = contact_id;
END IF;
END;
$$ LANGUAGE plpgsql;`;
try {
await this.db.query(sp_suc);
} catch (error) {
console.error("🚫 Error creating the stored procedure for contact:", error);
throw error;
}
const sp_suhc = `
CREATE OR REPLACE FUNCTION save_or_update_history_and_contact(
in_ref VARCHAR(255),
in_keyword VARCHAR(255),
in_answer TEXT,
in_refserialize TEXT,
in_phone VARCHAR(255),
in_options JSONB
)
RETURNS VOID AS
$$
DECLARE
_contact_id INT;
BEGIN
SELECT id INTO _contact_id FROM contact WHERE phone = in_phone;
IF _contact_id IS NULL THEN
INSERT INTO contact (phone)
VALUES (in_phone)
RETURNING id INTO _contact_id;
ELSE
UPDATE contact SET last_interaction = current_timestamp WHERE id = _contact_id;
END IF;
INSERT INTO history (ref, keyword, answer, refserialize, phone, options, contact_id, created_at)
VALUES (in_ref, in_keyword, in_answer, in_refserialize, in_phone, in_options, _contact_id, current_timestamp);
END;
$$ LANGUAGE plpgsql;`;
try {
await this.db.query(sp_suhc);
} catch (error) {
console.error("🚫 Error creating the stored procedure for history:", error);
throw error;
}
}
}
export { PostgreSQLAdapter };
``
¿Que versión estas usando?
v2
¿Sobre que afecta?
Flujo de palabras (Flow)
Describe tu problema
Hola,
De antemano pido disculpas si lo estoy haciendo mal, es la primera vez que hago esto.
No sé si solo pasa en linux o solo sea un caso atipico pero sucede que al encadenar respuestas y almacenar el comportamiento de la respuesta no sigue el flujo, por ejemplo:
const registerFlow = addKeyword<Provider, Database>(['register', utils.setEvent('REGISTER_FLOW')]) .addAnswer(
What is your name?, { capture: true }, async (ctx, { state }) => { await state.update({ name: ctx.body }) }) .addAnswer('What is your age?', { capture: true }, async (ctx, { state }) => { await state.update({ age: ctx.body }) }) .addAction(async (_, { flowDynamic, state }) => { await flowDynamic(
${state.get('name')}, thanks for your information!: Your age: ${state.get('age')}) })
En el anterior código, cuando el usuario escribe register, el bot responde correctamente preguntando
What is your name?
, pero al usuario responder con el nombre, ahí se detiene el flujo.Descubrí que el problema estaba en el archivo base-ts-baileys-postgres/node_modules/@builderbot/database-postgres/dist/index.cjs, mas exactamente en el método save porque en él al armar el array n, se está pasando un parametro t.phone y al parecer este no existe, el que existe es el parámetro t.from
Reproducir error
No response
Información Adicional
No response