Skip to content

Commit

Permalink
Mixed search implt. imports from spotify using CC
Browse files Browse the repository at this point in the history
  • Loading branch information
HemantKArya committed Apr 4, 2024
1 parent f3d4d94 commit d1be1e1
Show file tree
Hide file tree
Showing 21 changed files with 943 additions and 490 deletions.
156 changes: 63 additions & 93 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@ import 'dart:developer';
import 'dart:io' as io;
import 'package:Bloomee/blocs/internet_connectivity/cubit/connectivity_cubit.dart';
import 'package:Bloomee/blocs/settings_cubit/cubit/settings_cubit.dart';
import 'package:Bloomee/model/MediaPlaylistModel.dart';
import 'package:Bloomee/model/songModel.dart';
import 'package:Bloomee/model/youtube_vid_model.dart';
import 'package:Bloomee/repository/Youtube/youtube_api.dart';
import 'package:Bloomee/routes_and_consts/global_str_consts.dart';
import 'package:Bloomee/screens/widgets/snackbar.dart';
import 'package:Bloomee/theme_data/default.dart';
import 'package:Bloomee/utils/file_manager.dart';
import 'package:Bloomee/services/file_manager.dart';
import 'package:Bloomee/utils/external_list_importer.dart';
import 'package:Bloomee/utils/url_checker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:Bloomee/blocs/add_to_playlist/cubit/add_to_playlist_cubit.dart';
import 'package:Bloomee/blocs/library/cubit/library_items_cubit.dart';
import 'package:Bloomee/repository/Saavn/cubit/saavn_repository_cubit.dart';
import 'package:Bloomee/blocs/search/fetch_search_results.dart';
import 'package:Bloomee/routes_and_consts/routes.dart';
import 'package:Bloomee/screens/screen/library_views/cubit/current_playlist_cubit.dart';
Expand All @@ -26,62 +22,43 @@ import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'blocs/mediaPlayer/bloomee_player_cubit.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';

bool isYoutubeLink(String link) {
if (link.contains("youtube.com") || link.contains("youtu.be")) {
return true;
} else {
return false;
}
}

String? extractVideoId(String url) {
Uri uri = Uri.parse(url);

// Check if the URL is from youtube.com
if (uri.host == 'youtube.com') {
return uri.queryParameters['v']; // Retrieve video ID from query parameter
}

// Check if the URL is from youtu.be
if (uri.host == 'youtu.be') {
return uri.pathSegments.first; // Retrieve video ID from path
}

// Invalid URL format
return null;
}

