searchComments method Null safety

  1. @override
Future<VideoWithCommentsList> searchComments(
  1. {required String comment,
  2. SearchSort searchSort = SearchSort.newest,
  3. List<Language>? languages,
  4. List<SearchTarget>? searchTargets,
  5. List<String>? topics,
  6. List<String>? videoChannels,
  7. List<String>? organizations,
  8. bool paginated = true,
  9. int offset = 0,
  10. int limit = 25}
)

Flexible endpoint to search for comments in videos fufilling multiple conditions.

Descriptions with "any" implies an OR condition, and "all" implies a AND condition.

Searching for topics and clips is not supported, because clips do not contain topics

Arguments

  • searchSort Sort by newest or oldest
  • languages If set, will filter clips to only show clips with these languages + all vtuber streams (provided searchTargets is not set to filter out streams)
  • searchTargets Target types of videos
  • comment Find videos with comments containing specified string (case insensitive)
  • topics Return videos that match one of the provided topics
  • vch Videos with all of the specified channel ids. If two or more channel IDs are specified, will only return their collabs, or if one channel is a clipper, it will only show clips of the other vtubers made by this clipper.
  • organizations Videos of channels in any of the specified organizations, or clips that involve a channel in the specified organization.
  • paginated If paginated is set to true, returns VideoWithCommentsList with total, otherwise returns VideoWithCommentsList without the total.
  • offset Offset results
  • limit Result limit

Implementation

@override
Future<VideoWithCommentsList> searchComments({
  required String comment,
  SearchSort searchSort = SearchSort.newest,
  List<Language>? languages,
  List<SearchTarget>? searchTargets,
  List<String>? topics,
  List<String>? videoChannels,
  List<String>? organizations,
  bool paginated = true,
  int offset = 0,
  int limit = 25,
}) async {
  final Map<String, dynamic> data = {};

  data.addAll({
    'sort': EnumUtil.convertSearchSortToString(searchSort),
    'comment': comment,
    'offset': offset,
    'limit': limit,
  });

  if (organizations != null && organizations.isNotEmpty) {
    data.addAll({
      'org': organizations,
    });
  }

  if (paginated) {
    data.addAll({
      'paginated': paginated,
    });
  }

  if (languages != null && languages.isNotEmpty) {
    data.addAll({
      'lang':
          languages.map((l) => EnumUtil.convertLanguageToString(l)).toList(),
    });
  }

  if (searchTargets != null && searchTargets.isNotEmpty) {
    data.addAll({
      'target': searchTargets
          .map((s) => EnumUtil.convertSearchTargetToString(s))
          .toList(),
    });
  }

  if (topics != null && topics.isNotEmpty) {
    data.addAll({
      'topic': topics,
    });
  }

  if (videoChannels != null && videoChannels.isNotEmpty) {
    data.addAll({
      'vch': videoChannels,
    });
  }

  final response = await post(path: _Constants.commentSearch, data: data);

  if (paginated) {
    // Grab total and return with it
    final videoList = VideoWithCommentsList.fromJson(response.body);
    return videoList.copyWith(paginated: true);
  }

  final List list = jsonDecode(response.body);
  return VideoWithCommentsList(
      videos: list.map((video) => VideoWithComments.fromMap(video)).toList());
}