Add SearchClient, Closes #32
This commit is contained in:
parent
04be2cc0df
commit
6e4fe9d588
|
@ -42,9 +42,9 @@ class ChannelClient {
|
||||||
videoId = VideoId.fromString(videoId);
|
videoId = VideoId.fromString(videoId);
|
||||||
var videoInfoResponse =
|
var videoInfoResponse =
|
||||||
await VideoInfoResponse.get(_httpClient, videoId.value);
|
await VideoInfoResponse.get(_httpClient, videoId.value);
|
||||||
var playerReponse = videoInfoResponse.playerResponse;
|
var playerResponse = videoInfoResponse.playerResponse;
|
||||||
|
|
||||||
var channelId = playerReponse.videoChannelId;
|
var channelId = playerResponse.videoChannelId;
|
||||||
return await get(ChannelId(channelId));
|
return await get(ChannelId(channelId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import '../common/common.dart';
|
||||||
|
import '../reverse_engineering/responses/playerlist_response.dart';
|
||||||
|
import '../reverse_engineering/youtube_http_client.dart';
|
||||||
|
import '../videos/video.dart';
|
||||||
|
import '../videos/video_id.dart';
|
||||||
|
|
||||||
|
/// YouTube search queries.
|
||||||
|
class SearchClient {
|
||||||
|
final YoutubeHttpClient _httpClient;
|
||||||
|
|
||||||
|
/// Initializes an instance of [SearchClient]
|
||||||
|
SearchClient(this._httpClient);
|
||||||
|
|
||||||
|
/// Enumerates videos returned by the specified search query.
|
||||||
|
Stream<Video> getVideosAsync(String searchQuery) async* {
|
||||||
|
var encounteredVideoIds = <String>{};
|
||||||
|
|
||||||
|
for (var page = 0; page < double.maxFinite; page++) {
|
||||||
|
var response =
|
||||||
|
await PlaylistResponse.searchResults(_httpClient, searchQuery);
|
||||||
|
|
||||||
|
var countDelta = 0;
|
||||||
|
for (var video in response.videos) {
|
||||||
|
var videoId = video.id;
|
||||||
|
|
||||||
|
if (!encounteredVideoIds.add(videoId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield Video(
|
||||||
|
VideoId(videoId),
|
||||||
|
video.title,
|
||||||
|
video.author,
|
||||||
|
video.uploadDate,
|
||||||
|
video.description,
|
||||||
|
video.duration,
|
||||||
|
ThumbnailSet(videoId),
|
||||||
|
video.keywords,
|
||||||
|
Engagement(video.viewCount, video.likes, video.dislikes));
|
||||||
|
countDelta++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Videos loop around, so break when we stop seeing new videos
|
||||||
|
if (countDelta <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ library youtube_explode.base;
|
||||||
import 'channels/channels.dart';
|
import 'channels/channels.dart';
|
||||||
import 'playlists/playlist_client.dart';
|
import 'playlists/playlist_client.dart';
|
||||||
import 'reverse_engineering/youtube_http_client.dart';
|
import 'reverse_engineering/youtube_http_client.dart';
|
||||||
|
import 'search/search_client.dart';
|
||||||
import 'videos/video_client.dart';
|
import 'videos/video_client.dart';
|
||||||
|
|
||||||
/// Library entry point.
|
/// Library entry point.
|
||||||
|
@ -19,17 +20,20 @@ class YoutubeExplode {
|
||||||
ChannelClient get channels => _channels;
|
ChannelClient get channels => _channels;
|
||||||
|
|
||||||
/// YouTube search queries.
|
/// YouTube search queries.
|
||||||
//TODO: Add SearchClient
|
SearchClient get search => _search;
|
||||||
|
|
||||||
|
/// Initializes an instance of [YoutubeClient].
|
||||||
YoutubeExplode() : _httpClient = YoutubeHttpClient() {
|
YoutubeExplode() : _httpClient = YoutubeHttpClient() {
|
||||||
_videos = VideoClient(_httpClient);
|
_videos = VideoClient(_httpClient);
|
||||||
_playlists = PlaylistClient(_httpClient);
|
_playlists = PlaylistClient(_httpClient);
|
||||||
_channels = ChannelClient(_httpClient);
|
_channels = ChannelClient(_httpClient);
|
||||||
|
_search = SearchClient(_httpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoClient _videos;
|
VideoClient _videos;
|
||||||
PlaylistClient _playlists;
|
PlaylistClient _playlists;
|
||||||
ChannelClient _channels;
|
ChannelClient _channels;
|
||||||
|
SearchClient _search;
|
||||||
|
|
||||||
/// Closes the HttpClient assigned to this [YoutubeHttpClient].
|
/// Closes the HttpClient assigned to this [YoutubeHttpClient].
|
||||||
/// Should be called after this is not used anymore.
|
/// Should be called after this is not used anymore.
|
||||||
|
|
|
@ -4,5 +4,6 @@ export 'src/channels/channels.dart';
|
||||||
export 'src/common/common.dart';
|
export 'src/common/common.dart';
|
||||||
export 'src/exceptions/exceptions.dart';
|
export 'src/exceptions/exceptions.dart';
|
||||||
export 'src/playlists/playlists.dart';
|
export 'src/playlists/playlists.dart';
|
||||||
|
export 'src/search/search_client.dart';
|
||||||
export 'src/videos/videos.dart';
|
export 'src/videos/videos.dart';
|
||||||
export 'src/youtube_explode_base.dart';
|
export 'src/youtube_explode_base.dart';
|
||||||
|
|
|
@ -1 +1,22 @@
|
||||||
//TODO: Implement this
|
import 'package:test/test.dart';
|
||||||
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('Search', () {
|
||||||
|
YoutubeExplode yt;
|
||||||
|
setUp(() {
|
||||||
|
yt = YoutubeExplode();
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() {
|
||||||
|
yt.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SearchYouTubeVideos', () async {
|
||||||
|
var videos = await yt.search
|
||||||
|
.getVideosAsync('undead corporation megalomania')
|
||||||
|
.toList();
|
||||||
|
expect(videos, isNotEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue