Skip to content

Commit

Permalink
fix: non-banger songs breaking the queue if sources not found
Browse files Browse the repository at this point in the history
Now fallbacks to another audio source if not found in one
  • Loading branch information
KRTirtho committed Feb 17, 2024
1 parent cd669e2 commit 90f7c53
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 18 deletions.
3 changes: 1 addition & 2 deletions lib/provider/proxy_playlist/proxy_playlist_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
}
} catch (e, stackTrace) {
// Removing tracks that were not found to avoid queue interruption
// TODO: Add a flag to enable/disable skip not found tracks
if (e is TrackNotFoundException) {
if (e is TrackNotFoundError) {
final oldTrack =
mapSourcesToTracks([audioPlayer.nextSource!]).firstOrNull;
await removeTrack(oldTrack!.id!);
Expand Down
11 changes: 8 additions & 3 deletions lib/services/sourced_track/exceptions.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import 'package:spotify/spotify.dart';

class TrackNotFoundException implements Exception {
factory TrackNotFoundException(Track track) {
throw Exception("Failed to find any results for ${track.name}");
class TrackNotFoundError extends Error {
final Track track;

TrackNotFoundError(this.track);

@override
String toString() {
return '[TrackNotFoundError] ${track.name} - ${track.artists?.map((e) => e.name).join(", ")}';
}
}
38 changes: 35 additions & 3 deletions lib/services/sourced_track/sourced_track.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import 'dart:io';

import 'package:http/http.dart';
import 'package:collection/collection.dart';
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
import 'package:spotube/services/sourced_track/enums.dart';
import 'package:spotube/services/sourced_track/exceptions.dart';
import 'package:spotube/services/sourced_track/models/source_info.dart';
import 'package:spotube/services/sourced_track/models/source_map.dart';
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
import 'package:spotube/services/sourced_track/sources/piped.dart';
import 'package:spotube/services/sourced_track/sources/youtube.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';

abstract class SourcedTrack extends Track {
final SourceMap source;
Expand Down Expand Up @@ -101,9 +107,8 @@ abstract class SourcedTrack extends Track {
required Track track,
required Ref ref,
}) async {
final preferences = ref.read(userPreferencesProvider);
try {
final preferences = ref.read(userPreferencesProvider);

return switch (preferences.audioSource) {
AudioSource.piped =>
await PipedSourcedTrack.fetchFromTrack(track: track, ref: ref),
Expand All @@ -112,8 +117,35 @@ abstract class SourcedTrack extends Track {
AudioSource.jiosaavn =>
await JioSaavnSourcedTrack.fetchFromTrack(track: track, ref: ref),
};
} on TrackNotFoundError catch (_) {
return switch (preferences.audioSource) {
AudioSource.piped ||
AudioSource.youtube =>
await JioSaavnSourcedTrack.fetchFromTrack(
track: track,
ref: ref,
weakMatch: true,
),
AudioSource.jiosaavn =>
await PipedSourcedTrack.fetchFromTrack(track: track, ref: ref),
};
} on HttpClientClosedException catch (_) {
return await PipedSourcedTrack.fetchFromTrack(track: track, ref: ref);
} catch (e) {
return YoutubeSourcedTrack.fetchFromTrack(track: track, ref: ref);
if (e is DioException || e is ClientException || e is SocketException) {
if (preferences.audioSource == AudioSource.jiosaavn) {
return await JioSaavnSourcedTrack.fetchFromTrack(
track: track,
ref: ref,
weakMatch: true,
);
}
return await JioSaavnSourcedTrack.fetchFromTrack(
track: track,
ref: ref,
);
}
rethrow;
}
}

Expand Down
27 changes: 24 additions & 3 deletions lib/services/sourced_track/sources/jiosaavn.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,17 @@ class JioSaavnSourcedTrack extends SourcedTrack {
static Future<SourcedTrack> fetchFromTrack({
required Track track,
required Ref ref,
bool weakMatch = false,
}) async {
final cachedSource = await SourceMatch.box.get(track.id);

if (cachedSource == null ||
cachedSource.sourceType != SourceType.jiosaavn) {
final siblings = await fetchSiblings(ref: ref, track: track);
final siblings =
await fetchSiblings(ref: ref, track: track, weakMatch: weakMatch);

if (siblings.isEmpty) {
throw TrackNotFoundException(track);
throw TrackNotFoundError(track);
}

await SourceMatch.box.put(
Expand Down Expand Up @@ -119,16 +121,20 @@ class JioSaavnSourcedTrack extends SourcedTrack {
static Future<List<SiblingType>> fetchSiblings({
required Track track,
required Ref ref,
bool weakMatch = false,
}) async {
final query = SourcedTrack.getSearchTerm(track);

final SongSearchResponse(:results) =
await jiosaavnClient.search.songs(query, limit: 20);

final trackArtistNames = track.artists?.map((ar) => ar.name).toList();
return results

final matchedResults = results
.where(
(s) {
s.name?.unescapeHtml().contains(track.name!) ?? false;

final sameName = s.name?.unescapeHtml() == track.name;
final artistNames = [
s.primaryArtists,
Expand All @@ -139,12 +145,27 @@ class JioSaavnSourcedTrack extends SourcedTrack {
(artist) =>
trackArtistNames?.any((ar) => artist == ar) ?? false,
);
if (weakMatch) {
final containsName =
s.name?.unescapeHtml().contains(track.name!) ?? false;
final containsPrimaryArtist = s.primaryArtists
.unescapeHtml()
.contains(trackArtistNames?.first ?? "");

return containsName && containsPrimaryArtist;
}

return sameName && sameArtists;
},
)
.map(toSiblingType)
.toList();

if (weakMatch && matchedResults.isEmpty) {
return results.map(toSiblingType).toList();
}

return matchedResults;
}

@override
Expand Down
9 changes: 6 additions & 3 deletions lib/services/sourced_track/sources/piped.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class PipedSourcedTrack extends SourcedTrack {
if (cachedSource == null) {
final siblings = await fetchSiblings(ref: ref, track: track);
if (siblings.isEmpty) {
throw TrackNotFoundException(track);
throw TrackNotFoundError(track);
}

await SourceMatch.box.put(
Expand Down Expand Up @@ -160,13 +160,16 @@ class PipedSourcedTrack extends SourcedTrack {
final query = SourcedTrack.getSearchTerm(track);

final PipedSearchResult(items: searchResults) = await pipedClient.search(
"$query - Topic",
query,
preference.searchMode == SearchMode.youtube
? PipedFilter.video
: PipedFilter.musicSongs,
);

final isYouTubeMusic = preference.searchMode == SearchMode.youtubeMusic;
// when falling back to piped API make sure to use the YouTube mode
final isYouTubeMusic = preference.audioSource != AudioSource.piped
? false
: preference.searchMode == SearchMode.youtubeMusic;

if (isYouTubeMusic) {
final artists = (track.artists ?? [])
Expand Down
2 changes: 1 addition & 1 deletion lib/services/sourced_track/sources/youtube.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
if (cachedSource == null || cachedSource.sourceType != SourceType.youtube) {
final siblings = await fetchSiblings(ref: ref, track: track);
if (siblings.isEmpty) {
throw TrackNotFoundException(track);
throw TrackNotFoundError(track);
}

await SourceMatch.box.put(
Expand Down
4 changes: 2 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1619,10 +1619,10 @@ packages:
dependency: "direct main"
description:
name: piped_client
sha256: "8b96e1f9d8533c1da7eff7fbbd4bf188256fc76a20900d378b52be09418ea771"
sha256: "87b04b2ebf4e008cfbb0ac85e9920ab3741f5aa697be2dd44919658a3297a4bc"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
version: "0.1.1"
platform:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ dependencies:
path: ^1.8.0
path_provider: ^2.0.8
permission_handler: ^11.0.1
piped_client: ^0.1.0
piped_client: ^0.1.1
popover: ^0.2.6+3
scrobblenaut:
git:
Expand Down
1 change: 1 addition & 0 deletions untranslated_messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
],

"nl": [
"audio_source",
"start_a_radio",
"how_to_start_radio",
"replace_queue_question",
Expand Down

0 comments on commit 90f7c53

Please sign in to comment.