telegram-badge 1.4.0 → 1.5.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.
- package/README.ar.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +18 -3
- package/README.ru.md +18 -1
- package/README.th.md +1 -1
- package/README.zh.md +6 -6
- package/dist/api/badge-generator.js +3 -3
- package/dist/api/telegram-badge.js +4 -2
- package/dist/tests/telegram-badge.test.js +24 -18
- package/package.json +9 -1
package/README.ar.md
CHANGED
package/README.ja.md
CHANGED
package/README.ko.md
CHANGED
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Telegram Group Badge Generator
|
|
2
2
|
|
|
3
3
|
[🇷🇺 Русский](README.ru.md) | [🇺🇸 English](README.md) | [🇨🇳 中文](README.zh.md) | [🇹🇭 ไทย](README.th.md) | [🇸🇦 العربية](README.ar.md) | [🇯🇵 日本語](README.ja.md) | [🇰🇷 한국어](README.ko.md)
|
|
4
4
|
|
|
@@ -188,6 +188,23 @@ import badgeHandler from 'telegram-badge';
|
|
|
188
188
|
export default badgeHandler;
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
+
### As Deno/JSR package:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Using JSR
|
|
195
|
+
deno add @chatman-media/telegram-badge
|
|
196
|
+
|
|
197
|
+
# Or import directly
|
|
198
|
+
import badgeHandler from "jsr:@chatman-media/telegram-badge";
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import badgeHandler from "@chatman-media/telegram-badge";
|
|
203
|
+
|
|
204
|
+
// Use in your Deno serverless function
|
|
205
|
+
export default badgeHandler;
|
|
206
|
+
```
|
|
207
|
+
|
|
191
208
|
### Direct API calls:
|
|
192
209
|
|
|
193
210
|
```typescript
|
|
@@ -224,8 +241,6 @@ npm run build
|
|
|
224
241
|
|
|
225
242
|
## Subscribe
|
|
226
243
|
|
|
227
|
-
### 🌐 Follow on Social Media
|
|
228
|
-
|
|
229
244
|
[](https://stackoverflow.com/users/724036/alexander-kireyev)
|
|
230
245
|
|
|
231
246
|
[](https://github.com/chatman-media)
|
package/README.ru.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Telegram Group Badge Generator
|
|
2
2
|
|
|
3
3
|
[🇷🇺 Русский](README.ru.md) | [🇺🇸 English](README.md) | [🇨🇳 中文](README.zh.md) | [🇹🇭 ไทย](README.th.md) | [🇸🇦 العربية](README.ar.md) | [🇯🇵 日本語](README.ja.md) | [🇰🇷 한국어](README.ko.md)
|
|
4
4
|
|
|
@@ -187,6 +187,23 @@ import badgeHandler from 'telegram-badge';
|
|
|
187
187
|
export default badgeHandler;
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
+
### Как Deno/JSR пакет:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Используя JSR
|
|
194
|
+
deno add @chatman-media/telegram-badge
|
|
195
|
+
|
|
196
|
+
# Или импортируйте напрямую
|
|
197
|
+
import badgeHandler from "jsr:@chatman-media/telegram-badge";
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import badgeHandler from "@chatman-media/telegram-badge";
|
|
202
|
+
|
|
203
|
+
// Используйте в вашей Deno serverless функции
|
|
204
|
+
export default badgeHandler;
|
|
205
|
+
```
|
|
206
|
+
|
|
190
207
|
### Прямые вызовы API:
|
|
191
208
|
|
|
192
209
|
```typescript
|
package/README.th.md
CHANGED
package/README.zh.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Telegram 群组徽章生成器
|
|
2
2
|
|
|
3
3
|
[🇷🇺 Русский](README.ru.md) | [🇺🇸 English](README.md) | [🇨🇳 中文](README.zh.md) | [🇹🇭 ไทย](README.th.md) | [🇸🇦 العربية](README.ar.md) | [🇯🇵 日本語](README.ja.md) | [🇰🇷 한국어](README.ko.md)
|
|
4
4
|
|
|
5
|
-
[](https://github.com/chatman-media/telegram-badge/actions)
|
|
6
|
+
[](https://github.com/chatman-media/telegram-badge/actions)
|
|
7
|
+
[](https://www.npmjs.com/package/telegram-badge)
|
|
8
8
|
[](https://jsr.io/@chatman-media/telegram-badge)
|
|
9
|
-
[](https://bundlephobia.com/package/telegram-badge)
|
|
10
10
|
[](https://www.typescriptlang.org/)
|
|
11
|
-
[](https://opensource.org/licenses/MIT)
|
|
12
12
|
|
|
13
13
|
[](https://github.com/chatman-media/telegram-badge)
|
|
14
14
|
[](https://dev.to/chatman-media/show-your-telegram-group-member-count-in-github-readme-46pl)
|
|
@@ -14,10 +14,10 @@ function generateBadgeSVG(format) {
|
|
|
14
14
|
const messageWidth = message.length * 7 + 20;
|
|
15
15
|
const totalWidth = labelWidth + messageWidth;
|
|
16
16
|
// Create logo element
|
|
17
|
-
const logoElement = logo ? `<image x="5" y="3" width="14" height="14" href="data:image/svg+xml;base64,${
|
|
17
|
+
const logoElement = logo ? `<image x="5" y="3" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
|
|
18
18
|
// For-the-badge style
|
|
19
19
|
if (style === 'for-the-badge') {
|
|
20
|
-
const logoForBadge = logo ? `<image x="5" y="7" width="14" height="14" href="data:image/svg+xml;base64,${
|
|
20
|
+
const logoForBadge = logo ? `<image x="5" y="7" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
|
|
21
21
|
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth}" height="28" role="img" aria-label="${label}: ${message}">
|
|
22
22
|
<title>${label}: ${message}</title>
|
|
23
23
|
<g shape-rendering="crispEdges">
|
|
@@ -48,7 +48,7 @@ function generateBadgeSVG(format) {
|
|
|
48
48
|
}
|
|
49
49
|
// Social style
|
|
50
50
|
if (style === 'social') {
|
|
51
|
-
const socialLogoElement = logo ? `<image x="7" y="3" width="14" height="14" href="data:image/svg+xml;base64,${
|
|
51
|
+
const socialLogoElement = logo ? `<image x="7" y="3" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
|
|
52
52
|
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth + 4}" height="20" style="border-radius: 3px" role="img" aria-label="${label}: ${message}">
|
|
53
53
|
<title>${label}: ${message}</title>
|
|
54
54
|
<linearGradient id="s" x2="0" y2="100%">
|
|
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.default = handler;
|
|
37
|
-
const crypto = __importStar(require("crypto"));
|
|
37
|
+
const crypto = __importStar(require("node:crypto"));
|
|
38
38
|
const badge_generator_1 = require("./badge-generator");
|
|
39
39
|
const logger = {
|
|
40
40
|
info: (message, data = {}) => {
|
|
@@ -80,7 +80,6 @@ const getMemberCount = async (token, channelId) => {
|
|
|
80
80
|
'User-Agent': 'TelegramBadgeGenerator/1.0'
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
|
-
clearTimeout(timeoutId);
|
|
84
83
|
if (!response.ok) {
|
|
85
84
|
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
86
85
|
}
|
|
@@ -99,6 +98,9 @@ const getMemberCount = async (token, channelId) => {
|
|
|
99
98
|
logger.error('Error fetching member count', error);
|
|
100
99
|
throw error;
|
|
101
100
|
}
|
|
101
|
+
finally {
|
|
102
|
+
clearTimeout(timeoutId);
|
|
103
|
+
}
|
|
102
104
|
};
|
|
103
105
|
const validateStyleOptions = (options) => {
|
|
104
106
|
const validStyles = ['flat', 'plastic', 'flat-square', 'for-the-badge', 'social'];
|
|
@@ -36,8 +36,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const crypto = __importStar(require("node:crypto"));
|
|
39
40
|
const telegram_badge_1 = __importDefault(require("../api/telegram-badge"));
|
|
40
|
-
const crypto = __importStar(require("crypto"));
|
|
41
41
|
// Mock fetch globally
|
|
42
42
|
global.fetch = jest.fn();
|
|
43
43
|
// Mock console methods for clean test output
|
|
@@ -55,22 +55,23 @@ describe('Telegram Badge API', () => {
|
|
|
55
55
|
// Mock request and response objects
|
|
56
56
|
req = {
|
|
57
57
|
query: {},
|
|
58
|
-
headers: {}
|
|
58
|
+
headers: {},
|
|
59
59
|
};
|
|
60
60
|
res = {
|
|
61
61
|
status: jest.fn().mockReturnThis(),
|
|
62
62
|
send: jest.fn(),
|
|
63
63
|
setHeader: jest.fn(),
|
|
64
|
-
end: jest.fn()
|
|
64
|
+
end: jest.fn(),
|
|
65
65
|
};
|
|
66
66
|
// Mock successful Telegram API response
|
|
67
|
-
|
|
67
|
+
const mockResponse = {
|
|
68
68
|
ok: true,
|
|
69
69
|
json: jest.fn().mockResolvedValue({
|
|
70
70
|
ok: true,
|
|
71
|
-
result: 100
|
|
72
|
-
})
|
|
73
|
-
}
|
|
71
|
+
result: 100,
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
fetch.mockResolvedValue(mockResponse);
|
|
74
75
|
});
|
|
75
76
|
test('должен возвращать SVG бейдж с количеством участников', async () => {
|
|
76
77
|
await (0, telegram_badge_1.default)(req, res);
|
|
@@ -93,13 +94,14 @@ describe('Telegram Badge API', () => {
|
|
|
93
94
|
});
|
|
94
95
|
test('должен обрабатывать ошибки Telegram API', async () => {
|
|
95
96
|
// Mock Telegram API error
|
|
96
|
-
|
|
97
|
+
const mockErrorResponse = {
|
|
97
98
|
ok: true,
|
|
98
99
|
json: jest.fn().mockResolvedValue({
|
|
99
100
|
ok: false,
|
|
100
|
-
description: 'Test error'
|
|
101
|
-
})
|
|
102
|
-
}
|
|
101
|
+
description: 'Test error',
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
fetch.mockResolvedValue(mockErrorResponse);
|
|
103
105
|
await (0, telegram_badge_1.default)(req, res);
|
|
104
106
|
// Check that error response was sent
|
|
105
107
|
expect(res.status).toHaveBeenCalledWith(500);
|
|
@@ -119,7 +121,7 @@ describe('Telegram Badge API', () => {
|
|
|
119
121
|
style: 'flat-square',
|
|
120
122
|
label: 'Custom Label',
|
|
121
123
|
color: 'FF0000',
|
|
122
|
-
labelColor: '000000'
|
|
124
|
+
labelColor: '000000',
|
|
123
125
|
};
|
|
124
126
|
await (0, telegram_badge_1.default)(req, res);
|
|
125
127
|
// Check that response was sent with status 200
|
|
@@ -128,14 +130,16 @@ describe('Telegram Badge API', () => {
|
|
|
128
130
|
});
|
|
129
131
|
test('должен возвращать 304 Not Modified при совпадении ETag', async () => {
|
|
130
132
|
// Set If-None-Match header
|
|
131
|
-
const testEtag = '
|
|
132
|
-
req.headers
|
|
133
|
+
const testEtag = '"test-etag"';
|
|
134
|
+
if (req.headers) {
|
|
135
|
+
req.headers['if-none-match'] = testEtag;
|
|
136
|
+
}
|
|
133
137
|
// Mock the specific environment to create a predictable ETag
|
|
134
138
|
const originalEnv = process.env;
|
|
135
139
|
process.env = {
|
|
136
140
|
...originalEnv,
|
|
137
141
|
BOT_TOKEN: 'test_token_for_etag',
|
|
138
|
-
CHAT_ID: '@test_chat_for_etag'
|
|
142
|
+
CHAT_ID: '@test_chat_for_etag',
|
|
139
143
|
};
|
|
140
144
|
// We need to create the exact same hash that would be generated
|
|
141
145
|
const fixedTime = 1234567890000; // Fixed timestamp
|
|
@@ -147,10 +151,12 @@ describe('Telegram Badge API', () => {
|
|
|
147
151
|
token: 'test_token_for_etag',
|
|
148
152
|
channelId: '@test_chat_for_etag',
|
|
149
153
|
query: {},
|
|
150
|
-
time: Math.floor(fixedTime / 300000)
|
|
154
|
+
time: Math.floor(fixedTime / 300000),
|
|
151
155
|
}))
|
|
152
156
|
.digest('hex');
|
|
153
|
-
req.headers
|
|
157
|
+
if (req.headers) {
|
|
158
|
+
req.headers['if-none-match'] = `"${expectedHash}"`;
|
|
159
|
+
}
|
|
154
160
|
await (0, telegram_badge_1.default)(req, res);
|
|
155
161
|
// Restore environment
|
|
156
162
|
process.env = originalEnv;
|
|
@@ -171,7 +177,7 @@ describe('Telegram Badge API', () => {
|
|
|
171
177
|
test('должен валидировать стили бейджа', async () => {
|
|
172
178
|
// Set invalid style
|
|
173
179
|
req.query = {
|
|
174
|
-
style: 'invalid-style'
|
|
180
|
+
style: 'invalid-style',
|
|
175
181
|
};
|
|
176
182
|
await (0, telegram_badge_1.default)(req, res);
|
|
177
183
|
// Should still work with default style
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "telegram-badge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Generate Telegram group member count badges for GitHub README",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telegram",
|
|
@@ -36,12 +36,20 @@
|
|
|
36
36
|
"build": "echo 'Build handled by Vercel'",
|
|
37
37
|
"build:local": "tsc",
|
|
38
38
|
"type-check": "tsc --noEmit",
|
|
39
|
+
"lint": "biome lint .",
|
|
40
|
+
"lint:fix": "biome lint --write .",
|
|
41
|
+
"format": "biome format .",
|
|
42
|
+
"format:fix": "biome format --write .",
|
|
43
|
+
"check": "biome check .",
|
|
44
|
+
"check:fix": "biome check --write .",
|
|
39
45
|
"prepublishOnly": "npm run build:local && npm test",
|
|
40
46
|
"prepack": "npm run build:local",
|
|
41
47
|
"release": "semantic-release"
|
|
42
48
|
},
|
|
43
49
|
"devDependencies": {
|
|
50
|
+
"@biomejs/biome": "^2.2.4",
|
|
44
51
|
"@semantic-release/changelog": "^6.0.3",
|
|
52
|
+
"@semantic-release/exec": "7.1.0",
|
|
45
53
|
"@semantic-release/git": "^10.0.1",
|
|
46
54
|
"@semantic-release/github": "^11.0.6",
|
|
47
55
|
"@types/jest": "30.0.0",
|