mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00

Download track feature complete support in Android Android sudden solid color screen inno-script updated for permission_handler gensums updated for support for android apk updated description of Spotube in every file changes added to CHANGELOG
111 lines
3.1 KiB
Dart
111 lines
3.1 KiB
Dart
import 'dart:convert';
|
|
import 'package:html/parser.dart' as parser;
|
|
import 'package:html/dom.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:spotube/helpers/get-random-element.dart';
|
|
import 'package:spotube/models/Logger.dart';
|
|
import 'package:spotube/models/generated_secrets.dart';
|
|
|
|
final logger = createLogger("GetLyrics");
|
|
|
|
String getTitle(String title, String artist) {
|
|
return "$title $artist"
|
|
.toLowerCase()
|
|
.replaceAll(RegExp(" *\\([^)]*\\) *"), '')
|
|
.replaceAll(RegExp(" *\\[[^\\]]*]"), '')
|
|
.replaceAll(RegExp("feat.|ft."), '')
|
|
.replaceAll(RegExp("\\s+"), ' ')
|
|
.trim();
|
|
}
|
|
|
|
Future<String?> extractLyrics(Uri url) async {
|
|
try {
|
|
var response = await http.get(url);
|
|
|
|
Document document = parser.parse(response.body);
|
|
var lyrics = document.querySelector('div.lyrics')?.text.trim();
|
|
if (lyrics == null) {
|
|
lyrics = "";
|
|
document
|
|
.querySelectorAll("div[class^=\"Lyrics__Container\"]")
|
|
.forEach((element) {
|
|
if (element.text.trim().isNotEmpty) {
|
|
var snippet = element.innerHtml.replaceAll("<br>", "\n").replaceAll(
|
|
RegExp("<(?!\\s*br\\s*\\/?)[^>]+>", caseSensitive: false),
|
|
"",
|
|
);
|
|
var el = document.createElement("textarea");
|
|
el.innerHtml = snippet;
|
|
lyrics = "$lyrics${el.text.trim()}\n\n";
|
|
}
|
|
});
|
|
}
|
|
|
|
return lyrics;
|
|
} catch (e, stack) {
|
|
logger.e("extractLyrics", e, stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<List?> searchSong(
|
|
String title,
|
|
String artist, {
|
|
String? apiKey,
|
|
bool optimizeQuery = false,
|
|
bool authHeader = false,
|
|
}) async {
|
|
try {
|
|
if (apiKey == "" || apiKey == null) {
|
|
apiKey = getRandomElement(lyricsSecrets);
|
|
}
|
|
const searchUrl = 'https://api.genius.com/search?q=';
|
|
String song = optimizeQuery ? getTitle(title, artist) : "$title $artist";
|
|
|
|
String reqUrl = "$searchUrl${Uri.encodeComponent(song)}";
|
|
Map<String, String> headers = {"Authorization": 'Bearer $apiKey'};
|
|
var response = await http.get(
|
|
Uri.parse(authHeader ? reqUrl : "$reqUrl&access_token=$apiKey"),
|
|
headers: authHeader ? headers : null,
|
|
);
|
|
Map data = jsonDecode(response.body)["response"];
|
|
if (data["hits"]?.length == 0) return null;
|
|
List results = data["hits"]?.map((val) {
|
|
return <String, dynamic>{
|
|
"id": val["result"]["id"],
|
|
"full_title": val["result"]["full_title"],
|
|
"albumArt": val["result"]["song_art_image_url"],
|
|
"url": val["result"]["url"]
|
|
};
|
|
}).toList();
|
|
return results;
|
|
} catch (e, stack) {
|
|
logger.e("searchSong", e, stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<String?> getLyrics(
|
|
String title,
|
|
String artist, {
|
|
required String apiKey,
|
|
bool optimizeQuery = false,
|
|
bool authHeader = false,
|
|
}) async {
|
|
try {
|
|
var results = await searchSong(
|
|
title,
|
|
artist,
|
|
apiKey: apiKey,
|
|
optimizeQuery: optimizeQuery,
|
|
authHeader: authHeader,
|
|
);
|
|
if (results == null) return null;
|
|
String? lyrics = await extractLyrics(Uri.parse(results.first["url"]));
|
|
return lyrics;
|
|
} catch (e, stack) {
|
|
logger.e("getLyrics", e, stack);
|
|
return null;
|
|
}
|
|
}
|