webmaxsocket 1.0.0

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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Константы для библиотеки WebMax
3
+ */
4
+
5
+ const ChatActions = {
6
+ TYPING: 'typing',
7
+ STICKER: 'sticker',
8
+ FILE: 'file',
9
+ RECORDING_VOICE: 'recording_voice',
10
+ RECORDING_VIDEO: 'recording_video'
11
+ };
12
+
13
+ const EventTypes = {
14
+ START: 'start',
15
+ MESSAGE: 'message',
16
+ MESSAGE_REMOVED: 'message_removed',
17
+ CHAT_ACTION: 'chat_action',
18
+ ERROR: 'error',
19
+ DISCONNECT: 'disconnect'
20
+ };
21
+
22
+ const MessageTypes = {
23
+ TEXT: 'text',
24
+ IMAGE: 'image',
25
+ VIDEO: 'video',
26
+ AUDIO: 'audio',
27
+ DOCUMENT: 'document',
28
+ STICKER: 'sticker'
29
+ };
30
+
31
+ module.exports = {
32
+ ChatActions,
33
+ EventTypes,
34
+ MessageTypes
35
+ };
36
+
@@ -0,0 +1,39 @@
1
+ const User = require('./User');
2
+
3
+ /**
4
+ * Класс представляющий действие в чате
5
+ */
6
+ class ChatAction {
7
+ constructor(data, client) {
8
+ this.client = client;
9
+ this.type = data.type || data.action || null;
10
+ this.chatId = data.chatId || data.chat_id || null;
11
+ this.userId = data.userId || data.user_id || null;
12
+ this.user = data.user ? new User(data.user) : null;
13
+ this.timestamp = data.timestamp || Date.now();
14
+ this.rawData = data;
15
+ }
16
+
17
+ /**
18
+ * Возвращает строковое представление действия
19
+ */
20
+ toString() {
21
+ return `ChatAction(type=${this.type}, user=${this.userId}, chat=${this.chatId})`;
22
+ }
23
+
24
+ /**
25
+ * Возвращает JSON представление
26
+ */
27
+ toJSON() {
28
+ return {
29
+ type: this.type,
30
+ chatId: this.chatId,
31
+ userId: this.userId,
32
+ user: this.user ? this.user.toJSON() : null,
33
+ timestamp: this.timestamp
34
+ };
35
+ }
36
+ }
37
+
38
+ module.exports = ChatAction;
39
+
@@ -0,0 +1,152 @@
1
+ const User = require('./User');
2
+
3
+ /**
4
+ * Класс представляющий сообщение
5
+ */
6
+ class Message {
7
+ constructor(data, client) {
8
+ this.client = client;
9
+ this.id = data.id || data.messageId || null;
10
+ this.cid = data.cid || null;
11
+ this.chatId = data.chatId || data.chat_id || null;
12
+
13
+ // Обработка text: может быть строкой или объектом
14
+ if (typeof data.text === 'string') {
15
+ this.text = data.text;
16
+ } else if (typeof data.text === 'object' && data.text !== null) {
17
+ // Если text - объект, ищем текст внутри
18
+ this.text = data.text.text || JSON.stringify(data.text);
19
+ } else {
20
+ this.text = data.message || '';
21
+ }
22
+
23
+ // Обработка sender: может быть объектом User или просто ID
24
+ if (data.sender) {
25
+ if (typeof data.sender === 'object') {
26
+ this.senderId = data.sender.id;
27
+ this.sender = new User(data.sender);
28
+ } else {
29
+ // Если sender - это просто ID (число)
30
+ this.senderId = data.sender;
31
+ this.sender = null; // Будет загружен позже при необходимости
32
+ }
33
+ } else {
34
+ this.senderId = data.senderId || data.sender_id || data.from_id || null;
35
+ this.sender = null;
36
+ }
37
+
38
+ this.timestamp = data.timestamp || data.time || Date.now();
39
+ this.type = data.type || 'text';
40
+ this.isEdited = data.isEdited || data.is_edited || false;
41
+ this.replyTo = data.replyTo || data.reply_to || null;
42
+ this.attachments = data.attaches || data.attachments || [];
43
+ this.rawData = data;
44
+ }
45
+
46
+ /**
47
+ * Получить информацию об отправителе
48
+ */
49
+ async fetchSender() {
50
+ if (!this.sender && this.senderId) {
51
+ try {
52
+ this.sender = await this.client.getUser(this.senderId);
53
+ } catch (error) {
54
+ console.error('Ошибка загрузки информации об отправителе:', error);
55
+ }
56
+ }
57
+ return this.sender;
58
+ }
59
+
60
+ /**
61
+ * Получить имя отправителя
62
+ */
63
+ getSenderName() {
64
+ if (this.sender) {
65
+ return this.sender.fullname || this.sender.firstname || 'User';
66
+ }
67
+ return this.senderId ? `User ${this.senderId}` : 'Unknown';
68
+ }
69
+
70
+ /**
71
+ * Ответить на сообщение
72
+ */
73
+ async reply(options) {
74
+ if (typeof options === 'string') {
75
+ options = { text: options };
76
+ }
77
+
78
+ return await this.client.sendMessage({
79
+ chatId: this.chatId,
80
+ text: options.text,
81
+ cid: options.cid || Date.now(),
82
+ replyTo: this.id,
83
+ ...options
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Редактировать сообщение
89
+ */
90
+ async edit(options) {
91
+ if (typeof options === 'string') {
92
+ options = { text: options };
93
+ }
94
+
95
+ return await this.client.editMessage({
96
+ messageId: this.id,
97
+ chatId: this.chatId,
98
+ text: options.text,
99
+ ...options
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Удалить сообщение
105
+ */
106
+ async delete() {
107
+ return await this.client.deleteMessage({
108
+ messageId: this.id,
109
+ chatId: this.chatId
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Переслать сообщение
115
+ */
116
+ async forward(chatId) {
117
+ return await this.client.forwardMessage({
118
+ messageId: this.id,
119
+ fromChatId: this.chatId,
120
+ toChatId: chatId
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Возвращает строковое представление сообщения
126
+ */
127
+ toString() {
128
+ return `Message(id=${this.id}, from=${this.senderId}, text="${this.text.substring(0, 50)}")`;
129
+ }
130
+
131
+ /**
132
+ * Возвращает JSON представление
133
+ */
134
+ toJSON() {
135
+ return {
136
+ id: this.id,
137
+ cid: this.cid,
138
+ chatId: this.chatId,
139
+ text: this.text,
140
+ senderId: this.senderId,
141
+ sender: this.sender ? this.sender.toJSON() : null,
142
+ timestamp: this.timestamp,
143
+ type: this.type,
144
+ isEdited: this.isEdited,
145
+ replyTo: this.replyTo,
146
+ attachments: this.attachments
147
+ };
148
+ }
149
+ }
150
+
151
+ module.exports = Message;
152
+
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Класс представляющий пользователя
3
+ */
4
+ class User {
5
+ constructor(data) {
6
+ this.id = data.id || data.userId || data.contactId || null;
7
+ this.firstname = data.firstname || data.firstName || data.first_name || '';
8
+ this.lastname = data.lastname || data.lastName || data.last_name || '';
9
+ this.username = data.username || data.nick || null;
10
+ this.phone = data.phone || null;
11
+ this.avatar = data.avatar || data.baseUrl || data.baseRawUrl || null;
12
+ this.photoId = data.photoId || null;
13
+ this.status = data.status || 'online';
14
+ this.bio = data.bio || data.description || '';
15
+ this.rawData = data;
16
+ }
17
+
18
+ /**
19
+ * Возвращает полное имя пользователя
20
+ */
21
+ get fullname() {
22
+ return `${this.firstname} ${this.lastname}`.trim();
23
+ }
24
+
25
+ /**
26
+ * Возвращает строковое представление пользователя
27
+ */
28
+ toString() {
29
+ return `User(id=${this.id}, name=${this.fullname})`;
30
+ }
31
+
32
+ /**
33
+ * Возвращает JSON представление
34
+ */
35
+ toJSON() {
36
+ return {
37
+ id: this.id,
38
+ firstname: this.firstname,
39
+ lastname: this.lastname,
40
+ username: this.username,
41
+ phone: this.phone,
42
+ avatar: this.avatar,
43
+ photoId: this.photoId,
44
+ status: this.status,
45
+ bio: this.bio
46
+ };
47
+ }
48
+ }
49
+
50
+ module.exports = User;
51
+
@@ -0,0 +1,10 @@
1
+ const User = require('./User');
2
+ const Message = require('./Message');
3
+ const ChatAction = require('./ChatAction');
4
+
5
+ module.exports = {
6
+ User,
7
+ Message,
8
+ ChatAction
9
+ };
10
+
package/lib/opcodes.js ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Opcodes для протокола Max API
3
+ * Портировано из PyMax
4
+ */
5
+
6
+ const Opcode = {
7
+ PING: 1,
8
+ DEBUG: 2,
9
+ RECONNECT: 3,
10
+ LOG: 5,
11
+ SESSION_INIT: 6,
12
+ PROFILE: 16,
13
+ LOGIN: 19,
14
+ LOGOUT: 20,
15
+ SYNC: 21,
16
+ CONFIG: 22,
17
+ CONTACT_INFO: 32,
18
+ CONTACT_UPDATE: 34,
19
+ CONTACT_INFO_BY_PHONE: 46,
20
+ CHAT_INFO: 48,
21
+ CHAT_HISTORY: 49,
22
+ CHAT_MARK: 50,
23
+ CHATS_LIST: 53,
24
+ CHAT_UPDATE: 55,
25
+ CHAT_JOIN: 57,
26
+ CHAT_LEAVE: 58,
27
+ CHAT_MEMBERS: 59,
28
+ MSG_SEND: 64,
29
+ MSG_DELETE: 66,
30
+ MSG_EDIT: 67,
31
+ CHAT_MEMBERS_UPDATE: 77,
32
+ PHOTO_UPLOAD: 80,
33
+ VIDEO_UPLOAD: 82,
34
+ VIDEO_PLAY: 83,
35
+ FILE_UPLOAD: 87,
36
+ FILE_DOWNLOAD: 88,
37
+ LINK_INFO: 89,
38
+ SESSIONS_INFO: 96,
39
+ SESSIONS_CLOSE: 97,
40
+ NOTIF_MESSAGE: 128,
41
+ NOTIF_CHAT: 135,
42
+ NOTIF_ATTACH: 136,
43
+ NOTIF_MSG_REACTIONS_CHANGED: 155,
44
+ MSG_REACTION: 178,
45
+ MSG_CANCEL_REACTION: 179,
46
+ MSG_GET_REACTIONS: 180,
47
+ FOLDERS_GET: 272,
48
+ FOLDERS_UPDATE: 274,
49
+ FOLDERS_DELETE: 276,
50
+ GET_QR: 288,
51
+ GET_QR_STATUS: 289,
52
+ LOGIN_BY_QR: 291,
53
+ };
54
+
55
+ // Обратная карта для расшифровки опкодов
56
+ const OpcodeNames = {};
57
+ for (const [name, code] of Object.entries(Opcode)) {
58
+ OpcodeNames[code] = name;
59
+ }
60
+
61
+ /**
62
+ * Получить название опкода
63
+ */
64
+ function getOpcodeName(code) {
65
+ return OpcodeNames[code] || `UNKNOWN_${code}`;
66
+ }
67
+
68
+ const DeviceType = {
69
+ WEB: 'WEB',
70
+ };
71
+
72
+ module.exports = {
73
+ Opcode,
74
+ DeviceType,
75
+ getOpcodeName,
76
+ };
77
+
package/lib/session.js ADDED
@@ -0,0 +1,123 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Менеджер сессий для хранения данных авторизации
6
+ */
7
+ class SessionManager {
8
+ constructor(sessionName = 'default') {
9
+ this.sessionName = sessionName;
10
+ this.sessionDir = path.join(process.cwd(), 'sessions');
11
+ this.sessionFile = path.join(this.sessionDir, `${sessionName}.json`);
12
+ this.data = {};
13
+
14
+ this.ensureSessionDir();
15
+ this.load();
16
+ }
17
+
18
+ /**
19
+ * Создает директорию для сессий если её нет
20
+ */
21
+ ensureSessionDir() {
22
+ if (!fs.existsSync(this.sessionDir)) {
23
+ fs.mkdirSync(this.sessionDir, { recursive: true });
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Загружает данные сессии из файла
29
+ */
30
+ load() {
31
+ try {
32
+ if (fs.existsSync(this.sessionFile)) {
33
+ const data = fs.readFileSync(this.sessionFile, 'utf8');
34
+ this.data = JSON.parse(data);
35
+ return true;
36
+ }
37
+ } catch (error) {
38
+ console.error('Ошибка при загрузке сессии:', error.message);
39
+ }
40
+ return false;
41
+ }
42
+
43
+ /**
44
+ * Сохраняет данные сессии в файл
45
+ */
46
+ save() {
47
+ try {
48
+ fs.writeFileSync(
49
+ this.sessionFile,
50
+ JSON.stringify(this.data, null, 2),
51
+ 'utf8'
52
+ );
53
+ return true;
54
+ } catch (error) {
55
+ console.error('Ошибка при сохранении сессии:', error.message);
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Устанавливает значение в сессии
62
+ */
63
+ set(key, value) {
64
+ this.data[key] = value;
65
+ this.save();
66
+ }
67
+
68
+ /**
69
+ * Получает значение из сессии
70
+ */
71
+ get(key, defaultValue = null) {
72
+ return this.data[key] !== undefined ? this.data[key] : defaultValue;
73
+ }
74
+
75
+ /**
76
+ * Удаляет значение из сессии
77
+ */
78
+ delete(key) {
79
+ delete this.data[key];
80
+ this.save();
81
+ }
82
+
83
+ /**
84
+ * Проверяет наличие ключа в сессии
85
+ */
86
+ has(key) {
87
+ return this.data[key] !== undefined;
88
+ }
89
+
90
+ /**
91
+ * Очищает все данные сессии
92
+ */
93
+ clear() {
94
+ this.data = {};
95
+ this.save();
96
+ }
97
+
98
+ /**
99
+ * Удаляет файл сессии
100
+ */
101
+ destroy() {
102
+ try {
103
+ if (fs.existsSync(this.sessionFile)) {
104
+ fs.unlinkSync(this.sessionFile);
105
+ }
106
+ this.data = {};
107
+ return true;
108
+ } catch (error) {
109
+ console.error('Ошибка при удалении сессии:', error.message);
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Проверяет, авторизован ли пользователь
116
+ */
117
+ isAuthorized() {
118
+ return this.has('token') && this.has('userId');
119
+ }
120
+ }
121
+
122
+ module.exports = SessionManager;
123
+
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Генерация UserAgent для Max API
3
+ */
4
+
5
+ const DEVICE_NAMES = [
6
+ 'Chrome', 'Firefox', 'Edge', 'Safari', 'Opera', 'Vivaldi', 'Brave', 'Chromium',
7
+ 'Windows 10', 'Windows 11', 'macOS Big Sur', 'macOS Monterey', 'macOS Ventura',
8
+ 'Ubuntu 20.04', 'Ubuntu 22.04', 'Fedora 35', 'Fedora 36', 'Debian 11',
9
+ ];
10
+
11
+ const SCREEN_SIZES = [
12
+ '1920x1080 1.0x', '1366x768 1.0x', '1440x900 1.0x', '1536x864 1.0x',
13
+ '1280x720 1.0x', '1600x900 1.0x', '1680x1050 1.0x', '2560x1440 1.0x', '3840x2160 1.0x',
14
+ ];
15
+
16
+ const OS_VERSIONS = [
17
+ 'Windows 10', 'Windows 11', 'macOS Big Sur', 'macOS Monterey', 'macOS Ventura',
18
+ 'Ubuntu 20.04', 'Ubuntu 22.04', 'Fedora 35', 'Fedora 36', 'Debian 11',
19
+ ];
20
+
21
+ const TIMEZONES = [
22
+ 'Europe/Moscow', 'Europe/Kaliningrad', 'Europe/Samara', 'Asia/Yekaterinburg',
23
+ 'Asia/Omsk', 'Asia/Krasnoyarsk', 'Asia/Irkutsk', 'Asia/Yakutsk',
24
+ 'Asia/Vladivostok', 'Asia/Kamchatka',
25
+ ];
26
+
27
+ const USER_AGENTS = [
28
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
29
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
30
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
31
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
32
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.2; rv:121.0) Gecko/20100101 Firefox/121.0',
33
+ ];
34
+
35
+ function randomChoice(array) {
36
+ return array[Math.floor(Math.random() * array.length)];
37
+ }
38
+
39
+ function randomInt(min, max) {
40
+ return Math.floor(Math.random() * (max - min + 1)) + min;
41
+ }
42
+
43
+ /**
44
+ * Создает UserAgent пейлоад для Max API
45
+ */
46
+ class UserAgentPayload {
47
+ constructor(options = {}) {
48
+ this.deviceType = 'WEB'; // Всегда WEB (только QR авторизация)
49
+ this.locale = options.locale || 'ru';
50
+ this.deviceLocale = options.deviceLocale || 'ru';
51
+ this.osVersion = options.osVersion || randomChoice(OS_VERSIONS);
52
+ this.deviceName = options.deviceName || randomChoice(DEVICE_NAMES);
53
+ this.headerUserAgent = options.headerUserAgent || randomChoice(USER_AGENTS);
54
+ this.appVersion = options.appVersion || '25.12.14';
55
+ this.screen = options.screen || randomChoice(SCREEN_SIZES);
56
+ this.timezone = options.timezone || randomChoice(TIMEZONES);
57
+ this.clientSessionId = options.clientSessionId || randomInt(1, 15);
58
+ this.buildNumber = options.buildNumber || 0x97CB; // 38859
59
+ }
60
+
61
+ /**
62
+ * Преобразует в объект для отправки (camelCase ключи)
63
+ */
64
+ toJSON() {
65
+ return {
66
+ deviceType: this.deviceType,
67
+ locale: this.locale,
68
+ deviceLocale: this.deviceLocale,
69
+ osVersion: this.osVersion,
70
+ deviceName: this.deviceName,
71
+ headerUserAgent: this.headerUserAgent,
72
+ appVersion: this.appVersion,
73
+ screen: this.screen,
74
+ timezone: this.timezone,
75
+ clientSessionId: this.clientSessionId,
76
+ buildNumber: this.buildNumber,
77
+ };
78
+ }
79
+ }
80
+
81
+ module.exports = { UserAgentPayload };
82
+
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "webmaxsocket",
3
+ "version": "1.0.0",
4
+ "description": "Node.js client for Max Messenger with QR code authentication",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node example.js",
8
+ "example": "node example.js"
9
+ },
10
+ "keywords": [
11
+ "max",
12
+ "messenger",
13
+ "max-messenger",
14
+ "oneme",
15
+ "api",
16
+ "userbot",
17
+ "selfbot",
18
+ "websocket",
19
+ "qr-code",
20
+ "qr-auth",
21
+ "bot",
22
+ "nodejs",
23
+ "commonjs"
24
+ ],
25
+ "author": "Tellarion",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/Tellarion/webmaxsocket.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/Tellarion/webmaxsocket/issues"
33
+ },
34
+ "homepage": "https://github.com/Tellarion/webmaxsocket#readme",
35
+ "dependencies": {
36
+ "qrcode-terminal": "^0.12.0",
37
+ "uuid": "^9.0.0",
38
+ "ws": "^8.18.0"
39
+ },
40
+ "devDependencies": {},
41
+ "engines": {
42
+ "node": ">=14.0.0"
43
+ },
44
+ "files": [
45
+ "lib/",
46
+ "index.js",
47
+ "example.js",
48
+ "README.md"
49
+ ]
50
+ }
51
+