309 lines
10 KiB
Dart
309 lines
10 KiB
Dart
import 'dart:io';
|
||
import 'dart:convert';
|
||
import 'package:dio/dio.dart';
|
||
import 'package:dio/io.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
import '../model/response/kr_site_config.dart';
|
||
import '../common/app_config.dart';
|
||
import '../utils/kr_log_util.dart';
|
||
import '../utils/kr_http_adapter_util.dart';
|
||
import 'singbox_imp/kr_sing_box_imp.dart';
|
||
import 'api_service/kr_api.user.dart';
|
||
|
||
/// 网站配置服务
|
||
class KRSiteConfigService extends ChangeNotifier {
|
||
static final KRSiteConfigService _instance = KRSiteConfigService._internal();
|
||
factory KRSiteConfigService() => _instance;
|
||
KRSiteConfigService._internal() {
|
||
// 🔧 Android 15 优化:增加超时时间以适应移动网络(5秒 → 20秒)
|
||
_dio.options.connectTimeout = const Duration(seconds: 20);
|
||
_dio.options.sendTimeout = const Duration(seconds: 20);
|
||
_dio.options.receiveTimeout = const Duration(seconds: 20);
|
||
|
||
// 🔧 关键修复:添加 SSL 证书验证跳过,强制直连
|
||
_dio.httpClientAdapter = KRHttpAdapterUtil.createAdapter(
|
||
useSingBoxProxy: false,
|
||
forceDirect: true,
|
||
timeout: const Duration(seconds: 20),
|
||
);
|
||
|
||
if (kDebugMode) {
|
||
print('🌐 网站配置服务:使用直连模式,避免 SingBox 未初始化问题');
|
||
}
|
||
}
|
||
|
||
KRSiteConfig? _siteConfig;
|
||
bool _isInitialized = false;
|
||
final Dio _dio = Dio();
|
||
|
||
/// 获取站点配置
|
||
KRSiteConfig? get siteConfig => _siteConfig;
|
||
|
||
/// 是否已初始化
|
||
bool get isInitialized => _isInitialized;
|
||
|
||
Future<bool> initialize() async {
|
||
return await initializeDomains();
|
||
}
|
||
|
||
Future<bool> initializeDomains() async {
|
||
try {
|
||
await KRDomain.kr_loadBaseDomain();
|
||
_isInitialized = true;
|
||
notifyListeners();
|
||
return true;
|
||
} catch (_) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
Future<bool> fetchSiteConfig() async {
|
||
try {
|
||
final result = await KRUserApi().kr_config();
|
||
return await result.fold(
|
||
(error) async {
|
||
return false;
|
||
},
|
||
(cfg) async {
|
||
try {
|
||
if (cfg.kr_config.isNotEmpty) {
|
||
final Map<String, dynamic> root = jsonDecode(cfg.kr_config);
|
||
_siteConfig = KRSiteConfig.fromJson(root);
|
||
AppConfig.getInstance().device_limit = getDeviceLimit();
|
||
notifyListeners();
|
||
return true;
|
||
}
|
||
} catch (_) {}
|
||
return false;
|
||
},
|
||
);
|
||
} catch (_) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// 打印配置信息
|
||
void _printConfigInfo() {
|
||
if (_siteConfig == null) return;
|
||
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('📊 网站配置信息:', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// 站点信息
|
||
KRLogUtil.kr_i('🏠 站点名称: ${_siteConfig!.site.siteName}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('🏠 站点描述: ${_siteConfig!.site.siteDesc}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('🏠 站点域名: ${_siteConfig!.site.host}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('💬 Crisp ID: ${_siteConfig!.site.crispId}',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// 注册相关
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('📝 注册配置:', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 开放注册: ${isRegisterEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 手机号注册: ${isMobileRegisterEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 邮箱注册: ${isEmailRegisterEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 设备登录: ${isDeviceLoginEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// 验证相关
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('🔐 验证配置:', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 邮箱验证: ${isEmailVerificationEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 手机验证: ${isMobileVerificationEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 登录验证: ${isLoginVerificationEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 注册验证: ${isRegisterVerificationEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(
|
||
' ✓ 重置密码验证: ${isResetPasswordVerificationEnabled() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// 邀请相关
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('🎁 邀请配置:', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 强制邀请码: ${isForcedInvite() ? "是" : "否"}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 推荐比例: ${_siteConfig!.invite.referralPercentage}%',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// 货币相关
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('💰 货币配置:', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 货币单位: ${_siteConfig!.currency.currencyUnit}',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i(' ✓ 货币符号: ${_siteConfig!.currency.currencySymbol}',
|
||
tag: 'KRSiteConfigService');
|
||
|
||
// OAuth 方法
|
||
if (_siteConfig!.oauthMethods.isNotEmpty) {
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('🔑 OAuth 方法: ${_siteConfig!.oauthMethods.join(", ")}',
|
||
tag: 'KRSiteConfigService');
|
||
}
|
||
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('✅ 网站配置初始化成功', tag: 'KRSiteConfigService');
|
||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
||
tag: 'KRSiteConfigService');
|
||
}
|
||
|
||
/// 是否开启手机号注册
|
||
bool isMobileRegisterEnabled() {
|
||
return _siteConfig?.auth.mobile.enable ?? false;
|
||
}
|
||
|
||
/// 是否开启邮箱注册
|
||
bool isEmailRegisterEnabled() {
|
||
return _siteConfig?.auth.email.enable ?? false;
|
||
}
|
||
|
||
/// 是否开放注册(未停止注册)
|
||
bool isRegisterEnabled() {
|
||
return !(_siteConfig?.auth.register.stopRegister ?? true);
|
||
}
|
||
|
||
/// 是否开启邮箱验证
|
||
bool isEmailVerificationEnabled() {
|
||
return _siteConfig?.auth.email.enableVerify ?? false;
|
||
}
|
||
|
||
/// 是否开启手机验证
|
||
bool isMobileVerificationEnabled() {
|
||
return _siteConfig?.auth.mobile.enable ?? false;
|
||
}
|
||
|
||
/// 是否开启登录验证
|
||
bool isLoginVerificationEnabled() {
|
||
return _siteConfig?.verify.enableLoginVerify ?? false;
|
||
}
|
||
|
||
/// 是否开启注册验证
|
||
bool isRegisterVerificationEnabled() {
|
||
return _siteConfig?.verify.enableRegisterVerify ?? false;
|
||
}
|
||
|
||
/// 是否开启重置密码验证
|
||
bool isResetPasswordVerificationEnabled() {
|
||
return _siteConfig?.verify.enableResetPasswordVerify ?? false;
|
||
}
|
||
|
||
/// 是否强制邀请码
|
||
bool isForcedInvite() {
|
||
return _siteConfig?.invite.forcedInvite ?? false;
|
||
}
|
||
|
||
/// 获取验证码间隔时间(秒)
|
||
int getVerifyCodeInterval() {
|
||
return _siteConfig?.verifyCode.verifyCodeInterval ?? 60;
|
||
}
|
||
|
||
/// 获取OAuth方法列表
|
||
List<String> getOAuthMethods() {
|
||
return _siteConfig?.oauthMethods ?? [];
|
||
}
|
||
|
||
/// 检查是否支持设备模式(匿名游客模式)
|
||
bool isDeviceModeSupported() {
|
||
final oauthMethods = getOAuthMethods();
|
||
return oauthMethods.contains('device');
|
||
}
|
||
|
||
/// 检查是否启用设备登录
|
||
bool isDeviceLoginEnabled() {
|
||
return _siteConfig?.auth.device.enable ?? false;
|
||
}
|
||
|
||
/// 检查是否需要设备安全加密
|
||
bool isDeviceSecurityEnabled() {
|
||
return _siteConfig?.auth.device.enableSecurity ?? false;
|
||
}
|
||
|
||
/// 检查是否显示广告
|
||
bool isDeviceShowAds() {
|
||
return _siteConfig?.auth.device.showAds ?? false;
|
||
}
|
||
|
||
/// 检查是否只允许真实设备
|
||
bool isOnlyRealDevice() {
|
||
return _siteConfig?.auth.device.onlyRealDevice ?? false;
|
||
}
|
||
|
||
/// 获取站点信息
|
||
KRSiteInfo? getSiteInfo() {
|
||
return _siteConfig?.site;
|
||
}
|
||
|
||
/// 获取货币配置
|
||
KRCurrencyConfig? getCurrencyConfig() {
|
||
return _siteConfig?.currency;
|
||
}
|
||
|
||
/// 获取订阅配置
|
||
KRSubscribeConfig? getSubscribeConfig() {
|
||
return _siteConfig?.subscribe;
|
||
}
|
||
|
||
/// 检查手机号是否在白名单中
|
||
bool isMobileInWhitelist(String mobile) {
|
||
if (!(_siteConfig?.auth.mobile.enableWhitelist ?? false)) {
|
||
return true; // 如果未开启白名单,则允许所有手机号
|
||
}
|
||
|
||
final whitelist = _siteConfig?.auth.mobile.whitelist ?? [];
|
||
return whitelist.contains(mobile);
|
||
}
|
||
|
||
/// 检查邮箱域名是否被允许
|
||
bool isEmailDomainAllowed(String email) {
|
||
if (!(_siteConfig?.auth.email.enableDomainSuffix ?? false)) {
|
||
return true; // 如果未开启域名限制,则允许所有域名
|
||
}
|
||
|
||
final domainSuffixList = _siteConfig?.auth.email.domainSuffixList ?? '';
|
||
if (domainSuffixList.isEmpty) {
|
||
return true;
|
||
}
|
||
|
||
final allowedDomains =
|
||
domainSuffixList.split(',').map((d) => d.trim()).toList();
|
||
final emailDomain = email.split('@').last.toLowerCase();
|
||
|
||
return allowedDomains
|
||
.any((domain) => emailDomain.endsWith(domain.toLowerCase()));
|
||
}
|
||
|
||
/// 获取Crisp客服系统ID
|
||
String getCrispId() {
|
||
return _siteConfig?.site.crispId ?? '0';
|
||
}
|
||
|
||
/// 获取设备限制
|
||
String getDeviceLimit() {
|
||
return _siteConfig?.site.deviceLimit ?? '0';
|
||
}
|
||
|
||
/// 重置配置
|
||
void reset() {
|
||
_siteConfig = null;
|
||
_isInitialized = false;
|
||
notifyListeners();
|
||
}
|
||
}
|