Skip to content

Commit

Permalink
include device info in offline listens
Browse files Browse the repository at this point in the history
- also refactored obtaining of device info into separate function
  • Loading branch information
Chaphasilor committed Jan 4, 2025
1 parent dfa41b0 commit 7277228
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 19 deletions.
19 changes: 19 additions & 0 deletions lib/models/finamp_models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,7 @@ class OfflineListen {
this.artist,
this.album,
this.trackMbid,
this.deviceInfo,
});

/// The stop timestamp of the listen, measured in seconds since the epoch.
Expand All @@ -1430,6 +1431,9 @@ class OfflineListen {
// The MusicBrainz ID of the track, if available.
@HiveField(6)
String? trackMbid;

@HiveField(7)
DeviceInfo? deviceInfo;
}

@HiveType(typeId: 50)
Expand Down Expand Up @@ -2386,3 +2390,18 @@ class FinampFeatureChipsConfiguration {
);
}
}


@HiveType(typeId: 76)
class DeviceInfo {
DeviceInfo({
required this.name,
required this.id,
});

@HiveField(0)
String name;

@HiveField(1)
String? id;
}
44 changes: 42 additions & 2 deletions lib/models/finamp_models.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 39 additions & 17 deletions lib/services/jellyfin_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io' show HttpClient, Platform;
import 'package:app_set_id/app_set_id.dart';
import 'package:chopper/chopper.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:finamp/models/finamp_models.dart';
import 'package:finamp/services/http_aggregate_logging_interceptor.dart';
import 'package:get_it/get_it.dart';
import 'package:http/io_client.dart' as http;
Expand Down Expand Up @@ -601,40 +602,61 @@ Future<String> getAuthHeader() async {
}

authHeader = '${authHeader}Client="Finamp", ';

final deviceInfo = await getDeviceInfo();
authHeader =
'${authHeader}Device="${deviceInfo.name}",DeviceId="${deviceInfo.id}", ';

PackageInfo packageInfo = await PackageInfo.fromPlatform();
authHeader = '${authHeader}Version="${packageInfo.version}"';

// In some cases non-ASCII characters can end up in the header, usually via
// iOS device name
return authHeader.replaceAll(notAsciiRegex, "_");
}

// return type for deviceInfo

Future<DeviceInfo> getDeviceInfo() async {
DeviceInfo info;
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid) {
AndroidDeviceInfo androidDeviceInfo = await deviceInfo.androidInfo;
final appSetId = await AppSetId().getIdentifier();
authHeader = '${authHeader}Device="${androidDeviceInfo.model}", ';
authHeader = '${authHeader}DeviceId="$appSetId", ';
info = DeviceInfo(
name: androidDeviceInfo.model,
id: appSetId,
);
} else if (Platform.isIOS) {
IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
final appSetId = await AppSetId().getIdentifier();
authHeader = '${authHeader}Device="${iosDeviceInfo.name}", ';
authHeader = '${authHeader}DeviceId="$appSetId", ';
info = DeviceInfo(
name: iosDeviceInfo.name,
id: appSetId,
);
} else if (Platform.isWindows) {
WindowsDeviceInfo windowsDeviceInfo = await deviceInfo.windowsInfo;
authHeader = '${authHeader}Device="${windowsDeviceInfo.computerName}", ';
final windowsId = windowsDeviceInfo.deviceId;
authHeader = '${authHeader}DeviceId="$windowsId", ';
info = DeviceInfo(
name: windowsDeviceInfo.computerName,
id: windowsId,
);
} else if (Platform.isLinux) {
LinuxDeviceInfo linuxDeviceInfo = await deviceInfo.linuxInfo;
authHeader = '${authHeader}Device="${linuxDeviceInfo.name}", ';
final linuxId = linuxDeviceInfo.machineId;
authHeader = '${authHeader}DeviceId="$linuxId", ';
info = DeviceInfo(
name: linuxDeviceInfo.name,
id: linuxId,
);
} else if (Platform.isMacOS) {
MacOsDeviceInfo macOsDeviceInfo = await deviceInfo.macOsInfo;
authHeader = '${authHeader}Device="${macOsDeviceInfo.computerName}", ';
final macId = macOsDeviceInfo.systemGUID;
authHeader = '${authHeader}DeviceId="$macId", ';
info = DeviceInfo(
name: macOsDeviceInfo.computerName,
id: macId,
);
} else {
throw Exception("Unsupported platform");
}

PackageInfo packageInfo = await PackageInfo.fromPlatform();
authHeader = '${authHeader}Version="${packageInfo.version}"';

// In some cases non-ASCII characters can end up in the header, usually via
// iOS device name
return authHeader.replaceAll(notAsciiRegex, "_");
return info;
}
8 changes: 8 additions & 0 deletions lib/services/offline_listen_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'package:audio_service/audio_service.dart';
import 'package:finamp/models/finamp_models.dart';
import 'package:finamp/services/finamp_user_helper.dart';
import 'package:finamp/services/jellyfin_api.dart';
import 'package:get_it/get_it.dart';
import 'package:hive/hive.dart';
import 'package:logging/logging.dart';
Expand Down Expand Up @@ -38,6 +39,8 @@ class OfflineListenLogHelper {
Future<void> logOfflineListen(MediaItem item) async {
final itemJson = item.extras!["itemJson"];

final deviceInfo = await getDeviceInfo();

final offlineListen = OfflineListen(
timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000,
userId: _finampUserHelper.currentUserId!,
Expand All @@ -46,6 +49,7 @@ class OfflineListenLogHelper {
artist: itemJson["AlbumArtist"],
album: itemJson["Album"],
trackMbid: itemJson["ProviderIds"]?["MusicBrainzTrack"],
deviceInfo: deviceInfo,
);

return _logOfflineListen(offlineListen);
Expand Down Expand Up @@ -73,6 +77,10 @@ class OfflineListenLogHelper {
'album': listen.album,
'track_mbid': listen.trackMbid,
'user_id': listen.userId,
'device': {
'name': listen.deviceInfo?.name,
'id': listen.deviceInfo?.id,
},
};
final content = json.encode(data) + Platform.lineTerminator;

Expand Down

0 comments on commit 7277228

Please sign in to comment.