Skip to content

Commit

Permalink
fix: move last fm to its own service, re-organize main by adding regi…
Browse files Browse the repository at this point in the history
…ster.dart
  • Loading branch information
Feichtmeier committed Nov 15, 2024
1 parent 8f6ccc2 commit 0c271a9
Show file tree
Hide file tree
Showing 10 changed files with 427 additions and 337 deletions.
22 changes: 11 additions & 11 deletions lib/app/app_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ class AppModel extends SafeChangeNotifier {
Stream<String?> get errorStream => _exposeService.discordErrorStream;
Stream<bool> get isDiscordConnectedStream =>
_exposeService.isDiscordConnectedStream;
Stream<bool> get isLastFmAuthenticatedStream =>
_exposeService.isLastFmAuthenticatedStream;
//TODO: Do something(ex:change the text of the save button) once authenticated

Future<void> connectToDiscord() async => _exposeService.connectToDiscord();
Future<void> disconnectFromDiscord() async =>
_exposeService.disconnectFromDiscord();
Future<void> setLastFmAuth() async {
final sessionData = await _exposeService.setLastFmAuth();
if (sessionData != null) {
_settingsService.setLastFmSessionKey(sessionData['sessionKey']!);
_settingsService.setLastFmUsername(sessionData['username']!);
}
}

ValueNotifier<bool> get isLastFmAuthorized =>
_exposeService.isLastFmAuthorized;
Future<void> authorizeLastFm({
required String apiKey,
required String apiSecret,
}) async =>
_exposeService.authorizeLastFm(
apiKey: apiKey,
apiSecret: apiSecret,
);

final GitHub _gitHub;
final SettingsService _settingsService;
Expand Down
2 changes: 2 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const kAppName = 'musicpod';

const kAppId = 'org.feichtmeier.Musicpod';

const kMusicPodFallBackColor = Color(0xFFed3c63);

const kDiscordApplicationId = '1235321910221602837';

const kLinuxDBusName = 'org.mpris.MediaPlayer2.musicpod';
Expand Down
78 changes: 20 additions & 58 deletions lib/expose/expose_service.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import 'dart:async';

import 'package:flutter/widgets.dart';
import 'package:flutter_discord_rpc/flutter_discord_rpc.dart';
import 'package:lastfm/lastfm.dart';
import 'package:url_launcher/url_launcher.dart';

import 'lastfm_service.dart';

class ExposeService {
ExposeService({
required FlutterDiscordRPC? discordRPC,
required LastFMAuthorized? lastFm,
required LastfmService lastFmService,
}) : _discordRPC = discordRPC,
_lastFm = lastFm;
_lastFmService = lastFmService;

final FlutterDiscordRPC? _discordRPC;
final LastFMAuthorized? _lastFm;
final LastfmService _lastFmService;

final _errorController = StreamController<String?>.broadcast();
final _lastFmAuthController = StreamController<bool>.broadcast();
Stream<String?> get discordErrorStream => _errorController.stream;
Stream<bool> get isDiscordConnectedStream =>
_discordRPC?.isConnectedStream ?? Stream.value(false);
Stream<bool> get isLastFmAuthenticatedStream => _lastFmAuthController.stream;

Future<void> exposeTitleOnline({
required String title,
Expand All @@ -32,43 +32,11 @@ class ExposeService {
additionalInfo: additionalInfo,
imageUrl: imageUrl,
);
if (_lastFm != null) {
await _exposeTitleToLastfm(
title: title,
artist: artist,
);
}
}

Future<Map<String, String>?> setLastFmAuth() async {
final lastfmua = _lastFm as LastFMUnauthorized;
launchUrl(
Uri.parse(await lastfmua.authorizeDesktop()),
await _lastFmService.exposeTitleToLastfm(
title: title,
artist: artist,
);

const maxWaitDuration = Duration(minutes: 2); // Customize as needed
final startTime = DateTime.now();
await Future.delayed(const Duration(seconds: 10));
while (DateTime.now().difference(startTime) < maxWaitDuration) {
try {
final lastfm = await lastfmua.finishAuthorizeDesktop();
final sessionKey = lastfm.sessionKey;
final username = lastfm.username;
_updateLastFmAuthStatus(true);
return {
'sessionKey': sessionKey,
'username': username,
};
} catch (e) {
await Future.delayed(const Duration(seconds: 10));
}
}
_updateLastFmAuthStatus(false);
return null;
}

void _updateLastFmAuthStatus(bool status) {
_lastFmAuthController.add(status);
}

Future<void> _exposeTitleToDiscord({
Expand Down Expand Up @@ -99,21 +67,6 @@ class ExposeService {
}
}

Future<void> _exposeTitleToLastfm({
required String title,
required String artist,
}) async {
try {
await _lastFm?.scrobble(
track: title,
artist: artist,
startTime: DateTime.now(),
);
} on Exception catch (e) {
_errorController.add(e.toString());
}
}

Future<void> connect() async {
await connectToDiscord();
}
Expand All @@ -126,6 +79,16 @@ class ExposeService {
}
}

ValueNotifier<bool> get isLastFmAuthorized => _lastFmService.isAuthorized;
Future<void> authorizeLastFm({
required String apiKey,
required String apiSecret,
}) =>
_lastFmService.authorize(
apiKey: apiKey,
apiSecret: apiSecret,
);

Future<void> disconnectFromDiscord() async {
try {
await _discordRPC?.disconnect();
Expand All @@ -137,6 +100,5 @@ class ExposeService {
Future<void> dispose() async {
await disconnectFromDiscord();
await _errorController.close();
await _lastFmAuthController.close();
}
}
96 changes: 96 additions & 0 deletions lib/expose/lastfm_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import 'dart:async';

import 'package:flutter/widgets.dart';
import 'package:lastfm/lastfm.dart';
import 'package:url_launcher/url_launcher.dart';

import '../common/logging.dart';
import '../settings/settings_service.dart';

class LastfmService {
LastfmService({required SettingsService settingsService})
: _settingsService = settingsService;

final SettingsService _settingsService;

LastFM? _lastFm;
final isAuthorized = ValueNotifier<bool>(false);
void _setLastFm(LastFM lastFm) {
_lastFm = lastFm;
isAuthorized.value = lastFm is LastFMAuthorized;
}

Future<void> exposeTitleToLastfm({
required String title,
required String artist,
}) async {
if (isAuthorized.value && _settingsService.enableLastFmScrobbling) {
try {
await (_lastFm as LastFMAuthorized).scrobble(
track: title,
artist: artist,
startTime: DateTime.now(),
);
} on Exception catch (e) {
printMessageInDebugMode(e);
}
}
}

void init({LastFMAuthorized? lastFmAuthorized}) {
if (lastFmAuthorized != null) {
_setLastFm(lastFmAuthorized);
_settingsService.setLastFmSessionKey(lastFmAuthorized.sessionKey);
_settingsService.setLastFmUsername(lastFmAuthorized.username);
} else {
final apiKey = _settingsService.lastFmApiKey;
final apiSecret = _settingsService.lastFmSecret;
final sessionKey = _settingsService.lastFmSessionKey;
final username = _settingsService.lastFmUsername;

if (sessionKey != null &&
username != null &&
apiKey != null &&
apiSecret != null) {
_setLastFm(
LastFMAuthorized(
apiKey,
secret: apiSecret,
sessionKey: sessionKey,
username: username,
),
);
} else if (apiKey != null) {
_setLastFm(LastFMUnauthorized(apiKey, apiSecret));
}
}
}

Future<void> authorize({
required String apiKey,
required String apiSecret,
}) async {
_settingsService.setLastFmApiKey(apiKey);
_settingsService.setLastFmSecret(apiSecret);

final lastfmua = LastFMUnauthorized(apiKey, apiSecret);
launchUrl(
Uri.parse(await lastfmua.authorizeDesktop()),
);

const maxWaitDuration = Duration(minutes: 2); // Customize as needed
final startTime = DateTime.now();
await Future.delayed(const Duration(seconds: 10));
while (DateTime.now().difference(startTime) < maxWaitDuration) {
try {
final lastfm = await lastfmua.finishAuthorizeDesktop();
init(lastFmAuthorized: lastfm);
} catch (e) {
printMessageInDebugMode(e);
await Future.delayed(const Duration(seconds: 10));
}

if (isAuthorized.value) break;
}
}
}
2 changes: 2 additions & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"playlistDialogTitleNew": "Wiedergabeliste hinzufügen",
"playlistDialogTitleEdit": "Wiedergabeliste editieren",
"save": "Speichern",
"saveAndAuthorize": "Speichern und Autorisieren",
"title": "Titel",
"titles": "Titel",
"artist": "Künstler",
Expand Down Expand Up @@ -357,6 +358,7 @@
"exposeToDiscordTitle": "Discord",
"exposeToDiscordSubTitle": "Der Künstler und Titel des Lieds/Radio-Senders/Podcast das du gerade hörst wird online geteilt.",
"featureDisabledOnPlatform": "Diese Funktion ist momentan nicht für dieses Betriebssystem aktiviert.",
"exposeToLastfmSubTitle": "Der Künstler und Titel des Lieds/Radio-Senders/Podcast das du gerade hörst wird online geteilt.",
"regionNone": "Keine",
"onlineArtError": "Die Albumkunst-Online-Suche ist momentan nicht verfügbar",
"regionAfghanistan": "Afghanistan",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"playlistDialogTitleNew": "Add playlist",
"playlistDialogTitleEdit": "Edit playlist",
"save": "Save",
"saveAndAuthorize": "Save and authorize",
"title": "Title",
"titles": "Titles",
"artist": "Artist",
Expand Down
Loading

0 comments on commit 0c271a9

Please sign in to comment.