rubika 1.0.4 → 1.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rubika",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "author": "Hadi Rostami",
5
5
  "main": "src/index.ts",
6
6
  "description": "A modern library for Rubika built with Bun.",
@@ -1,3 +1,6 @@
1
+ import banChatMember from './banChatMember';
1
2
  import getChat from './getChat';
3
+ import unbanChatMember from './unbanChatMember';
2
4
 
3
- export { getChat };
5
+
6
+ export { getChat, banChatMember, unbanChatMember };
@@ -170,6 +170,20 @@ export default class Methods {
170
170
  return Chat.getChat.apply(this, args);
171
171
  }
172
172
 
173
+ async banChatMember(
174
+ this: Bot,
175
+ ...args: Parameters<typeof Chat.banChatMember>
176
+ ): Promise<any> {
177
+ return Chat.banChatMember.apply(this, args);
178
+ }
179
+
180
+ async unbanChatMember(
181
+ this: Bot,
182
+ ...args: Parameters<typeof Chat.unbanChatMember>
183
+ ): Promise<any> {
184
+ return Chat.unbanChatMember.apply(this, args);
185
+ }
186
+
173
187
  // utilities
174
188
  async start(
175
189
  this: Bot,
@@ -1,9 +1,34 @@
1
- export type MarkdownEntity = {
2
- type: string;
1
+ export type MarkdownType =
2
+ | "Quote"
3
+ | "Pre"
4
+ | "Bold"
5
+ | "Mono"
6
+ | "Italic"
7
+ | "Underline"
8
+ | "Strike"
9
+ | "Spoiler"
10
+ | "Link"
11
+ | "MentionText";
12
+
13
+ export interface MetaDataPart {
14
+ type: MarkdownType;
3
15
  from_index: number;
4
16
  length: number;
5
17
  language?: string;
18
+ link_url?: string;
19
+ link?: {
20
+ type: string;
21
+ hyperlink_data?: { url: string };
22
+ };
6
23
  mention_text_object_guid?: string;
24
+ mention_text_user_id?: string;
7
25
  mention_text_object_type?: string;
8
- link?: { type: string; hyperlink_data: { url: string } };
9
- };
26
+ }
27
+
28
+
29
+ export interface MetadataResult {
30
+ text: string;
31
+ metadata?: {
32
+ meta_data_parts: MetaDataPart[];
33
+ };
34
+ }
@@ -1,127 +1,173 @@
1
- import { MarkdownEntity } from "../types/utils";
2
-
3
- class Markdown {
4
- static markdownRegExp =
5
- /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)(`|\*\*|__|~~|--|\|\||\^\^)([^\n]+?)\7([\s\.,:?!;]|$)|@([a-zA-Z0-9]+)\s*\((.+?)\)|\[(.+?)\]\((.+?)\)/m;
6
-
7
- static markdownEntities: Record<string, string> = {
8
- "`": "Mono",
9
- "**": "Bold",
10
- __: "Italic",
11
- "||": "Spoiler",
12
- "~~": "Strike",
13
- "--": "Underline",
14
- "^^": "Quote",
15
- };
16
-
17
- static toMetadata(text: string): {
18
- text: string;
19
- metadata?: { meta_data_parts: MarkdownEntity[] };
20
- } {
21
- let entities: MarkdownEntity[] = [];
22
- let match: RegExpMatchArray | null;
23
- let remainingText = text;
24
- let parsedTextParts: string[] = [];
25
- let offset = 0;
1
+ import { MarkdownType, MetaDataPart, MetadataResult } from "../types/utils";
2
+
3
+ const MENTION_PREFIX_TYPES: Record<string, string> = {
4
+ u: "User",
5
+ g: "Group",
6
+ c: "Channel",
7
+ b: "Bot",
8
+ };
9
+
10
+ function buildUtf16PrefixLengths(text: string): number[] {
11
+ const prefixLengths: number[] = [0];
12
+ let total = 0;
13
+ for (const char of text) {
14
+ total += char.codePointAt(0)! > 0xffff ? 2 : 1;
15
+ prefixLengths.push(total);
16
+ }
17
+ return prefixLengths;
18
+ }
26
19
 
27
- while ((match = remainingText.match(this.markdownRegExp))) {
28
- const matchIndex = offset + (match.index || 0);
29
- parsedTextParts.push(remainingText.substring(0, match.index!));
30
- let matchedContent = match[3] || match[8] || match[11] || match[13];
31
-
32
- if (matchedContent) {
33
- offset -= matchedContent.length;
34
- matchedContent = matchedContent.trim();
35
- offset += matchedContent.length;
36
-
37
- if (/^`*$/.test(matchedContent)) {
38
- parsedTextParts.push(match[0]);
39
- } else if (match[3]) {
40
- if (match[5] === "\n") {
41
- match[5] = "";
42
- offset -= 1;
43
- }
44
- parsedTextParts.push(match[1] + matchedContent + match[5]);
45
- entities.push({
46
- type: "Pre",
47
- language: "",
48
- from_index: matchIndex + match[1].length,
49
- length: matchedContent.length,
50
- });
51
- offset -= match[2].length + match[4].length;
52
- } else if (match[7]) {
53
- parsedTextParts.push(match[6] + matchedContent + match[9]);
54
- entities.push({
55
- type: this.markdownEntities[match[7]],
56
- from_index: matchIndex + match[6].length,
57
- length: matchedContent.length,
58
- });
59
- offset -= 2 * match[7].length;
60
- } else if (match[11]) {
61
- parsedTextParts.push(matchedContent);
62
- entities.push({
63
- type: "MentionText",
64
- mention_text_object_guid: match[10],
65
- from_index: matchIndex,
66
- length: matchedContent.length,
67
- mention_text_object_type: "User",
68
- });
69
- offset -= match[0].length - matchedContent.length;
70
- } else if (match[12]) {
71
- const [label, url] = [match[12], match[13]];
72
-
73
- let mentionType: string | undefined;
74
- if (url.length === 32) {
75
- if (url.startsWith("u")) mentionType = "User";
76
- else if (url.startsWith("g")) mentionType = "Group";
77
- else if (url.startsWith("c")) mentionType = "Channel";
20
+ const MARKDOWN_RE =
21
+ /(?:^(?:> ?[^\n]*\n?)+)|```([\s\S]*?)```|\*\*([^\n*]+?)\*\*|`([^\n`]+?)`|__([^\n_]+?)__|--([^\n-]+?)--|~~([^\n~]+?)~~|\|\|([^\n|]+?)\|\||\[([^\]]+?)\]\((\S+)\)/gms;
22
+
23
+ const MARKDOWN_TYPE_SEQUENCE: [string, [MarkdownType, number | null]][] = [
24
+ [">", ["Quote", null]],
25
+ ["```", ["Pre", 1]],
26
+ ["**", ["Bold", 2]],
27
+ ["`", ["Mono", 3]],
28
+ ["__", ["Italic", 4]],
29
+ ["--", ["Underline", 5]],
30
+ ["~~", ["Strike", 6]],
31
+ ["||", ["Spoiler", 7]],
32
+ ["[", ["Link", 8]],
33
+ ];
34
+
35
+ export default class Markdown {
36
+ static toMetadata(text: string): MetadataResult {
37
+ const metaDataParts: MetaDataPart[] = [];
38
+ let currentText = text;
39
+ let offset = 0;
40
+ let charOffset = 0;
41
+ const utf16Prefix = buildUtf16PrefixLengths(text);
42
+
43
+ let match: RegExpExecArray | null;
44
+ const globalRegex = new RegExp(MARKDOWN_RE, "gms");
45
+
46
+ while ((match = globalRegex.exec(text)) !== null) {
47
+ const group = match[0];
48
+ const start = match.index;
49
+ const end = start + group.length;
50
+ const adjustedStart = utf16Prefix[start] - offset;
51
+ const adjustedCharStart = start - charOffset;
52
+
53
+ for (const [prefix, [mdType, groupIdx]] of MARKDOWN_TYPE_SEQUENCE) {
54
+ if (group.startsWith(prefix)) {
55
+ let content = "";
56
+ let contentLength = 0;
57
+ let charContentLength = 0;
58
+
59
+ if (mdType === "Quote") {
60
+ const quoteLines = group.split("\n");
61
+ const contentLines = quoteLines.map((line) => {
62
+ if (line.startsWith("> ")) return line.slice(2);
63
+ if (line.startsWith(">")) return line.slice(1);
64
+ return line;
65
+ });
66
+ content = contentLines.join("\n");
67
+ charContentLength = content.length;
68
+ contentLength = Markdown.getUtf16Length(content);
69
+
70
+ const innerMeta = this.toMetadata(content);
71
+ content = innerMeta.text;
72
+ contentLength = Markdown.getUtf16Length(content);
73
+ charContentLength = content.length;
74
+
75
+ if (innerMeta.metadata) {
76
+ for (const part of innerMeta.metadata.meta_data_parts) {
77
+ part.from_index += adjustedStart;
78
+ metaDataParts.push(part);
79
+ }
80
+ }
81
+ } else {
82
+ if (groupIdx !== null && match[groupIdx] !== undefined) {
83
+ content = match[groupIdx] || "";
84
+ const groupStart = match.index + group.indexOf(content);
85
+ const groupEnd = groupStart + content.length;
86
+ contentLength = utf16Prefix[groupEnd] - utf16Prefix[groupStart];
87
+ charContentLength = content.length;
88
+
89
+ if (mdType !== "Pre" && mdType !== "Link") {
90
+ const innerMeta = this.toMetadata(content);
91
+ content = innerMeta.text;
92
+ contentLength = Markdown.getUtf16Length(content);
93
+ charContentLength = content.length;
94
+
95
+ if (innerMeta.metadata) {
96
+ for (const part of innerMeta.metadata.meta_data_parts) {
97
+ part.from_index += adjustedStart;
98
+ metaDataParts.push(part);
99
+ }
100
+ }
101
+ }
102
+ } else {
103
+ content = "";
104
+ contentLength = 0;
105
+ charContentLength = 0;
106
+ }
78
107
  }
79
108
 
80
- parsedTextParts.push(label);
81
- const metaDataPart: MarkdownEntity = {
82
- type: mentionType ? "MentionText" : "Link",
83
- from_index: matchIndex,
84
- length: label.length,
109
+ const metaDataPart: MetaDataPart = {
110
+ type: mdType,
111
+ from_index: adjustedStart,
112
+ length: contentLength,
85
113
  };
86
114
 
87
- if (mentionType) {
88
- metaDataPart.mention_text_object_guid = url;
89
- metaDataPart.mention_text_object_type = mentionType;
90
- } else {
91
- metaDataPart.link = { type: "hyperlink", hyperlink_data: { url } };
115
+ // تنظیمات بر اساس نوع
116
+ if (mdType === "Pre") {
117
+ const lines = content.split("\n", 2);
118
+ const language =
119
+ lines.length > 1 && lines[0].trim() ? lines[0].trim() : "";
120
+ metaDataPart.language = language;
121
+ if (language) {
122
+ content = lines.slice(1).join("\n");
123
+ contentLength = Markdown.getUtf16Length(content);
124
+ charContentLength = content.length;
125
+ }
126
+ } else if (mdType === "Link") {
127
+ const url = match[9];
128
+ const mentionType = MENTION_PREFIX_TYPES[url?.[0]] || "hyperlink";
129
+
130
+ if (mentionType === "hyperlink") {
131
+ metaDataPart.link_url = url;
132
+ metaDataPart.link = {
133
+ type: mentionType,
134
+ hyperlink_data: { url },
135
+ };
136
+ } else {
137
+ metaDataPart.type = "MentionText";
138
+ metaDataPart.mention_text_object_guid = url;
139
+ metaDataPart.mention_text_user_id = url;
140
+ metaDataPart.mention_text_object_type = mentionType;
141
+ }
92
142
  }
93
143
 
94
- entities.push(metaDataPart);
95
- offset -= match[0].length - label.length;
96
- }
144
+ metaDataParts.push(metaDataPart);
145
+ currentText =
146
+ currentText.slice(0, adjustedCharStart) +
147
+ content +
148
+ currentText.slice(end - charOffset);
97
149
 
98
- remainingText = remainingText.substring(match.index! + match[0].length);
99
- offset += match.index! + match[0].length;
100
- }
101
- }
150
+ const markupLength = utf16Prefix[end] - utf16Prefix[start];
151
+ const charMarkupLength = end - start;
152
+ offset += markupLength - contentLength;
153
+ charOffset += charMarkupLength - charContentLength;
102
154
 
103
- parsedTextParts.push(remainingText);
104
- let resultText = parsedTextParts.join("");
105
- if (!resultText.replace(/\s+/g, "").length) {
106
- resultText = text;
107
- entities.splice(0, entities.length);
108
- }
109
- if (!entities.length) {
110
- resultText = resultText.trim();
155
+ break;
156
+ }
157
+ }
111
158
  }
112
159
 
113
- let returnData: {
114
- text: string;
115
- metadata?: { meta_data_parts: MarkdownEntity[] };
116
- } = {
117
- text: resultText,
160
+ return {
161
+ text: currentText.trim(),
162
+ ...(metaDataParts.length > 0 && {
163
+ metadata: { meta_data_parts: metaDataParts },
164
+ }),
118
165
  };
166
+ }
119
167
 
120
- if (entities.length > 0)
121
- returnData.metadata = { meta_data_parts: entities };
122
-
123
- return returnData;
168
+ static getUtf16Length(str: string): number {
169
+ return str.split("").reduce((len, char) => {
170
+ return len + (char.codePointAt(0)! > 0xffff ? 2 : 1);
171
+ }, 0);
124
172
  }
125
173
  }
126
-
127
- export default Markdown;
package/src/utils.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  class Utils {
2
- static Code = (text: string): string => "`" + text.trim() + "`";
2
+ static Mono = (text: string): string => "`" + text.trim() + "`";
3
+ static Pre = (text: string): string => "```" + text.trim() + "```";
3
4
  static Bold = (text: string): string => `**${text.trim()}**`;
4
5
  static Italic = (text: string): string => `__${text.trim()}__`;
5
6
  static Spoiler = (text: string): string => `||${text.trim()}||`;
6
7
  static Strike = (text: string): string => `~~${text.trim()}~~`;
7
8
  static Underline = (text: string): string => `--${text.trim()}--`;
8
- static Quote = (text: string): string => `^^${text.trim()}^^`;
9
+ static Quote = (text: string): string => `>${text.trim()}>`;
9
10
  static HyperLink = (text: string, link: string): string =>
10
11
  `[${text.trim()}](${link.trim()})`;
11
12
  }