🔀 Merge some services from spotube
This commit is contained in:
19
lib/services/song_link/model.dart
Executable file
19
lib/services/song_link/model.dart
Executable file
@ -0,0 +1,19 @@
|
||||
part of './song_link.dart';
|
||||
|
||||
@freezed
|
||||
class SongLink with _$SongLink {
|
||||
const factory SongLink({
|
||||
required String displayName,
|
||||
required String linkId,
|
||||
required String platform,
|
||||
required bool show,
|
||||
required String? uniqueId,
|
||||
required String? country,
|
||||
required String? url,
|
||||
required String? nativeAppUriMobile,
|
||||
required String? nativeAppUriDesktop,
|
||||
}) = _SongLink;
|
||||
|
||||
factory SongLink.fromJson(Map<String, dynamic> json) =>
|
||||
_$SongLinkFromJson(json);
|
||||
}
|
51
lib/services/song_link/song_link.dart
Executable file
51
lib/services/song_link/song_link.dart
Executable file
@ -0,0 +1,51 @@
|
||||
library song_link;
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:html/parser.dart';
|
||||
|
||||
part 'model.dart';
|
||||
|
||||
part 'song_link.freezed.dart';
|
||||
part 'song_link.g.dart';
|
||||
|
||||
abstract class SongLinkService {
|
||||
static Future<List<SongLink>> links(String spotifyId) async {
|
||||
try {
|
||||
final client = GetConnect();
|
||||
final res = await client.get(
|
||||
"https://song.link/s/$spotifyId",
|
||||
headers: {
|
||||
"Accept":
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
||||
},
|
||||
);
|
||||
|
||||
final document = parse(res.body);
|
||||
|
||||
final script = document.getElementById("__NEXT_DATA__")?.text;
|
||||
|
||||
if (script == null) {
|
||||
return <SongLink>[];
|
||||
}
|
||||
|
||||
final pageProps = jsonDecode(script) as Map<String, dynamic>;
|
||||
final songLinks = pageProps["props"]?["pageProps"]?["pageData"]
|
||||
?["sections"]
|
||||
?.firstWhere(
|
||||
(section) => section?["sectionId"] == "section|auto|links|listen",
|
||||
)?["links"] as List?;
|
||||
|
||||
return songLinks?.map((link) => SongLink.fromJson(link)).toList() ??
|
||||
<SongLink>[];
|
||||
} catch (e) {
|
||||
log('[SongLink] Unable get song link: $e');
|
||||
return <SongLink>[];
|
||||
}
|
||||
}
|
||||
}
|
320
lib/services/song_link/song_link.freezed.dart
Executable file
320
lib/services/song_link/song_link.freezed.dart
Executable file
@ -0,0 +1,320 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'song_link.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
SongLink _$SongLinkFromJson(Map<String, dynamic> json) {
|
||||
return _SongLink.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SongLink {
|
||||
String get displayName => throw _privateConstructorUsedError;
|
||||
String get linkId => throw _privateConstructorUsedError;
|
||||
String get platform => throw _privateConstructorUsedError;
|
||||
bool get show => throw _privateConstructorUsedError;
|
||||
String? get uniqueId => throw _privateConstructorUsedError;
|
||||
String? get country => throw _privateConstructorUsedError;
|
||||
String? get url => throw _privateConstructorUsedError;
|
||||
String? get nativeAppUriMobile => throw _privateConstructorUsedError;
|
||||
String? get nativeAppUriDesktop => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$SongLinkCopyWith<SongLink> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $SongLinkCopyWith<$Res> {
|
||||
factory $SongLinkCopyWith(SongLink value, $Res Function(SongLink) then) =
|
||||
_$SongLinkCopyWithImpl<$Res, SongLink>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String displayName,
|
||||
String linkId,
|
||||
String platform,
|
||||
bool show,
|
||||
String? uniqueId,
|
||||
String? country,
|
||||
String? url,
|
||||
String? nativeAppUriMobile,
|
||||
String? nativeAppUriDesktop});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$SongLinkCopyWithImpl<$Res, $Val extends SongLink>
|
||||
implements $SongLinkCopyWith<$Res> {
|
||||
_$SongLinkCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? displayName = null,
|
||||
Object? linkId = null,
|
||||
Object? platform = null,
|
||||
Object? show = null,
|
||||
Object? uniqueId = freezed,
|
||||
Object? country = freezed,
|
||||
Object? url = freezed,
|
||||
Object? nativeAppUriMobile = freezed,
|
||||
Object? nativeAppUriDesktop = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
displayName: null == displayName
|
||||
? _value.displayName
|
||||
: displayName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
linkId: null == linkId
|
||||
? _value.linkId
|
||||
: linkId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
platform: null == platform
|
||||
? _value.platform
|
||||
: platform // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
show: null == show
|
||||
? _value.show
|
||||
: show // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
uniqueId: freezed == uniqueId
|
||||
? _value.uniqueId
|
||||
: uniqueId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
country: freezed == country
|
||||
? _value.country
|
||||
: country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
url: freezed == url
|
||||
? _value.url
|
||||
: url // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
nativeAppUriMobile: freezed == nativeAppUriMobile
|
||||
? _value.nativeAppUriMobile
|
||||
: nativeAppUriMobile // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
nativeAppUriDesktop: freezed == nativeAppUriDesktop
|
||||
? _value.nativeAppUriDesktop
|
||||
: nativeAppUriDesktop // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SongLinkImplCopyWith<$Res>
|
||||
implements $SongLinkCopyWith<$Res> {
|
||||
factory _$$SongLinkImplCopyWith(
|
||||
_$SongLinkImpl value, $Res Function(_$SongLinkImpl) then) =
|
||||
__$$SongLinkImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String displayName,
|
||||
String linkId,
|
||||
String platform,
|
||||
bool show,
|
||||
String? uniqueId,
|
||||
String? country,
|
||||
String? url,
|
||||
String? nativeAppUriMobile,
|
||||
String? nativeAppUriDesktop});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SongLinkImplCopyWithImpl<$Res>
|
||||
extends _$SongLinkCopyWithImpl<$Res, _$SongLinkImpl>
|
||||
implements _$$SongLinkImplCopyWith<$Res> {
|
||||
__$$SongLinkImplCopyWithImpl(
|
||||
_$SongLinkImpl _value, $Res Function(_$SongLinkImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? displayName = null,
|
||||
Object? linkId = null,
|
||||
Object? platform = null,
|
||||
Object? show = null,
|
||||
Object? uniqueId = freezed,
|
||||
Object? country = freezed,
|
||||
Object? url = freezed,
|
||||
Object? nativeAppUriMobile = freezed,
|
||||
Object? nativeAppUriDesktop = freezed,
|
||||
}) {
|
||||
return _then(_$SongLinkImpl(
|
||||
displayName: null == displayName
|
||||
? _value.displayName
|
||||
: displayName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
linkId: null == linkId
|
||||
? _value.linkId
|
||||
: linkId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
platform: null == platform
|
||||
? _value.platform
|
||||
: platform // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
show: null == show
|
||||
? _value.show
|
||||
: show // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
uniqueId: freezed == uniqueId
|
||||
? _value.uniqueId
|
||||
: uniqueId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
country: freezed == country
|
||||
? _value.country
|
||||
: country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
url: freezed == url
|
||||
? _value.url
|
||||
: url // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
nativeAppUriMobile: freezed == nativeAppUriMobile
|
||||
? _value.nativeAppUriMobile
|
||||
: nativeAppUriMobile // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
nativeAppUriDesktop: freezed == nativeAppUriDesktop
|
||||
? _value.nativeAppUriDesktop
|
||||
: nativeAppUriDesktop // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$SongLinkImpl implements _SongLink {
|
||||
const _$SongLinkImpl(
|
||||
{required this.displayName,
|
||||
required this.linkId,
|
||||
required this.platform,
|
||||
required this.show,
|
||||
required this.uniqueId,
|
||||
required this.country,
|
||||
required this.url,
|
||||
required this.nativeAppUriMobile,
|
||||
required this.nativeAppUriDesktop});
|
||||
|
||||
factory _$SongLinkImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$SongLinkImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String displayName;
|
||||
@override
|
||||
final String linkId;
|
||||
@override
|
||||
final String platform;
|
||||
@override
|
||||
final bool show;
|
||||
@override
|
||||
final String? uniqueId;
|
||||
@override
|
||||
final String? country;
|
||||
@override
|
||||
final String? url;
|
||||
@override
|
||||
final String? nativeAppUriMobile;
|
||||
@override
|
||||
final String? nativeAppUriDesktop;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SongLink(displayName: $displayName, linkId: $linkId, platform: $platform, show: $show, uniqueId: $uniqueId, country: $country, url: $url, nativeAppUriMobile: $nativeAppUriMobile, nativeAppUriDesktop: $nativeAppUriDesktop)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SongLinkImpl &&
|
||||
(identical(other.displayName, displayName) ||
|
||||
other.displayName == displayName) &&
|
||||
(identical(other.linkId, linkId) || other.linkId == linkId) &&
|
||||
(identical(other.platform, platform) ||
|
||||
other.platform == platform) &&
|
||||
(identical(other.show, show) || other.show == show) &&
|
||||
(identical(other.uniqueId, uniqueId) ||
|
||||
other.uniqueId == uniqueId) &&
|
||||
(identical(other.country, country) || other.country == country) &&
|
||||
(identical(other.url, url) || other.url == url) &&
|
||||
(identical(other.nativeAppUriMobile, nativeAppUriMobile) ||
|
||||
other.nativeAppUriMobile == nativeAppUriMobile) &&
|
||||
(identical(other.nativeAppUriDesktop, nativeAppUriDesktop) ||
|
||||
other.nativeAppUriDesktop == nativeAppUriDesktop));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, displayName, linkId, platform,
|
||||
show, uniqueId, country, url, nativeAppUriMobile, nativeAppUriDesktop);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
||||
__$$SongLinkImplCopyWithImpl<_$SongLinkImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$SongLinkImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _SongLink implements SongLink {
|
||||
const factory _SongLink(
|
||||
{required final String displayName,
|
||||
required final String linkId,
|
||||
required final String platform,
|
||||
required final bool show,
|
||||
required final String? uniqueId,
|
||||
required final String? country,
|
||||
required final String? url,
|
||||
required final String? nativeAppUriMobile,
|
||||
required final String? nativeAppUriDesktop}) = _$SongLinkImpl;
|
||||
|
||||
factory _SongLink.fromJson(Map<String, dynamic> json) =
|
||||
_$SongLinkImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get displayName;
|
||||
@override
|
||||
String get linkId;
|
||||
@override
|
||||
String get platform;
|
||||
@override
|
||||
bool get show;
|
||||
@override
|
||||
String? get uniqueId;
|
||||
@override
|
||||
String? get country;
|
||||
@override
|
||||
String? get url;
|
||||
@override
|
||||
String? get nativeAppUriMobile;
|
||||
@override
|
||||
String? get nativeAppUriDesktop;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
32
lib/services/song_link/song_link.g.dart
Executable file
32
lib/services/song_link/song_link.g.dart
Executable file
@ -0,0 +1,32 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'song_link.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$SongLinkImpl _$$SongLinkImplFromJson(Map json) => _$SongLinkImpl(
|
||||
displayName: json['displayName'] as String,
|
||||
linkId: json['linkId'] as String,
|
||||
platform: json['platform'] as String,
|
||||
show: json['show'] as bool,
|
||||
uniqueId: json['uniqueId'] as String?,
|
||||
country: json['country'] as String?,
|
||||
url: json['url'] as String?,
|
||||
nativeAppUriMobile: json['nativeAppUriMobile'] as String?,
|
||||
nativeAppUriDesktop: json['nativeAppUriDesktop'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SongLinkImplToJson(_$SongLinkImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'displayName': instance.displayName,
|
||||
'linkId': instance.linkId,
|
||||
'platform': instance.platform,
|
||||
'show': instance.show,
|
||||
'uniqueId': instance.uniqueId,
|
||||
'country': instance.country,
|
||||
'url': instance.url,
|
||||
'nativeAppUriMobile': instance.nativeAppUriMobile,
|
||||
'nativeAppUriDesktop': instance.nativeAppUriDesktop,
|
||||
};
|
Reference in New Issue
Block a user