Comparing version 2.0.0-beta.6 to 2.0.0-beta.7
@@ -11,4 +11,4 @@ import EventEmitter from "events"; | ||
export declare enum CloseReason { | ||
DuplicateConnection = 0, | ||
ManualClosure = 1 | ||
ManualClosure = 1000, | ||
DuplicateConnection = 3000 | ||
} | ||
@@ -15,0 +15,0 @@ interface ListenerEvents { |
@@ -9,4 +9,4 @@ import EventEmitter from "events"; | ||
(function (CloseReason) { | ||
CloseReason[CloseReason["DuplicateConnection"] = 0] = "DuplicateConnection"; | ||
CloseReason[CloseReason["ManualClosure"] = 1] = "ManualClosure"; | ||
CloseReason[CloseReason["ManualClosure"] = 1000] = "ManualClosure"; | ||
CloseReason[CloseReason["DuplicateConnection"] = 3000] = "DuplicateConnection"; | ||
})(CloseReason || (CloseReason = {})); | ||
@@ -13,0 +13,0 @@ export class Listener extends EventEmitter { |
@@ -1,7 +0,65 @@ | ||
import { SerializedCookieJar } from "tough-cookie"; | ||
import { type SerializedCookie, type SerializedCookieJar } from "tough-cookie"; | ||
import type { ContextBase } from "../context.js"; | ||
export declare enum LoginQRCallbackEventType { | ||
QRCodeGenerated = 0, | ||
QRCodeExpired = 1, | ||
QRCodeScanned = 2, | ||
QRCodeDeclined = 3, | ||
GotLoginInfo = 4 | ||
} | ||
export type LoginQRCallbackEvent = { | ||
type: LoginQRCallbackEventType.QRCodeGenerated; | ||
data: { | ||
code: string; | ||
image: string; | ||
options: { | ||
enabledCheckOCR: boolean; | ||
enabledMultiLayer: boolean; | ||
}; | ||
}; | ||
actions: { | ||
saveToFile: (qrPath?: string) => Promise<any>; | ||
retry: () => any; | ||
abort: () => any; | ||
}; | ||
} | { | ||
type: LoginQRCallbackEventType.QRCodeExpired; | ||
data: null; | ||
actions: { | ||
retry: () => any; | ||
abort: () => any; | ||
}; | ||
} | { | ||
type: LoginQRCallbackEventType.QRCodeScanned; | ||
data: { | ||
avatar: string; | ||
display_name: string; | ||
}; | ||
actions: { | ||
retry: () => any; | ||
abort: () => any; | ||
}; | ||
} | { | ||
type: LoginQRCallbackEventType.QRCodeDeclined; | ||
data: { | ||
code: string; | ||
}; | ||
actions: { | ||
retry: () => any; | ||
abort: () => any; | ||
}; | ||
} | { | ||
type: LoginQRCallbackEventType.GotLoginInfo; | ||
data: { | ||
cookie: SerializedCookie[]; | ||
imei: string; | ||
userAgent: string; | ||
}; | ||
actions: null; | ||
}; | ||
export type LoginQRCallback = (event: LoginQRCallbackEvent) => any; | ||
export declare function loginQR(ctx: ContextBase, options: { | ||
userAgent: string; | ||
qrPath?: string; | ||
}, callback?: (qrPath: string) => any): Promise<{ | ||
}, callback?: LoginQRCallback): Promise<{ | ||
userInfo: { | ||
@@ -8,0 +66,0 @@ name: string; |
@@ -5,2 +5,10 @@ import { CookieJar } from "tough-cookie"; | ||
import { logger, request } from "../utils.js"; | ||
export var LoginQRCallbackEventType; | ||
(function (LoginQRCallbackEventType) { | ||
LoginQRCallbackEventType[LoginQRCallbackEventType["QRCodeGenerated"] = 0] = "QRCodeGenerated"; | ||
LoginQRCallbackEventType[LoginQRCallbackEventType["QRCodeExpired"] = 1] = "QRCodeExpired"; | ||
LoginQRCallbackEventType[LoginQRCallbackEventType["QRCodeScanned"] = 2] = "QRCodeScanned"; | ||
LoginQRCallbackEventType[LoginQRCallbackEventType["QRCodeDeclined"] = 3] = "QRCodeDeclined"; | ||
LoginQRCallbackEventType[LoginQRCallbackEventType["GotLoginInfo"] = 4] = "GotLoginInfo"; | ||
})(LoginQRCallbackEventType || (LoginQRCallbackEventType = {})); | ||
async function loadLoginPage(ctx) { | ||
@@ -153,3 +161,3 @@ const response = await request(ctx, "https://id.zalo.me/account?continue=https%3A%2F%2Fchat.zalo.me%2F", { | ||
form.append("v", version); | ||
logger(ctx).info("Vui lòng xác nhận trên điện thoại của bạn"); | ||
logger(ctx).info("Please confirm on your phone"); | ||
return await request(ctx, "https://id.zalo.me/account/authen/qr/waiting-confirm", { | ||
@@ -231,26 +239,76 @@ headers: { | ||
var _a; | ||
console.log(); | ||
function retry() { | ||
return resolve(loginQR(ctx, options, callback)); | ||
} | ||
if (ctx.options.logging) | ||
console.log(); | ||
const loginVersion = await loadLoginPage(ctx); | ||
if (!loginVersion) | ||
return reject(new ZaloApiError("Không thể lấy phiên bản API đăng nhập")); | ||
logger(ctx).info("Phiên bản API đăng nhập:", loginVersion); | ||
return reject(new ZaloApiError("Cannot get API login version")); | ||
logger(ctx).info("Got login version:", loginVersion); | ||
await getLoginInfo(ctx, loginVersion); | ||
await verifyClient(ctx, loginVersion); | ||
const qrData = await generate(ctx, loginVersion); | ||
if (!qrData) | ||
throw new ZaloApiError("Không thể khởi tạo QRCode"); | ||
const qrGenResult = await generate(ctx, loginVersion); | ||
if (!qrGenResult || !qrGenResult.data) | ||
return reject(new ZaloApiError(`Unable to generate QRCode\nResponse: ${JSON.stringify(qrGenResult, null, 2)}`)); | ||
const qrData = qrGenResult.data; | ||
if (callback) { | ||
callback({ | ||
type: LoginQRCallbackEventType.QRCodeGenerated, | ||
data: Object.assign(Object.assign({}, qrGenResult.data), { image: qrGenResult.data.image.replace(/^data:image\/png;base64,/, "") }), | ||
actions: { | ||
async saveToFile(qrPath) { | ||
var _a; | ||
if (qrPath === void 0) { qrPath = (_a = options.qrPath) !== null && _a !== void 0 ? _a : "qr.png"; } | ||
await saveQRCodeToFile(qrPath, qrData.image.replace(/^data:image\/png;base64,/, "")); | ||
logger(ctx).info("Scan the QR code at", `'${qrPath}'`, "to proceed with login"); | ||
}, | ||
retry, | ||
abort() { | ||
controller.abort(); | ||
}, | ||
}, | ||
}); | ||
} | ||
else { | ||
const qrPath = (_a = options.qrPath) !== null && _a !== void 0 ? _a : "qr.png"; | ||
await saveQRCodeToFile(qrPath, qrData.image.replace(/^data:image\/png;base64,/, "")); | ||
logger(ctx).info("Scan the QR code at", `'${qrPath}'`, "to proceed with login"); | ||
} | ||
const controller = new AbortController(); | ||
const timeout = setTimeout(() => { | ||
controller.abort(); | ||
logger(ctx).info("QR hết hạn, tiến hành lấy mới"); | ||
resolve(loginQR(ctx, options)); | ||
logger(ctx).info("QR expired!"); | ||
if (callback) { | ||
callback({ | ||
type: LoginQRCallbackEventType.QRCodeExpired, | ||
data: null, | ||
actions: { | ||
retry, | ||
abort() { | ||
resolve(null); | ||
}, | ||
}, | ||
}); | ||
} | ||
else { | ||
resolve(loginQR(ctx, options)); | ||
} | ||
}, 100000); | ||
const qrPath = (_a = options.qrPath) !== null && _a !== void 0 ? _a : "qr.png"; | ||
await saveQRCodeToFile(qrPath, qrData.data.image.replace(/^data:image\/png;base64,/, "")); | ||
callback === null || callback === void 0 ? void 0 : callback(qrPath); | ||
logger(ctx).info("Quét mã QR tại đường dẫn", `'${qrPath}'`, "để tiến hành đăng nhập"); | ||
const scanResult = await waitingScan(ctx, loginVersion, qrData.data.code, controller.signal); | ||
const scanResult = await waitingScan(ctx, loginVersion, qrGenResult.data.code, controller.signal); | ||
if (!scanResult || !scanResult.data) | ||
return resolve(null); | ||
const confirmResult = await waitingConfirm(ctx, loginVersion, qrData.data.code, controller.signal); | ||
if (callback) { | ||
callback({ | ||
type: LoginQRCallbackEventType.QRCodeScanned, | ||
data: scanResult.data, | ||
actions: { | ||
retry, | ||
abort() { | ||
controller.abort(); | ||
}, | ||
}, | ||
}); | ||
} | ||
const confirmResult = await waitingConfirm(ctx, loginVersion, qrGenResult.data.code, controller.signal); | ||
if (!confirmResult) | ||
@@ -262,15 +320,33 @@ return resolve(null); | ||
if (confirmResult.error_code == 0) { | ||
logger(ctx).info("Login thành công vào tài khoản", scanResult.data.display_name); | ||
logger(ctx).info("Successfully logged into the account", scanResult.data.display_name); | ||
} | ||
else if (confirmResult.error_code == -13) { | ||
logger(ctx).info("Bạn đã từ chối đăng nhập bằng mã QR"); | ||
if (callback) { | ||
callback({ | ||
type: LoginQRCallbackEventType.QRCodeDeclined, | ||
data: { | ||
code: qrData.code, | ||
}, | ||
actions: { | ||
retry, | ||
abort() { | ||
resolve(null); | ||
}, | ||
}, | ||
}); | ||
} | ||
else { | ||
logger(ctx).error("QRCode login declined"); | ||
resolve(null); | ||
} | ||
return; | ||
} | ||
else { | ||
logger(ctx).info("Đã có lỗi xảy ra.", confirmResult); | ||
return reject(new ZaloApiError(`An error has occurred.\nResponse: ${JSON.stringify(confirmResult, null, 2)}`)); | ||
} | ||
const userInfo = await getUserInfo(ctx); | ||
if (!userInfo || !userInfo.data) | ||
throw new ZaloApiError("Không thể lấy thông tin tài khoản"); | ||
return reject(new ZaloApiError("Can't get account info")); | ||
if (!userInfo.data.logged) | ||
throw new ZaloApiError("Không thể đăng nhập"); | ||
return reject(new ZaloApiError("Can't login")); | ||
clearTimeout(timeout); | ||
@@ -277,0 +353,0 @@ resolve({ |
@@ -9,2 +9,35 @@ import { GroupMessage, UserMessage, ThreadType } from "../models/index.js"; | ||
}; | ||
export declare enum TextStyle { | ||
Bold = "b", | ||
Italic = "i", | ||
Underline = "u", | ||
StrikeThrough = "s", | ||
Red = "c_db342e", | ||
Orange = "c_f27806", | ||
Yellow = "c_f7b503", | ||
Green = "c_15a85f", | ||
Small = "f_13", | ||
Big = "f_18", | ||
UnorderedList = "lst_1", | ||
OrderedList = "lst_2", | ||
Indent = "ind_$" | ||
} | ||
export type Style = { | ||
start: number; | ||
len: number; | ||
st: Exclude<TextStyle, TextStyle.Indent>; | ||
} | { | ||
start: number; | ||
len: number; | ||
st: TextStyle.Indent; | ||
/** | ||
* Number of spaces used for indentation. | ||
*/ | ||
indentSize?: number; | ||
}; | ||
export declare enum Urgency { | ||
Default = 0, | ||
Important = 1, | ||
Urgent = 2 | ||
} | ||
export type Mention = { | ||
@@ -30,2 +63,10 @@ /** | ||
/** | ||
* Text styles | ||
*/ | ||
styles?: Style[]; | ||
/** | ||
* Urgency of the message | ||
*/ | ||
urgency?: Urgency; | ||
/** | ||
* Quoted message (optional) | ||
@@ -32,0 +73,0 @@ */ |
@@ -35,2 +35,24 @@ import FormData from "form-data"; | ||
} | ||
export var TextStyle; | ||
(function (TextStyle) { | ||
TextStyle["Bold"] = "b"; | ||
TextStyle["Italic"] = "i"; | ||
TextStyle["Underline"] = "u"; | ||
TextStyle["StrikeThrough"] = "s"; | ||
TextStyle["Red"] = "c_db342e"; | ||
TextStyle["Orange"] = "c_f27806"; | ||
TextStyle["Yellow"] = "c_f7b503"; | ||
TextStyle["Green"] = "c_15a85f"; | ||
TextStyle["Small"] = "f_13"; | ||
TextStyle["Big"] = "f_18"; | ||
TextStyle["UnorderedList"] = "lst_1"; | ||
TextStyle["OrderedList"] = "lst_2"; | ||
TextStyle["Indent"] = "ind_$"; | ||
})(TextStyle || (TextStyle = {})); | ||
export var Urgency; | ||
(function (Urgency) { | ||
Urgency[Urgency["Default"] = 0] = "Default"; | ||
Urgency[Urgency["Important"] = 1] = "Important"; | ||
Urgency[Urgency["Urgent"] = 2] = "Urgent"; | ||
})(Urgency || (Urgency = {})); | ||
export const sendMessageFactory = apiFactory()((api, ctx, utils) => { | ||
@@ -123,3 +145,3 @@ const serviceURLs = { | ||
} | ||
async function handleMessage({ msg, mentions, quote }, threadId, type) { | ||
async function handleMessage({ msg, styles, urgency, mentions, quote }, threadId, type) { | ||
if (!msg || msg.length == 0) | ||
@@ -172,2 +194,20 @@ throw new ZaloApiError("Missing message content"); | ||
}; | ||
if (styles) { | ||
Object.assign(params, { | ||
textProperties: JSON.stringify({ | ||
styles: styles.map((e) => { | ||
var _a; | ||
const styleFinal = Object.assign(Object.assign({}, e), { indentSize: undefined, st: e.st == TextStyle.Indent | ||
? TextStyle.Indent.replace("$", `${(_a = e.indentSize) !== null && _a !== void 0 ? _a : 1}0`) | ||
: e.st }); | ||
removeUndefinedKeys(styleFinal); | ||
return styleFinal; | ||
}), | ||
ver: 0, | ||
}), | ||
}); | ||
} | ||
if (urgency == Urgency.Important || urgency == Urgency.Urgent) { | ||
Object.assign(params, { metaData: { urgency } }); | ||
} | ||
for (const key in params) { | ||
@@ -174,0 +214,0 @@ if (params[key] === undefined) |
@@ -34,3 +34,3 @@ export * from "./Errors/index.js"; | ||
export type { SendFriendRequestResponse } from "./apis/sendFriendRequest.js"; | ||
export type { Mention, MessageContent } from "./apis/sendMessage.js"; | ||
export type { Mention, MessageContent, SendMessageResponse, SendMessageResult, Style } from "./apis/sendMessage.js"; | ||
export type { SendReportResponse, SendReportOptions } from "./apis/sendReport.js"; | ||
@@ -43,3 +43,6 @@ export type { SendStickerResponse } from "./apis/sendSticker.js"; | ||
export type { FileData, ImageData, UploadAttachmentResponse, UploadAttachmentType } from "./apis/uploadAttachment.js"; | ||
export type { LoginQRCallback, LoginQRCallbackEvent } from "./apis/loginQR.js"; | ||
export { ReportReason } from "./apis/sendReport.js"; | ||
export { CloseReason } from "./apis/listen.js"; | ||
export { Urgency, TextStyle } from "./apis/sendMessage.js"; | ||
export { LoginQRCallbackEventType } from "./apis/loginQR.js"; |
@@ -7,1 +7,3 @@ export * from "./Errors/index.js"; | ||
export { CloseReason } from "./apis/listen.js"; | ||
export { Urgency, TextStyle } from "./apis/sendMessage.js"; | ||
export { LoginQRCallbackEventType } from "./apis/loginQR.js"; |
import { compare } from "semver"; | ||
import { isBun, logger } from "./utils.js"; | ||
const VERSION = "2.0.0-beta.6"; | ||
const VERSION = "2.0.0-beta.7"; | ||
const NPM_REGISTRY = "https://registry.npmjs.org/zca-js"; | ||
@@ -5,0 +5,0 @@ export async function checkUpdate(ctx) { |
@@ -33,2 +33,3 @@ import { Listener } from "./apis/listen.js"; | ||
import { lockPollFactory } from "./apis/lockPoll.js"; | ||
import { type LoginQRCallback } from "./apis/loginQR.js"; | ||
import { pinConversationsFactory } from "./apis/pinConversations.js"; | ||
@@ -81,3 +82,3 @@ import { removeGroupDeputyFactory } from "./apis/removeGroupDeputy.js"; | ||
qrPath?: string; | ||
}, callback?: (qrPath: string) => any): Promise<API>; | ||
}, callback?: LoginQRCallback): Promise<API>; | ||
} | ||
@@ -84,0 +85,0 @@ export declare class API { |
@@ -35,3 +35,3 @@ import { Listener } from "./apis/listen.js"; | ||
import { lockPollFactory } from "./apis/lockPoll.js"; | ||
import { loginQR } from "./apis/loginQR.js"; | ||
import { loginQR, LoginQRCallbackEventType } from "./apis/loginQR.js"; | ||
import { pinConversationsFactory } from "./apis/pinConversations.js"; | ||
@@ -118,6 +118,19 @@ import { removeGroupDeputyFactory } from "./apis/removeGroupDeputy.js"; | ||
if (!loginQRResult) | ||
throw new ZaloApiError("Đăng nhập với QR thất bại"); | ||
throw new ZaloApiError("Unable to login with QRCode"); | ||
const imei = generateZaloUUID(options.userAgent); | ||
if (callback) { | ||
// Thanks to @YanCastle for this great suggestion! | ||
callback({ | ||
type: LoginQRCallbackEventType.GotLoginInfo, | ||
data: { | ||
cookie: loginQRResult.cookies, | ||
imei, | ||
userAgent: options.userAgent, | ||
}, | ||
actions: null, | ||
}); | ||
} | ||
return this.loginCookie(ctx, { | ||
cookie: loginQRResult.cookies, | ||
imei: generateZaloUUID(options.userAgent), | ||
imei, | ||
userAgent: options.userAgent, | ||
@@ -124,0 +137,0 @@ language: options.language, |
{ | ||
"name": "zca-js", | ||
"version": "2.0.0-beta.6", | ||
"version": "2.0.0-beta.7", | ||
"description": "Unofficial Zalo API for JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
9534
372584
182