Add /config trial VPN generation for users (1 day default)

Users get Remnawave subscription via /config or inline button; TRIAL_USER_DAYS and panel lookup by Telegram ID.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
tgvpn
2026-05-21 01:29:55 +03:00
parent 30866bb244
commit cbb2133991
9 changed files with 278 additions and 24 deletions
+41 -5
View File
@@ -19,14 +19,48 @@ type CreateUserInput struct {
}
type PanelUser struct {
UUID string
Username string
ShortUUID string
Status string
ExpireAt time.Time
UUID string
Username string
ShortUUID string
Status string
ExpireAt time.Time
SubscriptionURL string
}
func (c *Client) GetUserByUsername(ctx context.Context, username string) (*PanelUser, error) {
path := fmt.Sprintf("/api/users/by-username/%s", username)
resp, body, err := c.get(ctx, path)
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusNotFound {
return nil, nil
}
if resp.StatusCode != http.StatusOK {
return nil, apiError(resp.StatusCode, body)
}
return parsePanelUser(body), nil
}
func (c *Client) GetUserByTelegramID(ctx context.Context, telegramID int64) (*PanelUser, error) {
path := fmt.Sprintf("/api/users/by-telegram-id/%d", telegramID)
resp, body, err := c.get(ctx, path)
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusNotFound {
return nil, nil
}
if resp.StatusCode != http.StatusOK {
return nil, apiError(resp.StatusCode, body)
}
u := parsePanelUser(body)
if u == nil || u.UUID == "" {
return nil, nil
}
return u, nil
}
func (c *Client) CreateUser(ctx context.Context, in CreateUserInput) (*PanelUser, error) {
payload := map[string]any{
"username": in.Username,
@@ -118,6 +152,8 @@ func parsePanelUser(body []byte) *PanelUser {
if json.Unmarshal(raw, &s) == nil {
if t, err := time.Parse(time.RFC3339Nano, s); err == nil {
u.ExpireAt = t
} else if t, err := time.Parse(time.RFC3339, s); err == nil {
u.ExpireAt = t
}
}
}