solveBulk method
Future<Map<String, String?> >
solveBulk(
- String playerUrl,
- Map<
JSChallengeType, List< requestsString> >
override
Solves JavaScript challenges in bulk.
The requests parameter is a map where the key is the type of challenge
and the value is a list of challenge strings to be solved.
Returns a map where each challenge string maps to its solved result or null if unsolved.
Implementation
@override
Future<Map<String, String?>> solveBulk(
String playerUrl, Map<JSChallengeType, List<String>> requests) async {
// Filter out already cached challenges
final uncachedRequests = <JSChallengeType, List<String>>{};
final cachedResults = <String, String?>{};
for (final entry in requests.entries) {
final type = entry.key;
final challenges = entry.value;
final uncached = <String>[];
for (final challenge in challenges) {
final key = (playerUrl, challenge, type);
if (_sigCache.containsKey(key)) {
cachedResults[challenge] = _sigCache[key]!;
} else {
uncached.add(challenge);
}
}
if (uncached.isNotEmpty) {
uncachedRequests[type] = uncached;
}
}
// If all challenges are cached, return early
if (uncachedRequests.isEmpty) {
return cachedResults;
}
// Get player script (from cache or fetch)
late String playerScript;
var isPreprocessed = false;
if (_preprocPlayer.containsKey(playerUrl)) {
playerScript = _preprocPlayer[playerUrl]!;
isPreprocessed = true;
} else if (_playerCache.containsKey(playerUrl)) {
playerScript = _playerCache[playerUrl]!;
} else {
final resp = await http.get(Uri.parse(playerUrl));
playerScript = _playerCache[playerUrl] = resp.body;
}
final jsCall = EJSBuilder.buildJSCall(playerScript, uncachedRequests,
isPreprocessed: isPreprocessed);
final resultJson = await executeJavaScript(jsCall);
final data = json.decode(resultJson) as Map<String, dynamic>;
if (data['type'] != 'result') {
throw Exception('Unexpected response type: ${data['type']}');
}
// Store preprocessed player if available
if (data['preprocessed_player'] != null) {
_preprocPlayer[playerUrl] = data['preprocessed_player'] as String;
}
// Process all responses
final responses = data['responses'] as List;
for (final response in responses) {
if (response['type'] != 'result') {
throw Exception('Unexpected item response type: ${response['type']}');
}
final responseData = response['data'] as Map<String, dynamic>;
for (final entry in responseData.entries) {
final challenge = entry.key;
final decoded = entry.value as String?;
// Find the type for this challenge
JSChallengeType? challengeType;
for (final typeEntry in uncachedRequests.entries) {
if (typeEntry.value.contains(challenge)) {
challengeType = typeEntry.key;
break;
}
}
if (challengeType != null) {
final key = (playerUrl, challenge, challengeType);
if (decoded != null) {
_sigCache[key] = decoded;
cachedResults[challenge] = decoded;
} else {
cachedResults[challenge] = null;
}
}
}
}
return cachedResults;
}