mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-02-23 21:01:17 +00:00
Fix RemnaWave sync timezone handling
This commit is contained in:
@@ -8,7 +8,7 @@ from collections import defaultdict
|
||||
from datetime import time
|
||||
from typing import List, Optional, Union, Dict
|
||||
from pydantic_settings import BaseSettings
|
||||
from pydantic import field_validator, Field
|
||||
from pydantic import field_validator, Field, AliasChoices
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -64,6 +64,8 @@ class Settings(BaseSettings):
|
||||
REMNAWAVE_AUTH_TYPE: str = "api_key"
|
||||
REMNAWAVE_USER_DESCRIPTION_TEMPLATE: str = "Bot user: {full_name} {username}"
|
||||
REMNAWAVE_USER_DELETE_MODE: str = "delete" # "delete" или "disable"
|
||||
|
||||
TIMEZONE: str = Field(default="UTC", validation_alias=AliasChoices("TIMEZONE", "TZ"))
|
||||
|
||||
TRIAL_DURATION_DAYS: int = 3
|
||||
TRIAL_TRAFFIC_LIMIT_GB: int = 10
|
||||
@@ -414,6 +416,10 @@ class Settings(BaseSettings):
|
||||
"auth_type": self.REMNAWAVE_AUTH_TYPE
|
||||
}
|
||||
|
||||
def get_timezone(self) -> str:
|
||||
timezone_value = (self.TIMEZONE or "UTC").strip()
|
||||
return timezone_value or "UTC"
|
||||
|
||||
def get_pal24_sbp_button_text(self, fallback: str) -> str:
|
||||
value = (self.PAL24_SBP_BUTTON_TEXT or "").strip()
|
||||
return value or fallback
|
||||
|
||||
@@ -3,7 +3,8 @@ from contextlib import asynccontextmanager
|
||||
from typing import Dict, List, Any, Optional
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import delete
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from zoneinfo import ZoneInfo
|
||||
import re
|
||||
|
||||
from app.config import settings
|
||||
@@ -51,6 +52,8 @@ class RemnaWaveService:
|
||||
password=auth_params.get("password")
|
||||
)
|
||||
|
||||
self._timezone = self._resolve_timezone()
|
||||
|
||||
@property
|
||||
def is_configured(self) -> bool:
|
||||
return self._config_error is None
|
||||
@@ -72,33 +75,47 @@ class RemnaWaveService:
|
||||
async with self.api as api:
|
||||
yield api
|
||||
|
||||
def _parse_remnawave_date(self, date_str: str) -> datetime:
|
||||
if not date_str:
|
||||
return datetime.utcnow() + timedelta(days=30)
|
||||
|
||||
def _resolve_timezone(self) -> ZoneInfo:
|
||||
timezone_name = settings.get_timezone()
|
||||
try:
|
||||
|
||||
return ZoneInfo(timezone_name)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
f"⚠️ Не удалось загрузить временную зону '{timezone_name}', используется UTC"
|
||||
)
|
||||
return ZoneInfo("UTC")
|
||||
|
||||
def _parse_remnawave_date(self, date_str: str) -> datetime:
|
||||
target_timezone = self._timezone
|
||||
if not date_str:
|
||||
return (datetime.now(target_timezone) + timedelta(days=30)).replace(tzinfo=None)
|
||||
|
||||
try:
|
||||
|
||||
cleaned_date = date_str.strip()
|
||||
|
||||
|
||||
if cleaned_date.endswith('Z'):
|
||||
cleaned_date = cleaned_date[:-1] + '+00:00'
|
||||
|
||||
|
||||
if '+00:00+00:00' in cleaned_date:
|
||||
cleaned_date = cleaned_date.replace('+00:00+00:00', '+00:00')
|
||||
|
||||
|
||||
cleaned_date = re.sub(r'(\+\d{2}:\d{2})\+\d{2}:\d{2}$', r'\1', cleaned_date)
|
||||
|
||||
|
||||
parsed_date = datetime.fromisoformat(cleaned_date)
|
||||
|
||||
if parsed_date.tzinfo is not None:
|
||||
parsed_date = parsed_date.replace(tzinfo=None)
|
||||
|
||||
logger.debug(f"Успешно распарсена дата: {date_str} -> {parsed_date}")
|
||||
return parsed_date
|
||||
|
||||
|
||||
if parsed_date.tzinfo is None:
|
||||
parsed_date = parsed_date.replace(tzinfo=timezone.utc)
|
||||
|
||||
localized_date = parsed_date.astimezone(target_timezone)
|
||||
result = localized_date.replace(tzinfo=None)
|
||||
|
||||
logger.debug(f"Успешно распарсена дата: {date_str} -> {result}")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Не удалось распарсить дату '{date_str}': {e}. Используем дефолтную дату.")
|
||||
return datetime.utcnow() + timedelta(days=30)
|
||||
return (datetime.now(target_timezone) + timedelta(days=30)).replace(tzinfo=None)
|
||||
|
||||
async def get_system_statistics(self) -> Dict[str, Any]:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user