zaileys 1.1.31 → 1.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2137,149 +2137,23 @@ declare class Worker {
2137
2137
  mute(mute: z.infer<typeof MuteWorkerBaseType>, options: z.infer<typeof MuteWorkerOptionsType>): Promise<void | undefined>;
2138
2138
  profile(roomId: z.infer<typeof ProfileWorkerBaseType>): Promise<z.infer<typeof ProfileWorkerBaseOutputType> | null>;
2139
2139
  presence(action: z.infer<typeof PresenceWorkerBaseType>, options: z.infer<typeof PresenceWorkerOptionsType>): Promise<void | undefined>;
2140
- addCompletion(props: z.infer<typeof llmMessagesTable>): Promise<{
2141
- channelId: string;
2142
- uniqueId: string;
2143
- role: string;
2144
- content: string;
2145
- model?: string | null | undefined;
2146
- additional?: string | null | undefined;
2147
- }>;
2148
- deleteCompletion(uniqueId: string): Promise<boolean>;
2149
- updateCompletion(uniqueId: string, props: Partial<z.infer<typeof llmMessagesTable>>): Promise<{
2150
- channelId: string;
2151
- uniqueId: string;
2152
- role: string;
2153
- content: string;
2154
- model?: string | null | undefined;
2155
- additional?: string | null | undefined;
2156
- }>;
2157
- clearCompletions(channelId: string): Promise<boolean>;
2158
- getCompletion(uniqueId: string): Promise<{
2159
- channelId: string;
2160
- uniqueId: string;
2161
- role: string;
2162
- content: string;
2163
- model?: string | null | undefined;
2164
- additional?: string | null | undefined;
2165
- } | null>;
2166
- getCompletions(channelId: string): Promise<{
2167
- channelId: string;
2168
- uniqueId: string;
2169
- role: string;
2170
- content: string;
2171
- model?: string | null | undefined;
2172
- additional?: string | null | undefined;
2173
- }[]>;
2174
- addPersonalization(props: z.infer<typeof llmPersonalizationTable>): Promise<{
2175
- uniqueId: string;
2176
- content: string;
2177
- senderId: string;
2178
- }>;
2179
- deletePersonalization(uniqueId: string): Promise<boolean>;
2180
- clearPersonalization(senderId: string): Promise<boolean>;
2181
- getPersonalization(senderId: string): Promise<{
2182
- uniqueId: string;
2183
- content: string;
2184
- senderId: string;
2185
- }[]>;
2186
- addRAG(props: z.infer<typeof addRAGType>): Promise<any>;
2187
- deleteRAG(id: string): Promise<boolean>;
2188
- updateRAG(id: string): Promise<{
2189
- metadata: {
2190
- id: string;
2191
- };
2192
- pageContent: string;
2193
- }>;
2194
- clearRAGs(): Promise<boolean>;
2195
- getRAG(id: string): Promise<{
2196
- metadata: {
2197
- id: string;
2198
- };
2199
- pageContent: string;
2200
- } | null>;
2201
- getRAGs(keyword: string): Promise<{
2202
- metadata: {
2203
- id: string;
2204
- };
2205
- pageContent: string;
2206
- }[]>;
2207
- getMessage(chatId: string): Promise<{
2208
- channelId: string;
2209
- uniqueId: string;
2210
- message: (...args: unknown[]) => Record<string, any>;
2211
- senderId: string;
2212
- roomId: string;
2213
- isGroup: boolean;
2214
- text: string | null;
2215
- chatId: string;
2216
- receiverId: string;
2217
- receiverName: string;
2218
- roomName: string;
2219
- senderName: string;
2220
- senderDevice: "unknown" | "android" | "ios" | "desktop" | "web";
2221
- chatType: "text" | "image" | "contact" | "location" | "document" | "audio" | "video" | "protocol" | "contactsArray" | "highlyStructured" | "sendPayment" | "liveLocation" | "requestPayment" | "declinePaymentRequest" | "cancelPaymentRequest" | "template" | "sticker" | "groupInvite" | "templateButtonReply" | "product" | "deviceSent" | "list" | "viewOnce" | "order" | "listResponse" | "ephemeral" | "invoice" | "buttons" | "buttonsResponse" | "paymentInvite" | "interactive" | "reaction" | "interactiveResponse" | "pollCreation" | "pollUpdate" | "keepInChat" | "requestPhoneNumber" | "scheduledCallCreation" | "groupMentioned" | "pinInChat" | "scheduledCallEdit" | "ptv" | "botInvoke" | "callLog" | "encComment" | "bcall" | "lottieSticker" | "event" | "comment" | "placeholder" | "encEventUpdate";
2222
- timestamp: number;
2223
- mentions: string[];
2224
- links: string[];
2225
- isPrefix: boolean;
2226
- isSpam: boolean;
2227
- isFromMe: boolean;
2228
- isTagMe: boolean;
2229
- isStory: boolean;
2230
- isViewOnce: boolean;
2231
- isEdited: boolean;
2232
- isDeleted: boolean;
2233
- isPinned: boolean;
2234
- isUnPinned: boolean;
2235
- isChannel: boolean;
2236
- isBroadcast: boolean;
2237
- isEphemeral: boolean;
2238
- isForwarded: boolean;
2239
- citation: Record<string, boolean> | null;
2240
- media: z.objectOutputType<{
2241
- buffer: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<Buffer<ArrayBufferLike>, z.ZodTypeDef, Buffer<ArrayBufferLike>>>;
2242
- stream: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<stream.Readable, z.ZodTypeDef, stream.Readable>>;
2243
- }, z.ZodTypeAny, "passthrough"> | null;
2244
- replied: {
2245
- channelId: string;
2246
- uniqueId: string;
2247
- message: (...args: unknown[]) => Record<string, any>;
2248
- senderId: string;
2249
- roomId: string;
2250
- isGroup: boolean;
2251
- text: string | null;
2252
- chatId: string;
2253
- receiverId: string;
2254
- receiverName: string;
2255
- roomName: string;
2256
- senderName: string;
2257
- senderDevice: "unknown" | "android" | "ios" | "desktop" | "web";
2258
- chatType: "text" | "image" | "contact" | "location" | "document" | "audio" | "video" | "protocol" | "contactsArray" | "highlyStructured" | "sendPayment" | "liveLocation" | "requestPayment" | "declinePaymentRequest" | "cancelPaymentRequest" | "template" | "sticker" | "groupInvite" | "templateButtonReply" | "product" | "deviceSent" | "list" | "viewOnce" | "order" | "listResponse" | "ephemeral" | "invoice" | "buttons" | "buttonsResponse" | "paymentInvite" | "interactive" | "reaction" | "interactiveResponse" | "pollCreation" | "pollUpdate" | "keepInChat" | "requestPhoneNumber" | "scheduledCallCreation" | "groupMentioned" | "pinInChat" | "scheduledCallEdit" | "ptv" | "botInvoke" | "callLog" | "encComment" | "bcall" | "lottieSticker" | "event" | "comment" | "placeholder" | "encEventUpdate";
2259
- timestamp: number;
2260
- mentions: string[];
2261
- links: string[];
2262
- isPrefix: boolean;
2263
- isSpam: boolean;
2264
- isFromMe: boolean;
2265
- isTagMe: boolean;
2266
- isStory: boolean;
2267
- isViewOnce: boolean;
2268
- isEdited: boolean;
2269
- isDeleted: boolean;
2270
- isPinned: boolean;
2271
- isUnPinned: boolean;
2272
- isChannel: boolean;
2273
- isBroadcast: boolean;
2274
- isEphemeral: boolean;
2275
- isForwarded: boolean;
2276
- citation: Record<string, boolean> | null;
2277
- media: z.objectOutputType<{
2278
- buffer: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<Buffer<ArrayBufferLike>, z.ZodTypeDef, Buffer<ArrayBufferLike>>>;
2279
- stream: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<stream.Readable, z.ZodTypeDef, stream.Readable>>;
2280
- }, z.ZodTypeAny, "passthrough"> | null;
2281
- } | null;
2282
- } | null>;
2140
+ private addCompletion;
2141
+ private deleteCompletion;
2142
+ private updateCompletion;
2143
+ private clearCompletions;
2144
+ private getCompletion;
2145
+ private getCompletions;
2146
+ private addPersonalization;
2147
+ private deletePersonalization;
2148
+ private clearPersonalization;
2149
+ private getPersonalization;
2150
+ private addRAG;
2151
+ private deleteRAG;
2152
+ private updateRAG;
2153
+ private clearRAGs;
2154
+ private getRAG;
2155
+ private getRAGs;
2156
+ private getMessage;
2283
2157
  llms: llmsAdapter;
2284
2158
  chats: chatsAdapter;
2285
2159
  }
