Skip to content

Commit

Permalink
Added support for scrobbling to Libre.fm
Browse files Browse the repository at this point in the history
  • Loading branch information
nrubin29 committed Aug 14, 2021
1 parent 2c02afe commit 2011e1b
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 13 deletions.
34 changes: 21 additions & 13 deletions lib/services/lastfm/lastfm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:finale/services/lastfm/track.dart';
import 'package:finale/services/lastfm/user.dart';
import 'package:finale/util/preferences.dart';

Uri _buildUri(String method, Map<String, dynamic> data) {
Uri _buildUri(String method, Map<String, dynamic> data, {bool libre = false}) {
final allData = {
...data.map((key, value) => MapEntry(key, value.toString())),
'api_key': apiKey,
Expand All @@ -27,17 +27,18 @@ Uri _buildUri(String method, Map<String, dynamic> data) {

return Uri(
scheme: 'https',
host: 'ws.audioscrobbler.com',
path: '2.0',
host: libre ? 'libre.fm' : 'ws.audioscrobbler.com',
path: '2.0/',
queryParameters: allData);
}

Future<Map<String, dynamic>> _doRequest(
String method, Map<String, dynamic> data,
{bool post = false}) async {
final uri = _buildUri(method, data);
final response =
post ? await httpClient.post(uri) : await httpClient.get(uri);
{bool post = false, bool libre = false}) async {
final uri = _buildUri(method, data, libre: libre);
final response = post
? await httpClient.post(uri, body: libre ? uri.queryParameters : null)
: await httpClient.get(uri);

dynamic jsonObject;

Expand Down Expand Up @@ -247,10 +248,10 @@ class UserGetTrackScrobblesRequest extends PagedRequest<LUserTrackScrobble> {
}

class Lastfm {
static Future<LAuthenticationResponseSession> authenticate(
String token) async {
final rawResponse =
await _doRequest('auth.getSession', {'token': token}, post: true);
static Future<LAuthenticationResponseSession> authenticate(String token,
{bool libre = false}) async {
final rawResponse = await _doRequest('auth.getSession', {'token': token},
post: true, libre: libre);
return LAuthenticationResponseSession.fromJson(rawResponse['session']);
}

Expand Down Expand Up @@ -355,7 +356,6 @@ class Lastfm {
static Future<LScrobbleResponseScrobblesAttr> scrobble(
List<Track> tracks, List<DateTime> timestamps) async {
final data = <String, dynamic>{};
data['sk'] = Preferences().key;

tracks.asMap().forEach((i, track) {
if (track.albumName?.isNotEmpty ?? false) {
Expand All @@ -367,7 +367,15 @@ class Lastfm {
data['timestamp[$i]'] = timestamps[i].millisecondsSinceEpoch ~/ 1000;
});

final rawResponse = await _doRequest('track.scrobble', data, post: true);
if (Preferences().libreEnabled) {
await _doRequest(
'track.scrobble', {...data, 'sk': Preferences().libreKey},
post: true, libre: true);
}

final rawResponse = await _doRequest(
'track.scrobble', {...data, 'sk': Preferences().key},
post: true);
return LScrobbleResponseScrobblesAttr.fromJson(
rawResponse['scrobbles']['@attr']);
}
Expand Down
19 changes: 19 additions & 0 deletions lib/util/preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,25 @@ class Preferences {
_spotifyEnabledChange.add(null);
}

String? get libreKey => _preferences.getString('libreKey');

set libreKey(String? value) {
if (value != null) {
_preferences.setString('libreKey', value);
} else {
_preferences.remove('libreKey');
}
}

bool get libreEnabled => _preferences.getBool('libreEnabled') ?? false;

set libreEnabled(bool value) => _preferences.setBool('libreEnabled', value);

void clearLibre() {
libreEnabled = false;
libreKey = null;
}

SearchEngine get searchEngine {
if (!_preferences.containsKey('searchEngine')) {
_preferences.setInt('searchEngine', SearchEngine.lastfm.index);
Expand Down
41 changes: 41 additions & 0 deletions lib/widgets/settings/search_engine_settings_view.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import 'package:finale/env.dart';
import 'package:finale/services/lastfm/lastfm.dart';
import 'package:finale/util/preferences.dart';
import 'package:finale/util/util.dart';
import 'package:finale/widgets/entity/spotify/spotify_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_auth/flutter_web_auth.dart';
import 'package:social_media_buttons/social_media_icons.dart';

class SearchEngineSettingsView extends StatefulWidget {
Expand All @@ -11,11 +15,13 @@ class SearchEngineSettingsView extends StatefulWidget {

class _SearchEngineSettingsViewState extends State<SearchEngineSettingsView> {
late bool _spotifyEnabled;
late bool _libreEnabled;

@override
void initState() {
super.initState();
_spotifyEnabled = Preferences().spotifyEnabled;
_libreEnabled = Preferences().libreEnabled;
}

void _logOutSpotify() {
Expand Down Expand Up @@ -76,6 +82,41 @@ class _SearchEngineSettingsViewState extends State<SearchEngineSettingsView> {
},
),
),
ListTile(
title: Row(children: const [Text('Libre.fm')]),
leading: const Icon(Icons.rss_feed),
trailing: Switch(
value: _libreEnabled,
onChanged: (value) async {
if (value && Preferences().libreKey == null) {
try {
final result = await FlutterWebAuth.authenticate(
url: Uri.https('libre.fm', 'api/auth', {
'api_key': apiKey,
'cb': authCallbackUrl
}).toString(),
callbackUrlScheme: 'finale');
final token = Uri.parse(result).queryParameters['token']!;
final session = await Lastfm.authenticate(token, libre: true);
Preferences().libreKey = session.key;
} on PlatformException catch (e) {
assert(() {
throw e;
}());
return;
}
}

_libreEnabled = (Preferences().libreEnabled = value);

setState(() {
if (!_libreEnabled) {
Preferences().clearLibre();
}
});
},
),
),
]),
);
}
Expand Down

0 comments on commit 2011e1b

Please sign in to comment.