rubika 1.2.0 → 1.2.3

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.
@@ -48,7 +48,7 @@ async function sendMessage(
48
48
  }
49
49
  file_inline = await fs.promises.readFile(fileName);
50
50
  } else if (!Buffer.isBuffer(file_inline)) {
51
- throw this.logger.error(
51
+ return this.logger.error(
52
52
  "File argument must be a file path or bytes",
53
53
  "warn",
54
54
  );
@@ -70,7 +70,7 @@ async function sendMessage(
70
70
  thumb = false;
71
71
  if (audio_info) {
72
72
  if (!optionalMusicMetadata) {
73
- throw new Error(
73
+ return new Error(
74
74
  "music-metadata module is not installed. Some features may be disabled.",
75
75
  );
76
76
  }
@@ -16,7 +16,7 @@ async function start(this: Client): Promise<void> {
16
16
  }
17
17
 
18
18
  try {
19
- if (!this.auth) throw Error("[start] Error auth is not set");
19
+ if (!this.auth) return Error("[start] Error auth is not set");
20
20
  this.key = Buffer.from(Crypto.passphrase(this.auth), "utf8");
21
21
  this.decode_auth = Crypto.decode_auth(this.auth);
22
22
  const result = await this.getUserInfo();
@@ -8,7 +8,7 @@ const ffmpeg = optionalImport<typeof import("fluent-ffmpeg")>("fluent-ffmpeg");
8
8
  class ThumbnailGenerator {
9
9
  static async getTime(videoPath: string): Promise<number> {
10
10
  if (!ffmpeg) {
11
- throw new Error(
11
+ return new Error(
12
12
  "fluent-ffmpeg module is not installed. Some features may be disabled.",
13
13
  );
14
14
  }
@@ -28,7 +28,7 @@ class ThumbnailGenerator {
28
28
 
29
29
  static async fromVideo(videoPath: string): Promise<string> {
30
30
  if (!ffmpeg) {
31
- throw new Error(
31
+ return new Error(
32
32
  "fluent-ffmpeg module is not installed. Some features may be disabled.",
33
33
  );
34
34
  }
@@ -57,7 +57,7 @@ class ThumbnailGenerator {
57
57
  return base64Thumbnail;
58
58
  } catch (error) {
59
59
  console.error("Error generating video thumbnail:", error);
60
- throw error;
60
+ return error;
61
61
  }
62
62
  }
63
63
 
@@ -66,7 +66,7 @@ class ThumbnailGenerator {
66
66
  width: number = 320,
67
67
  ): Promise<string> {
68
68
  if (!sharp) {
69
- throw new Error(
69
+ return new Error(
70
70
  "sharp module is not installed. Some features may be disabled.",
71
71
  );
72
72
  }
@@ -76,7 +76,7 @@ class ThumbnailGenerator {
76
76
  return buffer.toString("base64");
77
77
  } catch (error) {
78
78
  console.error("Error generating image thumbnail:", error);
79
- throw error;
79
+ return error;
80
80
  }
81
81
  }
82
82
  }
@@ -20,7 +20,7 @@ interface SendPayloadInputs {
20
20
  * Retrieves API and WSS server URLs
21
21
  */
22
22
  export async function getDcs(network: Network): Promise<boolean> {
23
- const url = "https://getdcmess.iranlms.ir/";
23
+ const url = `https://${network.client.application === "Shad" ? "sh" : ""}getdcmess.iranlms.ir/`;
24
24
  const RETRY_DELAY = 3000;
25
25
 
26
26
  while (true) {
@@ -86,7 +86,7 @@ export async function sendRequest(network: Network, url: string, data: any) {
86
86
 
87
87
  await network.delay(1000);
88
88
  }
89
- throw network.client.logger.error(
89
+ return network.client.logger.error(
90
90
  `[request] Failed after ${MAX_ATTEMPTS} attempts: ${url}`,
91
91
  "warn",
92
92
  );
@@ -8,7 +8,7 @@ export async function uploadFile(
8
8
  chunkSize: number = 1048576,
9
9
  ): Promise<any> {
10
10
  if (!fs.existsSync(filePath))
11
- throw new Error("File not found in the given path");
11
+ return new Error("File not found in the given path");
12
12
 
13
13
  const stat = await fs.promises.stat(filePath);
14
14
  const fileSize = stat.size;
@@ -81,7 +81,7 @@ export async function uploadFile(
81
81
  }
82
82
  }
83
83
 
84
- throw new Error("Upload failed completely.");
84
+ return new Error("Upload failed completely.");
85
85
  }
86
86
 
87
87
  export async function download(
@@ -20,8 +20,9 @@ export default class Network {
20
20
  public reconnecting: boolean = false;
21
21
 
22
22
  constructor(public client: Client) {
23
- this.defaultPlatform = resolvePlatform(client.platform);
24
- this.headers = buildHeaders(client.platform);
23
+ const isShad = client.application === "Shad";
24
+ this.defaultPlatform = resolvePlatform(client.platform , isShad);
25
+ this.headers = buildHeaders(client.platform , isShad);
25
26
  }
26
27
 
27
28
  getDcs = () => getDcs(this);
@@ -1,30 +1,32 @@
1
- import UserAgent from 'user-agents';
1
+ import UserAgent from "user-agents";
2
2
 
3
3
  export function delay(ms: number) {
4
- return new Promise((resolve) => setTimeout(resolve, ms));
4
+ return new Promise((resolve) => setTimeout(resolve, ms));
5
5
  }
6
6
 
7
- export function resolvePlatform(platform: string) {
8
- const isAndroid = platform?.toLowerCase() === 'android';
9
- return {
10
- app_name: 'Main',
11
- app_version: isAndroid ? '3.6.4' : '4.4.9',
12
- platform: isAndroid ? 'Android' : 'Web',
13
- package: isAndroid ? 'app.rbmain.a' : 'web.rubika.ir',
14
- lang_code: 'fa',
15
- };
7
+ export function resolvePlatform(platform: string, isShad: boolean) {
8
+ const isAndroid = platform?.toLowerCase() === "android";
9
+ return {
10
+ app_name: "Main",
11
+ app_version: isAndroid ? "3.6.4" : "4.4.9",
12
+ platform: isAndroid ? "Android" : "Web",
13
+ package: isAndroid
14
+ ? `app.${isShad ? "sh" : "rb"}main.a`
15
+ : `web.${isShad ? "shad" : "rubika"}.ir`,
16
+ lang_code: "fa",
17
+ };
16
18
  }
17
19
 
18
- export function buildHeaders(platform: string) {
19
- const headers: Record<string, string> = {
20
- 'content-type': 'application/json',
21
- connection: 'keep-alive',
22
- 'user-agent': new UserAgent().toString(),
23
- };
24
- if (platform.toLowerCase() !== 'android') {
25
- headers.origin = 'https://web.rubika.ir';
26
- headers.referer = 'https://web.rubika.ir/';
27
- }
20
+ export function buildHeaders(platform: string, isShad: boolean) {
21
+ const headers: Record<string, string> = {
22
+ "content-type": "application/json",
23
+ connection: "keep-alive",
24
+ "user-agent": new UserAgent().toString(),
25
+ };
26
+ if (platform.toLowerCase() !== "android") {
27
+ headers.origin = `https://web.${isShad ? "shad" : "rubika"}.ir`;
28
+ headers.referer = `https://web.${isShad ? "shad" : "rubika"}.ir/`;
29
+ }
28
30
 
29
- return headers;
31
+ return headers;
30
32
  }
@@ -1,6 +1,6 @@
1
1
  import Network from ".";
2
2
  import Crypto from "../crypto";
3
- import { ContextMap, Handler } from "../types/client.type";
3
+ import { ContextMapCon, Handler } from "../types/client.type";
4
4
  import { ContextConstructors } from "../contexts/contextConstructors";
5
5
  import Message from "../contexts/message.type";
6
6
  import { checkFilters } from "../../utils";
@@ -143,9 +143,9 @@ async function getMessage(message: string, network: Network) {
143
143
  }
144
144
  }
145
145
 
146
- async function handleCategory<T extends keyof ContextMap>(
146
+ async function handleCategory<T extends keyof ContextMapCon>(
147
147
  type: T,
148
- handlers: Handler<ContextMap[T]>[],
148
+ handlers: Handler<ContextMapCon[T]>[],
149
149
  updates: any[],
150
150
  network: Network,
151
151
  author_title: string,
@@ -161,7 +161,7 @@ async function handleCategory<T extends keyof ContextMap>(
161
161
  update.client_guid = network.client.userGuid;
162
162
  update.message.author_title = author_title;
163
163
 
164
- const ctx = new CtxClass(network.client, update) as ContextMap[T];
164
+ const ctx = new CtxClass(network.client, update) as ContextMapCon[T];
165
165
 
166
166
  for (const { filters, handler, prefix } of handlers) {
167
167
  const passed = await checkFilters(ctx, filters);
@@ -17,12 +17,6 @@ export type TypeUpdate = "activities" | "chat" | "message" | "notifications";
17
17
  export type SessionType = string | Session;
18
18
  export type PlatformType = "Android" | "Web";
19
19
 
20
- export type ErrorMiddleware = (
21
- error: any,
22
- ctx: Message,
23
- next: () => Promise<void>,
24
- ) => Promise<void>;
25
-
26
20
  // پلاگین
27
21
  type PluginFunction = (client: Client) => Promise<void>;
28
22
 
@@ -43,6 +37,13 @@ export interface ContextMap {
43
37
  };
44
38
  }
45
39
 
40
+ export interface ContextMapCon {
41
+ chat: Chat;
42
+ message: Message;
43
+ activities: Activities;
44
+ notifications: Notifications;
45
+ }
46
+
46
47
  export type Handler<T> = {
47
48
  filters: Array<(ctx: T) => boolean | Promise<boolean>>;
48
49
  handler: (ctx: T) => Promise<void>;
@@ -0,0 +1,224 @@
1
+ import { Message } from "./decorators.type";
2
+
3
+ type OnlineTimeType =
4
+ | "Exact"
5
+ | "Recently"
6
+ | "LastWeek"
7
+ | "LastMonth"
8
+ | "Offline";
9
+ type FileId = string | number;
10
+
11
+ interface AvatarThumbnail {
12
+ file_id: FileId;
13
+ mime: string;
14
+ dc_id: string;
15
+ access_hash_rec: string;
16
+ }
17
+
18
+ interface MusicTrack {
19
+ file_id: FileId;
20
+ mime: string;
21
+ dc_id: string;
22
+ access_hash_rec: string;
23
+ file_name: string;
24
+ width: number;
25
+ height: number;
26
+ time: number;
27
+ size: number;
28
+ type: string;
29
+ music_performer: string;
30
+ }
31
+
32
+ interface BaseUser {
33
+ user_guid: string;
34
+ first_name: string;
35
+ last_name: string;
36
+ phone: string;
37
+ username?: string;
38
+ avatar_thumbnail?: AvatarThumbnail;
39
+ last_online: number;
40
+ bio: string;
41
+ is_deleted: boolean;
42
+ is_verified: boolean;
43
+ online_time: { type: OnlineTimeType | string; exact_time?: number };
44
+ birth_date?: string;
45
+ saved_music_last_track?: MusicTrack;
46
+ }
47
+
48
+ export interface GetUserInfoResponse {
49
+ user: BaseUser;
50
+ chat: {
51
+ object_guid: string;
52
+ access: string[];
53
+ count_unseen: number;
54
+ is_mute: boolean;
55
+ is_pinned: boolean;
56
+ time_string: string;
57
+ last_message?: {
58
+ message_id: string;
59
+ type: string;
60
+ text?: string;
61
+ author_object_guid: string;
62
+ is_mine: boolean;
63
+ author_title: string;
64
+ author_type: string;
65
+ };
66
+ last_seen_my_mid: string;
67
+ last_seen_peer_mid: string;
68
+ status: string;
69
+ time: number;
70
+ abs_object: {
71
+ object_guid: string;
72
+ type: string;
73
+ first_name?: string;
74
+ last_name?: string;
75
+ avatar_thumbnail?: AvatarThumbnail;
76
+ is_verified: boolean;
77
+ is_deleted: boolean;
78
+ };
79
+ is_blocked: boolean;
80
+ last_message_id: string;
81
+ last_deleted_mid?: string;
82
+ has_schedule: boolean;
83
+ auto_delete: string;
84
+ };
85
+ timestamp: string;
86
+ can_receive_call: boolean;
87
+ can_video_call: boolean;
88
+ user_additional_info: {
89
+ is_in_contact: boolean;
90
+ can_receive_call: boolean;
91
+ can_video_call: boolean;
92
+ photo_changed_time?: number;
93
+ };
94
+ }
95
+
96
+ export interface SendCodeResponse {
97
+ phone_code_hash: string;
98
+ status: "OK" | string;
99
+ code_digits_count: number;
100
+ has_confirmed_recovery_email: boolean;
101
+ no_recovery_alert?: string;
102
+ send_type: "SMS" | string;
103
+ hint_pass_key: string
104
+ }
105
+
106
+ export interface SignInResponse {
107
+ status: "OK" | string;
108
+ auth: string;
109
+ user: BaseUser;
110
+ timestamp: string;
111
+ two_step_enabled?: boolean;
112
+ }
113
+
114
+ export interface AddChannelResponse {
115
+ channel: {
116
+ channel_guid: string;
117
+ channel_title: string;
118
+ count_members: number;
119
+ description: string;
120
+ is_deleted: boolean;
121
+ is_verified: boolean;
122
+ channel_type: string;
123
+ sign_messages: boolean;
124
+ chat_reaction_setting: {
125
+ reaction_type: string;
126
+ };
127
+ is_restricted_content: boolean;
128
+ };
129
+ chat_update: {
130
+ object_guid: string;
131
+ action: string;
132
+ chat: {
133
+ object_guid: string;
134
+ access: string[];
135
+ count_unseen: number;
136
+ is_mute: boolean;
137
+ is_pinned: boolean;
138
+ time_string: string;
139
+ last_message?: {
140
+ message_id: string;
141
+ type: string;
142
+ text: string;
143
+ is_mine: boolean;
144
+ };
145
+ last_seen_my_mid: string;
146
+ last_seen_peer_mid: string;
147
+ status: string;
148
+ time: number;
149
+ abs_object: {
150
+ object_guid: string;
151
+ type: string;
152
+ title: string;
153
+ is_verified: boolean;
154
+ is_deleted: boolean;
155
+ };
156
+ is_blocked: boolean;
157
+ last_message_id: string;
158
+ last_deleted_mid?: string;
159
+ show_ask_spam?: boolean;
160
+ auto_delete: string;
161
+ };
162
+ updated_parameters: any[];
163
+ timestamp: string;
164
+ type: string;
165
+ };
166
+ message_update?: Message;
167
+ timestamp: string;
168
+ }
169
+
170
+ export interface GetChannelInfoResponse {
171
+ channel: {
172
+ channel_guid: string;
173
+ channel_title: string;
174
+ avatar_thumbnail?: AvatarThumbnail;
175
+ count_members: number;
176
+ description: string;
177
+ username?: string;
178
+ is_deleted: boolean;
179
+ is_verified: boolean;
180
+ share_url?: string;
181
+ channel_type: string;
182
+ sign_messages: boolean;
183
+ chat_reaction_setting: {
184
+ reaction_type: string;
185
+ selected_reactions: string[];
186
+ };
187
+ is_restricted_content: boolean;
188
+ };
189
+ chat: {
190
+ object_guid: string;
191
+ access: string[];
192
+ count_unseen: number;
193
+ is_mute: boolean;
194
+ is_pinned: boolean;
195
+ time_string: string;
196
+ last_message?: {
197
+ message_id: string;
198
+ type: string;
199
+ text: string;
200
+ is_mine: boolean;
201
+ };
202
+ last_seen_my_mid: string;
203
+ last_seen_peer_mid: string;
204
+ status: string;
205
+ time: number;
206
+ abs_object: {
207
+ object_guid: string;
208
+ type: string;
209
+ title?: string;
210
+ avatar_thumbnail?: AvatarThumbnail;
211
+ is_verified: boolean;
212
+ is_deleted: boolean;
213
+ };
214
+ is_blocked: boolean;
215
+ last_message_id: string;
216
+ last_deleted_mid?: string;
217
+ show_ask_spam?: boolean;
218
+ is_archived?: boolean;
219
+ auto_delete: string;
220
+ };
221
+ timestamp: string;
222
+ }
223
+
224
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rubika",
3
- "version": "1.2.0",
3
+ "version": "1.2.3",
4
4
  "author": "Hadi Rostami",
5
5
  "main": "index.ts",
6
6
  "description": "A modern library for Rubika built with Bun.",