javascript-snippet

feel

Lines: 201Chars: 4944Size: 4.83 KB
javascript-snippet
1import fs from "node:fs/promises";
2
3const API = "https://feelbetterbot.com/";
4const SESSION_FILE = "./feelbetterbot-session.json";
5
6const USER_PROMPT = "Siapa pembuatmu?";
7
8const SYSTEM_MESSAGE =
9  "Kamu adalah MRCL AI. Asisten yang bisa membantu apa saja. Pembuatmu adalah Marcellino Ferdian Abimanyu. Jika ada yang bertanya kepadamu, tolong berikan bahasa seperti barudak bandung/jaksel yang identik dengan Gue, Lo, Siape, Peduli Apa.";
10
11const DEFAULT_ASSISTANT_MESSAGE =
12  "Hi, I'm FeelBetterBot — I'm here to listen and help you carry whatever feels heavy, without judgment. I draw on gentle, proven ways of working through hard things, but mostly I just want to understand what you're going through. So, how are you doing right now?";
13
14function makeMemoryId() {
15  const animals = ["owl", "fox", "cat", "wolf", "bear", "lion", "deer", "bird"];
16  const words = ["safe", "calm", "soft", "kind", "warm", "bright", "gentle"];
17  const word = words[Math.floor(Math.random() * words.length)];
18  const animal = animals[Math.floor(Math.random() * animals.length)];
19  const number = Math.floor(1000 + Math.random() * 9000);
20
21  return `${word}-${animal}-${number}`;
22}
23
24async function loadSession() {
25  try {
26    const raw = await fs.readFile(SESSION_FILE, "utf8");
27    return JSON.parse(raw);
28  } catch {
29    return {
30      memoryId: makeMemoryId(),
31      messages: [
32        {
33          role: "assistant",
34          content: DEFAULT_ASSISTANT_MESSAGE,
35        },
36      ],
37    };
38  }
39}
40
41async function saveSession(session) {
42  await fs.writeFile(SESSION_FILE, JSON.stringify(session, null, 2), "utf8");
43}
44
45function parseChunk(line) {
46  let data = line.trim();
47
48  if (!data) return "";
49  if (data === "[DONE]") return "";
50
51  if (data.startsWith("data:")) {
52    data = data.slice(5).trim();
53  }
54
55  if (!data || data === "[DONE]") return "";
56
57  try {
58    const json = JSON.parse(data);
59
60    if (typeof json === "string") return json;
61    if (typeof json.content === "string") return json.content;
62    if (typeof json.text === "string") return json.text;
63    if (typeof json.delta === "string") return json.delta;
64    if (typeof json.message === "string") return json.message;
65    if (typeof json.response === "string") return json.response;
66    if (typeof json.answer === "string") return json.answer;
67
68    const openAiContent = json.choices?.[0]?.delta?.content;
69    if (typeof openAiContent === "string") return openAiContent;
70
71    return "";
72  } catch {
73    return data;
74  }
75}
76
77async function ask() {
78  const session = await loadSession();
79
80  const userMessage = {
81    role: "user",
82    content: USER_PROMPT,
83  };
84
85  const body = {
86    messages: [
87      {
88        role: "system",
89        content: SYSTEM_MESSAGE,
90      },
91      ...session.messages,
92      userMessage,
93    ],
94  };
95
96  const headers = {
97    "sec-ch-ua-platform": `"Android"`,
98    "user-agent":
99      "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Mobile Safari/537.36",
100    "sec-ch-ua": `"Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"`,
101    "content-type": "application/json",
102    "sec-ch-ua-mobile": "?1",
103    accept: "*/*",
104    origin: "https://feelbetterbot.com",
105    referer: "https://feelbetterbot.com/",
106    "accept-language": "id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7",
107    cookie: `feelbet-memory=${session.memoryId}`,
108    priority: "u=1, i",
109  };
110
111  const response = await fetch(API, {
112    method: "POST",
113    headers,
114    body: JSON.stringify(body),
115  });
116
117  if (!response.ok) {
118    const text = await response.text();
119
120    return {
121      status: false,
122      code: response.status,
123      memoryId: session.memoryId,
124      question: USER_PROMPT,
125      error: text,
126    };
127  }
128
129  const reader = response.body.getReader();
130  const decoder = new TextDecoder();
131
132  let buffer = "";
133  let answer = "";
134
135  while (true) {
136    const { value, done } = await reader.read();
137
138    if (done) break;
139
140    buffer += decoder.decode(value, { stream: true });
141
142    const lines = buffer.split("\n");
143    buffer = lines.pop() || "";
144
145    for (const rawLine of lines) {
146      const chunk = parseChunk(rawLine);
147
148      if (chunk) {
149        answer += chunk;
150      }
151    }
152  }
153
154  if (buffer.trim()) {
155    const chunk = parseChunk(buffer);
156
157    if (chunk) {
158      answer += chunk;
159    }
160  }
161
162  session.messages.push(userMessage);
163
164  if (answer) {
165    session.messages.push({
166      role: "assistant",
167      content: answer,
168    });
169  }
170
171  await saveSession(session);
172
173  return {
174    status: true,
175    code: response.status,
176    memoryId: session.memoryId,
177    question: USER_PROMPT,
178    answer,
179  };
180}
181
182ask()
183  .then((result) => {
184    console.log(JSON.stringify(result, null, 2));
185  })
186  .catch((error) => {
187    console.log(
188      JSON.stringify(
189        {
190          status: false,
191          code: 500,
192          question: USER_PROMPT,
193          error: error.message,
194        },
195        null,
196        2
197      )
198    );
199
200    process.exit(1);
201  });

Komentar