class NewsArticle { final String id; final String title; final String content; final String? imageUrl; final String source; final String sourceUrl; final DateTime publishedAt; final List categories; final String? sentiment; NewsArticle({ required this.id, required this.title, required this.content, this.imageUrl, required this.source, required this.sourceUrl, required this.publishedAt, this.categories = const [], this.sentiment, }); factory NewsArticle.fromApiResponse(Map map) { // Handle the APITube.io response format return NewsArticle( id: map['id'] ?? map['uuid'] ?? DateTime.now().millisecondsSinceEpoch.toString(), title: map['title'] ?? 'Untitled', content: map['content'] ?? map['description'] ?? '', imageUrl: map['image_url'] ?? map['imageUrl'], source: map['source'] ?? map['publisher'] ?? 'Unknown Source', sourceUrl: map['url'] ?? map['sourceUrl'] ?? '', publishedAt: map['published_at'] != null ? DateTime.parse(map['published_at']) : (map['publishedAt'] != null ? DateTime.parse(map['publishedAt']) : DateTime.now()), categories: map['categories'] != null ? List.from(map['categories']) : [], sentiment: map['sentiment'], ); } // Get a short preview of the content String get contentPreview { if (content.isEmpty) { return 'No content available'; } else if (content.length > 100) { return '${content.substring(0, 100)}...'; } else { return content; } } }