void processIncomingIntent(List<SharedMediaFile> _sharedFiles) {
if (Uri.tryParse(_sharedFiles[0].path) != null &&
isYoutubeLink(_sharedFiles[0].path)) {
var _tempId = extractVideoId(_sharedFiles[0].path);
if (_tempId != null) {
log(extractVideoId(_sharedFiles[0].path).toString(),
name: "Shared Files");
var _tempVid = YouTubeServices().getVideoFromId(_tempId);
_tempVid.then((value) {
if (value != null) {
YouTubeServices()
.formatVideo(video: value, quality: "High")
.then((value) async {
if (value != null) {
MediaItemModel _mIM = fromYtVidSongMap2MediaItem(value);
MediaPlaylist _tempPlaylist = MediaPlaylist(
albumName: "Shared Playlist",
mediaItems: [_mIM],
);
log(_mIM.title, name: "Shared Files");
await bloomeePlayerCubit.bloomeePlayer
.loadPlaylist(_tempPlaylist, doPlay: true);
GlobalRoutes.globalRouter.pushNamed(GlobalStrConsts.playerScreen);
}
});
void processIncomingIntent(List<SharedMediaFile> sharedMediaFiles) {
if (isUrl(sharedMediaFiles[0].path)) {
final urlType = getUrlType(sharedMediaFiles[0].path);
switch (urlType) {
case UrlType.spotifyTrack:
ExternalMediaImporter.sfyMediaImporter(sharedMediaFiles[0].path)
.then((value) async {
if (value != null) {
await bloomeePlayerCubit.bloomeePlayer
.addQueueItem(value, doPlay: true);
}
});
break;
case UrlType.spotifyPlaylist:
SnackbarService.showMessage("Import Spotify Playlist from library!");
break;
case UrlType.youtubePlaylist:
SnackbarService.showMessage("Import Youtube Playlist from library!");
break;
case UrlType.youtubeVideo:
ExternalMediaImporter.ytMediaImporter(sharedMediaFiles[0].path)
.then((value) async {
if (value != null) {
await bloomeePlayerCubit.bloomeePlayer
.addQueueItem(value, doPlay: true);
}
});
break;
case UrlType.other:
if (sharedMediaFiles[0].mimeType == "application/octet-stream") {
SnackbarService.showMessage("Processing File...");
importItems(
Uri.parse(sharedMediaFiles[0].path).toFilePath().toString());
}
});
default:
log("Invalid URL");
}
} else if (_sharedFiles[0].mimeType == "application/octet-stream") {
SnackbarService.showMessage("Processing File...");
importItems(Uri.parse(_sharedFiles[0].path).toFilePath().toString());
}
}

Expand Down Expand Up @@ -135,30 +112,31 @@ class _MyAppState extends State<MyApp> {
// Initialize the player
// This widget is the root of your application.
late StreamSubscription _intentSub;
final _sharedFiles = <SharedMediaFile>[];
final sharedMediaFiles = <SharedMediaFile>[];
@override
void initState() {
super.initState();

// For sharing or opening urls/text coming from outside the app while the app is in the memory
_intentSub = ReceiveSharingIntent.getMediaStream().listen((event) {
_sharedFiles.clear();
_sharedFiles.addAll(event);
log(_sharedFiles[0].mimeType.toString(), name: "Shared Files");
log(_sharedFiles[0].path, name: "Shared Files");
processIncomingIntent(_sharedFiles);
sharedMediaFiles.clear();
sharedMediaFiles.addAll(event);
log(sharedMediaFiles[0].mimeType.toString(), name: "Shared Files");
log(sharedMediaFiles[0].path, name: "Shared Files");
processIncomingIntent(sharedMediaFiles);

// Tell the library that we are done processing the intent.
ReceiveSharingIntent.reset();
});

// For sharing or opening urls/text coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialMedia().then((event) {
_sharedFiles.clear();
_sharedFiles.addAll(event);
log(_sharedFiles[0].mimeType.toString(), name: "Shared Files Offline");
log(_sharedFiles[0].path, name: "Shared Files Offline");
processIncomingIntent(_sharedFiles);
sharedMediaFiles.clear();
sharedMediaFiles.addAll(event);
log(sharedMediaFiles[0].mimeType.toString(),
name: "Shared Files Offline");
log(sharedMediaFiles[0].path, name: "Shared Files Offline");
processIncomingIntent(sharedMediaFiles);
ReceiveSharingIntent.reset();
});
}
Expand Down Expand Up @@ -211,27 +189,19 @@ class _MyAppState extends State<MyApp> {
create: (context) => FetchSearchResultsCubit(),
),
],
child: MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => SaavnRepositoryCubit()),
RepositoryProvider(
create: (context) => SaavnSearchRepositoryCubit(),
),
],
child: BlocBuilder<BloomeePlayerCubit, BloomeePlayerState>(
builder: (context, state) {
if (state is BloomeePlayerInitial) {
return const SizedBox(
width: 50, height: 50, child: CircularProgressIndicator());
} else {
return MaterialApp.router(
scaffoldMessengerKey: SnackbarService.messengerKey,
routerConfig: GlobalRoutes.globalRouter,
theme: Default_Theme().defaultThemeData,
);
}
},
),
child: BlocBuilder<BloomeePlayerCubit, BloomeePlayerState>(
builder: (context, state) {
if (state is BloomeePlayerInitial) {
return const SizedBox(
width: 50, height: 50, child: CircularProgressIndicator());
} else {
return MaterialApp.router(
scaffoldMessengerKey: SnackbarService.messengerKey,
routerConfig: GlobalRoutes.globalRouter,
theme: Default_Theme().defaultThemeData,
);
}
},
),
);
}
Expand Down
59 changes: 59 additions & 0 deletions lib/repository/MixedAPI/mixed_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'dart:developer';

import 'package:Bloomee/model/saavnModel.dart';
import 'package:Bloomee/model/songModel.dart';
import 'package:Bloomee/model/yt_music_model.dart';
import 'package:Bloomee/repository/Saavn/saavn_api.dart';
import 'package:Bloomee/repository/Youtube/yt_music_api.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart' as fw;

class MixedAPI {
bool selectBestString(String source, String first, String second) {
final int a = fw.ratio(source, first);
final int b = fw.ratio(source, second);
log("Confidence for string-1($first): $a and string-2($second): $b",
name: "MixedAPI");
return (b > a) ? false : true;
}

Future<MediaItemModel?> getTrackMixed(String songName) async {
final ytItems = await YtMusicService().search(songName, filter: "songs");
// log(ytItems.toString());
final jsItems = await SaavnAPI()
.fetchSongSearchResults(searchQuery: songName, count: 2);
String? ytTitle;
String? jsTitle;
var jsItem;
var ytItem;
int idx = 0;
if (ytItems.isNotEmpty) {
ytItem = ytItems[0]["items"][0];

ytTitle = "${ytItem!['title']} ${ytItem['artist']}";
}
if (jsItems["songs"].isNotEmpty) {
List<String> titles = (jsItems['songs'] as List)
.map((e) => "${e['title']} ${e['artist']}")
.toList();
idx = fw.extractOne(query: songName, choices: titles).index;
// log("${jsItems.toString()}");
jsItem = jsItems['songs'][idx];
jsTitle = "${jsItem!['title']} ${jsItem['artist']}";
}
if (jsTitle != null && ytTitle != null) {
final slct = selectBestString(
songName, jsTitle.trim().toLowerCase(), ytTitle.trim().toLowerCase());
log(slct ? "$jsTitle from JIOSaavn" : "$ytTitle from Youtube",
name: "MixedAPI");
return slct
? fromSaavnSongMap2MediaItem(jsItem!)
: fromYtSongMap2MediaItem(ytItem!);
} else {
if (jsTitle != null) {
return fromSaavnSongMap2MediaItem(jsItem!);
} else {
return fromYtSongMap2MediaItem(ytItem!);
}
}
}
}
Loading

0 comments on commit d1be1e1

Please sign in to comment.