81 lines
2.3 KiB
Dart
81 lines
2.3 KiB
Dart
enum MaxLinkKind { call, invite, user, content, public, auth, stickerSet }
|
|
|
|
class MaxLink {
|
|
final MaxLinkKind kind;
|
|
final String url;
|
|
final String baseUrl;
|
|
final String? startPayload;
|
|
|
|
const MaxLink(this.kind, this.url, {String? baseUrl, this.startPayload})
|
|
: baseUrl = baseUrl ?? url;
|
|
|
|
static final RegExp _host = RegExp(
|
|
r'^https?://(?:www\.)?max\.ru/(.+)$',
|
|
caseSensitive: false,
|
|
);
|
|
|
|
static final RegExp _segment = RegExp(r'^[A-Za-z0-9_]+$');
|
|
|
|
static const Set<String> _reserved = {
|
|
'join',
|
|
'joincall',
|
|
'u',
|
|
'c',
|
|
'login',
|
|
'ps',
|
|
'tos',
|
|
'privacy',
|
|
'about',
|
|
'help',
|
|
};
|
|
|
|
static bool isMaxLink(String url) => parse(url) != null;
|
|
|
|
static MaxLink? parse(String input) {
|
|
final url = input.trim();
|
|
final match = _host.firstMatch(url);
|
|
if (match == null) return null;
|
|
|
|
final rest = match.group(1)!;
|
|
final path = rest.split('?').first.split('#').first;
|
|
final segments = path
|
|
.split('/')
|
|
.where((s) => s.isNotEmpty)
|
|
.toList(growable: false);
|
|
if (segments.isEmpty) return null;
|
|
|
|
switch (segments.first.toLowerCase()) {
|
|
case ':auth':
|
|
return segments.length >= 2 ? MaxLink(MaxLinkKind.auth, url) : null;
|
|
case 'joincall':
|
|
return segments.length >= 2 ? MaxLink(MaxLinkKind.call, url) : null;
|
|
case 'join':
|
|
return segments.length >= 2 ? MaxLink(MaxLinkKind.invite, url) : null;
|
|
case 'u':
|
|
return segments.length >= 2 ? MaxLink(MaxLinkKind.user, url) : null;
|
|
case 'c':
|
|
return segments.length >= 3 ? MaxLink(MaxLinkKind.content, url) : null;
|
|
case 'stickerset':
|
|
return segments.length >= 2
|
|
? MaxLink(MaxLinkKind.stickerSet, url)
|
|
: null;
|
|
}
|
|
|
|
if (_reserved.contains(segments.first.toLowerCase())) return null;
|
|
if (!_segment.hasMatch(segments.first)) return null;
|
|
return MaxLink(
|
|
MaxLinkKind.public,
|
|
url,
|
|
baseUrl: 'https://max.ru/${segments.join('/')}',
|
|
startPayload: _startPayload(rest),
|
|
);
|
|
}
|
|
|
|
static String? _startPayload(String rest) {
|
|
final parts = rest.split('#').first.split('?');
|
|
if (parts.length < 2) return null;
|
|
final value = Uri.splitQueryString(parts[1])['start']?.trim();
|
|
return (value == null || value.isEmpty) ? null : value;
|
|
}
|
|
}
|