package/dist/index.d.ts CHANGED
@@ -2137,149 +2137,23 @@ declare class Worker {
2137
2137
  mute(mute: z.infer<typeof MuteWorkerBaseType>, options: z.infer<typeof MuteWorkerOptionsType>): Promise<void | undefined>;
2138
2138
  profile(roomId: z.infer<typeof ProfileWorkerBaseType>): Promise<z.infer<typeof ProfileWorkerBaseOutputType> | null>;
2139
2139
  presence(action: z.infer<typeof PresenceWorkerBaseType>, options: z.infer<typeof PresenceWorkerOptionsType>): Promise<void | undefined>;
2140
- addCompletion(props: z.infer<typeof llmMessagesTable>): Promise<{
2141
- channelId: string;
2142
- uniqueId: string;
2143
- role: string;
2144
- content: string;
2145
- model?: string | null | undefined;
2146
- additional?: string | null | undefined;
2147
- }>;
2148
- deleteCompletion(uniqueId: string): Promise<boolean>;
2149
- updateCompletion(uniqueId: string, props: Partial<z.infer<typeof llmMessagesTable>>): Promise<{
2150
- channelId: string;
2151
- uniqueId: string;
2152
- role: string;
2153
- content: string;
2154
- model?: string | null | undefined;
2155
- additional?: string | null | undefined;
2156
- }>;
2157
- clearCompletions(channelId: string): Promise<boolean>;
2158
- getCompletion(uniqueId: string): Promise<{
2159
- channelId: string;
2160
- uniqueId: string;
2161
- role: string;
2162
- content: string;
2163
- model?: string | null | undefined;
2164
- additional?: string | null | undefined;
2165
- } | null>;
2166
- getCompletions(channelId: string): Promise<{
2167
- channelId: string;
2168
- uniqueId: string;
2169
- role: string;
2170
- content: string;
2171
- model?: string | null | undefined;
2172
- additional?: string | null | undefined;
2173
- }[]>;
2174
- addPersonalization(props: z.infer<typeof llmPersonalizationTable>): Promise<{
2175
- uniqueId: string;
2176
- content: string;
2177
- senderId: string;
2178
- }>;
2179
- deletePersonalization(uniqueId: string): Promise<boolean>;
2180
- clearPersonalization(senderId: string): Promise<boolean>;
2181
- getPersonalization(senderId: string): Promise<{
2182
- uniqueId: string;
2183
- content: string;
2184
- senderId: string;
2185
- }[]>;
2186
- addRAG(props: z.infer<typeof addRAGType>): Promise<any>;
2187
- deleteRAG(id: string): Promise<boolean>;
2188
- updateRAG(id: string): Promise<{
2189
- metadata: {
2190
- id: string;
2191
- };
2192
- pageContent: string;
2193
- }>;
2194
- clearRAGs(): Promise<boolean>;
2195
- getRAG(id: string): Promise<{
2196
- metadata: {
2197
- id: string;
2198
- };
2199
- pageContent: string;
2200
- } | null>;
2201
- getRAGs(keyword: string): Promise<{
2202
- metadata: {
2203
- id: string;
2204
- };
2205
- pageContent: string;
2206
- }[]>;
2207
- getMessage(chatId: string): Promise<{
2208
- channelId: string;
2209
- uniqueId: string;
2210
- message: (...args: unknown[]) => Record<string, any>;
2211
- senderId: string;
2212
- roomId: string;
2213
- isGroup: boolean;
2214
- text: string | null;
2215
- chatId: string;
2216
- receiverId: string;
2217
- receiverName: string;
2218
- roomName: string;
2219
- senderName: string;
2220
- senderDevice: "unknown" | "android" | "ios" | "desktop" | "web";
2221
- chatType: "text" | "image" | "contact" | "location" | "document" | "audio" | "video" | "protocol" | "contactsArray" | "highlyStructured" | "sendPayment" | "liveLocation" | "requestPayment" | "declinePaymentRequest" | "cancelPaymentRequest" | "template" | "sticker" | "groupInvite" | "templateButtonReply" | "product" | "deviceSent" | "list" | "viewOnce" | "order" | "listResponse" | "ephemeral" | "invoice" | "buttons" | "buttonsResponse" | "paymentInvite" | "interactive" | "reaction" | "interactiveResponse" | "pollCreation" | "pollUpdate" | "keepInChat" | "requestPhoneNumber" | "scheduledCallCreation" | "groupMentioned" | "pinInChat" | "scheduledCallEdit" | "ptv" | "botInvoke" | "callLog" | "encComment" | "bcall" | "lottieSticker" | "event" | "comment" | "placeholder" | "encEventUpdate";
2222
- timestamp: number;
2223
- mentions: string[];
2224
- links: string[];
2225
- isPrefix: boolean;
2226
- isSpam: boolean;
2227
- isFromMe: boolean;
2228
- isTagMe: boolean;
2229
- isStory: boolean;
2230
- isViewOnce: boolean;
2231
- isEdited: boolean;
2232
- isDeleted: boolean;
2233
- isPinned: boolean;
2234
- isUnPinned: boolean;
2235
- isChannel: boolean;
2236
- isBroadcast: boolean;
2237
- isEphemeral: boolean;
2238
- isForwarded: boolean;
2239
- citation: Record<string, boolean> | null;
2240
- media: z.objectOutputType<{
2241
- buffer: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<Buffer<ArrayBufferLike>, z.ZodTypeDef, Buffer<ArrayBufferLike>>>;
2242
- stream: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<stream.Readable, z.ZodTypeDef, stream.Readable>>;
2243
- }, z.ZodTypeAny, "passthrough"> | null;
2244
- replied: {
2245
- channelId: string;
2246
- uniqueId: string;
2247
- message: (...args: unknown[]) => Record<string, any>;
2248
- senderId: string;
2249
- roomId: string;
2250
- isGroup: boolean;
2251
- text: string | null;
2252
- chatId: string;
2253
- receiverId: string;
2254
- receiverName: string;
2255
- roomName: string;
2256
- senderName: string;
2257
- senderDevice: "unknown" | "android" | "ios" | "desktop" | "web";
2258
- chatType: "text" | "image" | "contact" | "location" | "document" | "audio" | "video" | "protocol" | "contactsArray" | "highlyStructured" | "sendPayment" | "liveLocation" | "requestPayment" | "declinePaymentRequest" | "cancelPaymentRequest" | "template" | "sticker" | "groupInvite" | "templateButtonReply" | "product" | "deviceSent" | "list" | "viewOnce" | "order" | "listResponse" | "ephemeral" | "invoice" | "buttons" | "buttonsResponse" | "paymentInvite" | "interactive" | "reaction" | "interactiveResponse" | "pollCreation" | "pollUpdate" | "keepInChat" | "requestPhoneNumber" | "scheduledCallCreation" | "groupMentioned" | "pinInChat" | "scheduledCallEdit" | "ptv" | "botInvoke" | "callLog" | "encComment" | "bcall" | "lottieSticker" | "event" | "comment" | "placeholder" | "encEventUpdate";
2259
- timestamp: number;
2260
- mentions: string[];
2261
- links: string[];
2262
- isPrefix: boolean;
2263
- isSpam: boolean;
2264
- isFromMe: boolean;
2265
- isTagMe: boolean;
2266
- isStory: boolean;
2267
- isViewOnce: boolean;
2268
- isEdited: boolean;
2269
- isDeleted: boolean;
2270
- isPinned: boolean;
2271
- isUnPinned: boolean;
2272
- isChannel: boolean;
2273
- isBroadcast: boolean;
2274
- isEphemeral: boolean;
2275
- isForwarded: boolean;
2276
- citation: Record<string, boolean> | null;
2277
- media: z.objectOutputType<{
2278
- buffer: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<Buffer<ArrayBufferLike>, z.ZodTypeDef, Buffer<ArrayBufferLike>>>;
2279
- stream: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodType<stream.Readable, z.ZodTypeDef, stream.Readable>>;
2280
- }, z.ZodTypeAny, "passthrough"> | null;
2281
- } | null;
2282
- } | null>;
2140
+ private addCompletion;
2141
+ private deleteCompletion;
2142
+ private updateCompletion;
2143
+ private clearCompletions;
2144
+ private getCompletion;
2145
+ private getCompletions;
2146
+ private addPersonalization;
2147
+ private deletePersonalization;
2148
+ private clearPersonalization;
2149
+ private getPersonalization;
2150
+ private addRAG;
2151
+ private deleteRAG;
2152
+ private updateRAG;
2153
+ private clearRAGs;
2154
+ private getRAG;
2155
+ private getRAGs;
2156
+ private getMessage;
2283
2157
  llms: llmsAdapter;
2284
2158
  chats: chatsAdapter;
2285
2159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zaileys",
3
- "version": "1.1.31",
3
+ "version": "1.1.33",
4
4
  "description": "Zaileys - Simplified WhatsApp Node.js API",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1,25 +0,0 @@
1
- import { Client } from "../src";
2
- // import { Client } from "zaileys";
3
-
4
- const wa = new Client({
5
- authType: "qr", // has issue with pairing code, just use qr only,
6
- citation: {
7
- authors: () => [62858000000, 628580000],
8
- otherNumbers: () => [62830000000, 628300000],
9
- premiumUsers: async () => {
10
- const numbers = await fetch("https://api.npoint.io/cd9d2eeb80838a6c86bb").then((x) => x.json()).catch(() => []);
11
- return numbers;
12
- },
13
- },
14
- });
15
-
16
- wa.on("messages", (ctx) => {
17
- const { citation, roomId } = ctx;
18
-
19
- // from 'author' to 'isAuthors'
20
- console.log(citation?.isAuthors); // boolean
21
-
22
- if (citation?.isPremiumUsers) {
23
- wa.text("Hello premium users!", { roomId });
24
- }
25
- });
@@ -1,23 +0,0 @@
1
- import { Client } from "../src";
2
- // import { Client } from "zaileys";
3
-
4
- const wa = new Client({
5
- authType: "qr", // has issue with pairing code, just use qr only
6
-
7
- // max 10 messages on 10 seconds
8
- limiter: {
9
- durationMs: 10000,
10
- maxMessages: 5,
11
- },
12
- });
13
-
14
- wa.on("messages", (ctx) => {
15
- const { isSpam, roomId } = ctx;
16
-
17
- if (isSpam) {
18
- wa.text("You're spamming!!", { roomId });
19
- return;
20
- }
21
-
22
- wa.text("Hello!", { roomId });
23
- });
package/examples/llms.ts DELETED
@@ -1,37 +0,0 @@
1
- import Groq from "groq-sdk";
2
-
3
- import { Client } from "../src";
4
- // import { Client } from "zaileys";
5
-
6
- const groq = new Groq({ apiKey: "YOUR_GROQ_APIKEY" });
7
-
8
- const wa = new Client({
9
- authType: "qr", // has issue with pairing code, just use qr only
10
- loadLLMSchemas: true, // this option must be activated!
11
- });
12
-
13
- wa.on("messages", async (ctx) => {
14
- const { channelId, uniqueId, roomId, text } = ctx;
15
-
16
- if (text == "clear") {
17
- await wa.llms.clearCompletions(channelId);
18
- await wa.text("History clear!", { roomId });
19
- return;
20
- }
21
-
22
- const histories = await wa.llms.getCompletions(channelId);
23
- const model = await groq.chat.completions.create({
24
- messages: [
25
- { role: "system", content: "You are 'Zaileys AI' a helpful assistant speak indonesian." },
26
- ...(histories.map((x) => ({ role: x.role, content: x.content })) as never),
27
- { role: "user", content: text || "" },
28
- ],
29
- model: "llama-3.3-70b-versatile",
30
- });
31
-
32
- const output = model.choices[0]?.message?.content || "";
33
- const ai = await wa.text(output, { roomId });
34
-
35
- await wa.llms.addCompletion({ channelId, uniqueId, role: "user", content: text || "" });
36
- await wa.llms.addCompletion({ channelId, uniqueId: ai?.uniqueId || "", role: "assistant", content: output });
37
- });
@@ -1,16 +0,0 @@
1
- import { Client } from "../src";
2
- // import { Client } from "zaileys";
3
-
4
- const wa = new Client({
5
- authType: "qr", // has issue with pairing code, just use qr only
6
- });
7
-
8
- wa.on("messages", (ctx) => {
9
- wa.text("Hello!", { roomId: ctx.roomId });
10
- });
11
-
12
- wa.on("calls", (ctx) => {
13
- if (ctx.status == "terminate") {
14
- wa.text("Why call me!?", { roomId: ctx.roomId });
15
- }
16
- });
@@ -1,38 +0,0 @@
1
- import { createPartFromUri, createUserContent, GoogleGenAI } from "@google/genai";
2
-
3
- import { Client } from "../src";
4
- // import { Client } from "zaileys";
5
-
6
- const agent = new GoogleGenAI({ apiKey: "AIzaSyCE8ml8-tcfXVChsfYiqR-Z1W1ovHZSIh8" });
7
-
8
- const wa = new Client({
9
- authType: "qr", // has issue with pairing code, just use qr only
10
- });
11
-
12
- wa.on("messages", async (ctx) => {
13
- if (ctx.chatType != "audio") return;
14
-
15
- const buffer = await ctx.media?.buffer();
16
- const stream = new File([buffer || ""], "voice.ogg", { type: "audio/ogg" });
17
-
18
- const uploaded = await agent.files.upload({
19
- file: stream,
20
- config: { mimeType: "audio/ogg" },
21
- });
22
-
23
- const speech = await agent.models
24
- .generateContent({
25
- model: "gemini-2.0-flash-001",
26
- contents: createUserContent([{ text: "Please transcribe this audio:" }, createPartFromUri(uploaded.uri!, uploaded.mimeType!)]),
27
- })
28
- .then((x) => x.candidates?.[0].content?.parts?.[0].text || "");
29
-
30
- const answer = await agent.models
31
- .generateContent({
32
- model: "gemini-2.0-flash-001",
33
- contents: speech,
34
- })
35
- .then((x) => x.candidates?.[0].content?.parts?.[0].text || "");
36
-
37
- await wa.text(answer, { roomId: ctx.roomId });
38
- });
@@ -1,37 +0,0 @@
1
- import { Client } from "../src";
2
- // import { Client } from "zaileys";
3
-
4
- const wa = new Client({
5
- authType: "qr", // has issue with pairing code, just use qr only
6
- webhooks: {
7
- url: "https://...", // An event triggers a call to the webhook url
8
- },
9
- });
10
-
11
- /*
12
- ✔ Webhooks Access
13
- - URL : http://xxx.xxx.x.xxx:4135/webhooks
14
- - PORT : 4135
15
- - METHOD: GET, POST
16
-
17
- hit to "URL" with data to be captured by "webhooks" event
18
- example:
19
-
20
- await fetch("http://xxx.xxx.x.xxx:4135/webhooks?test1=hello&test2=world", {
21
- method: "POST", // optional (GET & POST only)
22
- body: JSON.stringify({ testingBody: "OK", yourData: "test1" })
23
- })
24
- */
25
-
26
- wa.on("webhooks", (ctx) => {
27
- // passing search params
28
- console.log(ctx.data.query); // { test1: "hello", test2: "world" }
29
-
30
- // passing body
31
- console.log(ctx.data.json); // { testingBody: "OK", yourData: "test1" }
32
-
33
- // lets explore
34
- console.log(ctx)
35
- console.log(ctx.data.form)
36
- console.log(ctx.data.raw)
37
- });