yumi-flutter/lib/shared/tools/sc_install_referrer_utils.dart
2026-05-09 18:31:48 +08:00

129 lines
3.3 KiB
Dart

import 'dart:io';
import 'package:flutter/services.dart';
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
class SCInstallReferrerUtils {
static const MethodChannel _channel = MethodChannel(
'com.org.yumiparty/install_referrer',
);
static const String _cachedInviteCodeKey = 'install_referrer_invite_code';
static const String _cachedRawReferrerKey = 'install_referrer_raw';
static Future<String> getInviteCode() async {
final cachedInviteCode = DataPersistence.getString(_cachedInviteCodeKey);
if (cachedInviteCode.isNotEmpty) {
return cachedInviteCode;
}
final cachedRawReferrer = DataPersistence.getString(_cachedRawReferrerKey);
if (cachedRawReferrer.isNotEmpty) {
return extractInviteCode(cachedRawReferrer);
}
if (!Platform.isAndroid) {
return '';
}
try {
final referrer = await _channel.invokeMethod<String>(
'getInstallReferrer',
);
if (referrer == null || referrer.trim().isEmpty) {
return '';
}
await DataPersistence.setString(_cachedRawReferrerKey, referrer);
final inviteCode = extractInviteCode(referrer);
if (inviteCode.isNotEmpty) {
await DataPersistence.setString(_cachedInviteCodeKey, inviteCode);
}
return inviteCode;
} on PlatformException catch (e) {
return '';
} catch (e) {
return '';
}
}
static String extractInviteCode(String referrer) {
return _extractInviteCode(referrer, 0);
}
static String _extractInviteCode(String input, int depth) {
if (depth > 4) {
return '';
}
final value = input.trim();
if (value.isEmpty) {
return '';
}
final params = _queryParameters(value);
final inviteCode = _inviteCodeFromParams(params);
if (inviteCode.isNotEmpty) {
return inviteCode;
}
final nestedReferrer = _nestedReferrerFromParams(params);
if (nestedReferrer != null && nestedReferrer.isNotEmpty) {
final nestedInviteCode = _extractInviteCode(nestedReferrer, depth + 1);
if (nestedInviteCode.isNotEmpty) {
return nestedInviteCode;
}
}
final decodedValue = _decodeComponent(value);
if (decodedValue != value) {
return _extractInviteCode(decodedValue, depth + 1);
}
return '';
}
static Map<String, String> _queryParameters(String value) {
final uri = Uri.tryParse(value);
if (uri != null && uri.hasQuery) {
return uri.queryParameters;
}
if (!value.contains('=')) {
return const {};
}
try {
return Uri.splitQueryString(value);
} catch (_) {
return const {};
}
}
static String _inviteCodeFromParams(Map<String, String> params) {
for (final entry in params.entries) {
final key = entry.key.toLowerCase();
if (key == 'invite_code' || key == 'invitecode') {
return entry.value.trim();
}
}
return '';
}
static String? _nestedReferrerFromParams(Map<String, String> params) {
for (final entry in params.entries) {
if (entry.key.toLowerCase() == 'referrer') {
return entry.value;
}
}
return null;
}
static String _decodeComponent(String value) {
try {
return Uri.decodeComponent(value);
} catch (_) {
return value;
}
}
}