132 lines
3.4 KiB
Dart
132 lines
3.4 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
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) {
|
|
debugPrint('get install referrer failed: ${e.code} ${e.message}');
|
|
return '';
|
|
} catch (e) {
|
|
debugPrint('get install referrer failed: $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;
|
|
}
|
|
}
|
|
}
|