getInfo method

Future<LibrivoxItem> getInfo(
  1. String id
)

Implementation

Future<LibrivoxItem> getInfo(String id) async {
  String extractDescription(String? rawHtml) {
    if (rawHtml == null) {
      return '';
    }

    final document = html.parse(rawHtml);
    final text = document.body?.text ?? rawHtml;

    // Optionally trim boilerplate like "For further information..."
    final cutoffIndex = text.indexOf('For further information');
    return cutoffIndex > 0
        ? text.substring(0, cutoffIndex).trim()
        : text.trim();
  }

  if (id.trim().isEmpty) {
    throw ArgumentError('Identifier cannot be empty');
  }

  final uri = Uri.parse('https://archive.org/metadata/$id');

  final response = await http.get(uri);

  if (response.statusCode == 404) {
    throw LibrivoxNotFoundException('Item not found for id: $id');
  }

  if (response.statusCode != 200) {
    throw LibrivoxApiException(
      'Failed to fetch Librivox item. Status: ${response.statusCode}',
    );
  }

  final Map<String, dynamic> jsonMap;
  try {
    jsonMap = jsonDecode(response.body) as Map<String, dynamic>;
  } catch (e) {
    throw LibrivoxParseException('Failed to parse response: $e');
  }

  final metadata = jsonMap['metadata'] as Map<String, dynamic>?;
  final files = jsonMap['files'] as List<dynamic>?;

  if (metadata == null) {
    throw const LibrivoxParseException(
      'Invalid response: missing metadata field',
    );
  }

  final title = metadata['title'] as String?;
  final creator = metadata['creator'] as String?;
  final language = metadata['language'] as String?;

  final releaseDate = metadata['date'] as String?;
  final description = metadata['description'] as String?;

  if (title == null || title.isEmpty) {
    throw const LibrivoxParseException(
      'Missing or empty title in item metadata',
    );
  }

  // Pick first MP3/ZIP file link
  final List<String> downloadLinks = [];
  if (files != null) {
    for (final file in files) {
      final fileMap = file as Map<String, dynamic>;
      final name = fileMap['name'] as String?;
      if (name != null && (name.endsWith('.zip') || name.endsWith('.m4b'))) {
        downloadLinks.add('https://archive.org/download/$id/$name');
      }
    }
  }

  return LibrivoxItem(
    id: id,
    title: title,
    author: creator,
    releaseDate: releaseDate,
    description: extractDescription(description),
    language: language,
    coverUrl: 'https://archive.org/services/img/$id',
    downloadLinks: downloadLinks,
  );
}