Skip to content

Commit de8f4ce

Browse files
committed
feat: enhance template engine with user-specific data
- Bumped version of the backend contract to 0.3.68. - Added new template keys for USERNAME, EMAIL, and TELEGRAM_ID. - Implemented a method in TemplateEngine to format templates with user data, including traffic metrics and status. - Updated SubscriptionService and FormatHostsService to utilize the new user-specific template formatting for profile titles and remarks.
1 parent 772f9f8 commit de8f4ce

File tree

5 files changed

+37
-18
lines changed

5 files changed

+37
-18
lines changed

libs/contract/constants/templates/template-keys.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ export const TEMPLATE_KEYS = [
44
'TRAFFIC_LEFT',
55
'STATUS',
66
'TOTAL_TRAFFIC',
7+
'USERNAME',
8+
'EMAIL',
9+
'TELEGRAM_ID',
710
] as const;
811
export type TemplateKeys = (typeof TEMPLATE_KEYS)[number];

libs/contract/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@remnawave/backend-contract",
3-
"version": "0.3.67",
3+
"version": "0.3.68",
44
"public": true,
55
"license": "AGPL-3.0-only",
66
"description": "A contract library for Remnawave Backend. It can be used in backend and frontend.",

src/common/utils/templates/replace-templates-values.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1+
import dayjs from 'dayjs';
2+
13
import { TemplateKeys } from '@libs/contracts/constants/templates/template-keys';
4+
import { USER_STATUSES_TEMPLATE } from '@libs/contracts/constants';
5+
6+
import { UserWithActiveInboundsEntity } from '@modules/users/entities/user-with-active-inbounds.entity';
7+
8+
import { prettyBytesUtil } from '../bytes';
29

310
type TemplateValues = {
411
[key in TemplateKeys]: number | string | undefined;
@@ -17,4 +24,17 @@ export class TemplateEngine {
1724

1825
return hasReplacement ? result : template;
1926
}
27+
28+
static formarWithUser(template: string, user: UserWithActiveInboundsEntity): string {
29+
return this.replace(template, {
30+
DAYS_LEFT: dayjs(user.expireAt).diff(dayjs(), 'day'),
31+
TRAFFIC_USED: prettyBytesUtil(user.usedTrafficBytes, true, 3),
32+
TRAFFIC_LEFT: prettyBytesUtil(user.trafficLimitBytes - user.usedTrafficBytes, true, 3),
33+
TOTAL_TRAFFIC: prettyBytesUtil(user.trafficLimitBytes, true, 3),
34+
STATUS: USER_STATUSES_TEMPLATE[user.status],
35+
USERNAME: user.username,
36+
EMAIL: user.email || '',
37+
TELEGRAM_ID: user.telegramId?.toString() || '',
38+
});
39+
}
2040
}

src/modules/subscription-template/generators/format-hosts.service.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { randomUUID } from 'node:crypto';
2-
import dayjs from 'dayjs';
32

43
import { Injectable } from '@nestjs/common';
54
import { QueryBus } from '@nestjs/cqrs';
@@ -13,9 +12,7 @@ import {
1312
import { RawObject } from '@common/helpers/xray-config/interfaces/transport.config';
1413
import { TemplateEngine } from '@common/utils/templates/replace-templates-values';
1514
import { XRayConfig } from '@common/helpers/xray-config/xray-config.validator';
16-
import { prettyBytesUtil } from '@common/utils/bytes/pretty-bytes.util';
1715
import { ICommandResponse } from '@common/types/command-response.type';
18-
import { USER_STATUSES_TEMPLATE } from '@libs/contracts/constants/templates/user-statuses';
1916
import { SECURITY_LAYERS, USERS_STATUS } from '@libs/contracts/constants';
2017

2118
import { SubscriptionSettingsEntity } from '@modules/subscription-settings/entities/subscription-settings.entity';
@@ -57,7 +54,11 @@ export class FormatHostsService {
5754
break;
5855
}
5956

60-
formattedHosts.push(...this.createFallbackHosts(specialRemarks));
57+
const templatedRemarks = specialRemarks.map((remark) =>
58+
TemplateEngine.formarWithUser(remark, user),
59+
);
60+
61+
formattedHosts.push(...this.createFallbackHosts(templatedRemarks));
6162

6263
return formattedHosts;
6364
}
@@ -96,17 +97,7 @@ export class FormatHostsService {
9697
continue;
9798
}
9899

99-
const remark = TemplateEngine.replace(inputHost.remark, {
100-
DAYS_LEFT: dayjs(user.expireAt).diff(dayjs(), 'day'),
101-
TRAFFIC_USED: prettyBytesUtil(user.usedTrafficBytes, true, 3),
102-
TRAFFIC_LEFT: prettyBytesUtil(
103-
user.trafficLimitBytes - user.usedTrafficBytes,
104-
true,
105-
3,
106-
),
107-
TOTAL_TRAFFIC: prettyBytesUtil(user.trafficLimitBytes, true, 3),
108-
STATUS: USER_STATUSES_TEMPLATE[user.status],
109-
});
100+
const remark = TemplateEngine.formarWithUser(inputHost.remark, user);
110101

111102
const address = inputHost.address;
112103
const port = inputHost.port;

src/modules/subscription/subscription.service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Injectable, Logger } from '@nestjs/common';
44
import { CommandBus, QueryBus } from '@nestjs/cqrs';
55
import { ConfigService } from '@nestjs/config';
66

7+
import { TemplateEngine } from '@common/utils/templates/replace-templates-values';
78
import { prettyBytesUtil } from '@common/utils/bytes/pretty-bytes.util';
89
import { ICommandResponse } from '@common/types/command-response.type';
910
import { XRayConfig } from '@common/helpers/xray-config';
@@ -365,15 +366,19 @@ export class SubscriptionService {
365366
const headers: ISubscriptionHeaders = {
366367
'content-disposition': `attachment; filename="${user.username}"`,
367368
'support-url': settings.supportLink,
368-
'profile-title': `base64:${Buffer.from(settings.profileTitle).toString('base64')}`,
369+
'profile-title': `base64:${Buffer.from(
370+
TemplateEngine.formarWithUser(settings.profileTitle, user),
371+
).toString('base64')}`,
369372
'profile-update-interval': settings.profileUpdateInterval.toString(),
370373
'subscription-userinfo': Object.entries(getSubscriptionUserInfo(user))
371374
.map(([key, val]) => `${key}=${val}`)
372375
.join('; '),
373376
};
374377

375378
if (isHapp && settings.happAnnounce) {
376-
headers.announce = `base64:${Buffer.from(settings.happAnnounce).toString('base64')}`;
379+
headers.announce = `base64:${Buffer.from(
380+
TemplateEngine.formarWithUser(settings.happAnnounce, user),
381+
).toString('base64')}`;
377382
}
378383

379384
if (isHapp && settings.happRouting) {

0 commit comments

Comments
 (0)