mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
chore: remove unnecessary files and youtube_explode
This commit is contained in:
parent
962d9118dd
commit
5a4e3baa51
@ -1,101 +0,0 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||
|
||||
part 'cache_track.g.dart';
|
||||
|
||||
@HiveType(typeId: 2)
|
||||
class CacheTrackEngagement {
|
||||
@HiveField(0)
|
||||
late int viewCount;
|
||||
|
||||
@HiveField(1)
|
||||
late int? likeCount;
|
||||
|
||||
@HiveField(2)
|
||||
late int? dislikeCount;
|
||||
|
||||
CacheTrackEngagement();
|
||||
|
||||
CacheTrackEngagement.fromEngagement(Engagement engagement)
|
||||
: viewCount = engagement.viewCount,
|
||||
likeCount = engagement.likeCount,
|
||||
dislikeCount = engagement.dislikeCount;
|
||||
}
|
||||
|
||||
@HiveType(typeId: 3)
|
||||
class CacheTrackSkipSegment {
|
||||
@HiveField(0)
|
||||
late int start;
|
||||
@HiveField(1)
|
||||
late int end;
|
||||
|
||||
CacheTrackSkipSegment();
|
||||
|
||||
CacheTrackSkipSegment.fromJson(Map map)
|
||||
: start = map["start"].toInt(),
|
||||
end = map["end"].toInt();
|
||||
|
||||
Map<String, int> toJson() {
|
||||
return Map.castFrom<String, dynamic, String, int>(
|
||||
{"start": start, "end": end});
|
||||
}
|
||||
}
|
||||
|
||||
@HiveType(typeId: 1)
|
||||
class CacheTrack extends HiveObject {
|
||||
@HiveField(0)
|
||||
late String id;
|
||||
|
||||
@HiveField(1)
|
||||
late String title;
|
||||
|
||||
@HiveField(2)
|
||||
late String channelId;
|
||||
|
||||
@HiveField(3)
|
||||
late String? uploadDate;
|
||||
|
||||
@HiveField(4)
|
||||
late String? publishDate;
|
||||
|
||||
@HiveField(5)
|
||||
late String description;
|
||||
|
||||
@HiveField(6)
|
||||
late String? duration;
|
||||
|
||||
@HiveField(7)
|
||||
late List<String>? keywords;
|
||||
|
||||
@HiveField(8)
|
||||
late CacheTrackEngagement engagement;
|
||||
|
||||
@HiveField(9)
|
||||
late String mode;
|
||||
|
||||
@HiveField(10)
|
||||
late String author;
|
||||
|
||||
@HiveField(11)
|
||||
late List<CacheTrackSkipSegment>? skipSegments;
|
||||
|
||||
CacheTrack();
|
||||
|
||||
CacheTrack.fromVideo(
|
||||
Video video,
|
||||
this.mode, {
|
||||
required List<Map<String, int>> skipSegments,
|
||||
}) : id = video.id.value,
|
||||
title = video.title,
|
||||
author = video.author,
|
||||
channelId = video.channelId.value,
|
||||
uploadDate = video.uploadDate.toString(),
|
||||
publishDate = video.publishDate.toString(),
|
||||
description = video.description,
|
||||
duration = video.duration.toString(),
|
||||
keywords = video.keywords,
|
||||
engagement = CacheTrackEngagement.fromEngagement(video.engagement),
|
||||
skipSegments = skipSegments
|
||||
.map((segment) => CacheTrackSkipSegment.fromJson(segment))
|
||||
.toList();
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'cache_track.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class CacheTrackEngagementAdapter extends TypeAdapter<CacheTrackEngagement> {
|
||||
@override
|
||||
final int typeId = 2;
|
||||
|
||||
@override
|
||||
CacheTrackEngagement read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return CacheTrackEngagement()
|
||||
..viewCount = fields[0] as int
|
||||
..likeCount = fields[1] as int?
|
||||
..dislikeCount = fields[2] as int?;
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, CacheTrackEngagement obj) {
|
||||
writer
|
||||
..writeByte(3)
|
||||
..writeByte(0)
|
||||
..write(obj.viewCount)
|
||||
..writeByte(1)
|
||||
..write(obj.likeCount)
|
||||
..writeByte(2)
|
||||
..write(obj.dislikeCount);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is CacheTrackEngagementAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
|
||||
class CacheTrackSkipSegmentAdapter extends TypeAdapter<CacheTrackSkipSegment> {
|
||||
@override
|
||||
final int typeId = 3;
|
||||
|
||||
@override
|
||||
CacheTrackSkipSegment read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return CacheTrackSkipSegment()
|
||||
..start = fields[0] as int
|
||||
..end = fields[1] as int;
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, CacheTrackSkipSegment obj) {
|
||||
writer
|
||||
..writeByte(2)
|
||||
..writeByte(0)
|
||||
..write(obj.start)
|
||||
..writeByte(1)
|
||||
..write(obj.end);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is CacheTrackSkipSegmentAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
|
||||
class CacheTrackAdapter extends TypeAdapter<CacheTrack> {
|
||||
@override
|
||||
final int typeId = 1;
|
||||
|
||||
@override
|
||||
CacheTrack read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return CacheTrack()
|
||||
..id = fields[0] as String
|
||||
..title = fields[1] as String
|
||||
..channelId = fields[2] as String
|
||||
..uploadDate = fields[3] as String?
|
||||
..publishDate = fields[4] as String?
|
||||
..description = fields[5] as String
|
||||
..duration = fields[6] as String?
|
||||
..keywords = (fields[7] as List?)?.cast<String>()
|
||||
..engagement = fields[8] as CacheTrackEngagement
|
||||
..mode = fields[9] as String
|
||||
..author = fields[10] as String
|
||||
..skipSegments = (fields[11] as List?)?.cast<CacheTrackSkipSegment>();
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, CacheTrack obj) {
|
||||
writer
|
||||
..writeByte(12)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.title)
|
||||
..writeByte(2)
|
||||
..write(obj.channelId)
|
||||
..writeByte(3)
|
||||
..write(obj.uploadDate)
|
||||
..writeByte(4)
|
||||
..write(obj.publishDate)
|
||||
..writeByte(5)
|
||||
..write(obj.description)
|
||||
..writeByte(6)
|
||||
..write(obj.duration)
|
||||
..writeByte(7)
|
||||
..write(obj.keywords)
|
||||
..writeByte(8)
|
||||
..write(obj.engagement)
|
||||
..writeByte(9)
|
||||
..write(obj.mode)
|
||||
..writeByte(10)
|
||||
..write(obj.author)
|
||||
..writeByte(11)
|
||||
..write(obj.skipSegments);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is CacheTrackAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
@ -1,37 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:catcher/catcher.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:piped_client/piped_client.dart';
|
||||
import 'package:spotube/entities/cache_track.dart';
|
||||
import 'package:spotube/models/logger.dart';
|
||||
import 'package:spotube/models/track.dart';
|
||||
import 'package:spotube/provider/user_preferences_provider.dart';
|
||||
import 'package:spotube/services/youtube.dart';
|
||||
import 'package:spotube/utils/duration.dart';
|
||||
|
||||
extension PipedSearchItemExtension on PipedSearchItem {
|
||||
static PipedSearchItemStream fromCacheTrack(CacheTrack cacheTrack) {
|
||||
return PipedSearchItemStream(
|
||||
type: PipedSearchItemType.stream,
|
||||
url: "watch?v=${cacheTrack.id}",
|
||||
title: cacheTrack.title,
|
||||
uploaderName: cacheTrack.author,
|
||||
uploaderUrl: "/channel/${cacheTrack.channelId}",
|
||||
uploaded: -1,
|
||||
uploadedDate: cacheTrack.uploadDate ?? "",
|
||||
shortDescription: cacheTrack.description,
|
||||
isShort: false,
|
||||
thumbnail: "",
|
||||
duration: cacheTrack.duration != null
|
||||
? tryParseDuration(cacheTrack.duration!) ?? Duration.zero
|
||||
: Duration.zero,
|
||||
uploaderAvatar: "",
|
||||
uploaderVerified: false,
|
||||
views: cacheTrack.engagement.viewCount,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension PipedStreamResponseExtension on PipedStreamResponse {
|
||||
static Future<PipedStreamResponse> fromBackendTrack(
|
||||
|
@ -1,159 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:catcher/catcher.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:spotube/entities/cache_track.dart';
|
||||
import 'package:spotube/models/logger.dart';
|
||||
import 'package:spotube/models/track.dart';
|
||||
import 'package:spotube/provider/user_preferences_provider.dart';
|
||||
import 'package:spotube/utils/duration.dart';
|
||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||
|
||||
extension VideoFromCacheTrackExtension on Video {
|
||||
static Video fromCacheTrack(CacheTrack cacheTrack) {
|
||||
return Video(
|
||||
VideoId.fromString(cacheTrack.id),
|
||||
cacheTrack.title,
|
||||
cacheTrack.author,
|
||||
ChannelId.fromString(cacheTrack.channelId),
|
||||
cacheTrack.uploadDate != null
|
||||
? DateTime.tryParse(cacheTrack.uploadDate!)
|
||||
: null,
|
||||
cacheTrack.uploadDate,
|
||||
cacheTrack.publishDate != null
|
||||
? DateTime.tryParse(cacheTrack.publishDate!)
|
||||
: null,
|
||||
cacheTrack.description,
|
||||
cacheTrack.duration != null
|
||||
? tryParseDuration(cacheTrack.duration!)
|
||||
: null,
|
||||
ThumbnailSet(cacheTrack.id),
|
||||
cacheTrack.keywords,
|
||||
Engagement(
|
||||
cacheTrack.engagement.viewCount,
|
||||
cacheTrack.engagement.likeCount,
|
||||
cacheTrack.engagement.dislikeCount,
|
||||
),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Video> fromBackendTrack(
|
||||
BackendTrack track, YoutubeExplode youtube) {
|
||||
return youtube.videos.get(VideoId.fromString(track.youtubeId));
|
||||
}
|
||||
}
|
||||
|
||||
extension ThumbnailSetJson on ThumbnailSet {
|
||||
static ThumbnailSet fromJson(Map<String, dynamic> map) {
|
||||
return ThumbnailSet(map["videoId"]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
"videoId": videoId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension EngagementJson on Engagement {
|
||||
static Engagement fromJson(Map<String, dynamic> map) {
|
||||
return Engagement(
|
||||
map["viewCount"],
|
||||
map["likeCount"],
|
||||
map["dislikeCount"],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
"dislikeCount": dislikeCount,
|
||||
"likeCount": likeCount,
|
||||
"viewCount": viewCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension VideoToJson on Video {
|
||||
static Video fromJson(Map<String, dynamic> map) {
|
||||
return Video(
|
||||
VideoId(map["id"]),
|
||||
map["title"],
|
||||
map["author"],
|
||||
ChannelId(map["channelId"]),
|
||||
DateTime.tryParse(map["uploadDate"]),
|
||||
map["uploadDate"],
|
||||
DateTime.tryParse(map["publishDate"]),
|
||||
map["description"],
|
||||
parseDuration(map["duration"]),
|
||||
ThumbnailSetJson.fromJson(map["thumbnails"]),
|
||||
List.castFrom<dynamic, String>(map["keywords"]),
|
||||
EngagementJson.fromJson(map["engagement"]),
|
||||
map["isLive"],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
"hasWatchPage": hasWatchPage,
|
||||
"url": url,
|
||||
"author": author,
|
||||
"channelId": channelId.value,
|
||||
"description": description,
|
||||
"duration": duration.toString(),
|
||||
"engagement": engagement.toJson(),
|
||||
"id": id.value,
|
||||
"isLive": isLive,
|
||||
"keywords": keywords.toList(),
|
||||
"publishDate": publishDate.toString(),
|
||||
"thumbnails": thumbnails.toJson(),
|
||||
"title": title,
|
||||
"uploadDate": uploadDate.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension GetSkipSegments on Video {
|
||||
Future<List<Map<String, int>>> getSkipSegments(
|
||||
UserPreferences preferences) async {
|
||||
if (!preferences.skipSponsorSegments) return [];
|
||||
try {
|
||||
final res = await get(Uri(
|
||||
scheme: "https",
|
||||
host: "sponsor.ajay.app",
|
||||
path: "/api/skipSegments",
|
||||
queryParameters: {
|
||||
"videoID": id.value,
|
||||
"category": [
|
||||
'sponsor',
|
||||
'selfpromo',
|
||||
'interaction',
|
||||
'intro',
|
||||
'outro',
|
||||
'music_offtopic'
|
||||
],
|
||||
"actionType": 'skip'
|
||||
},
|
||||
));
|
||||
|
||||
if (res.body == "Not Found") {
|
||||
return List.castFrom<dynamic, Map<String, int>>([]);
|
||||
}
|
||||
|
||||
final data = jsonDecode(res.body) as List;
|
||||
final segments = data.map((obj) {
|
||||
return Map.castFrom<String, dynamic, String, int>({
|
||||
"start": obj["segment"].first.toInt(),
|
||||
"end": obj["segment"].last.toInt(),
|
||||
});
|
||||
}).toList();
|
||||
getLogger(Video).v(
|
||||
"[SponsorBlock] successfully fetched skip segments for $title | ${id.value}",
|
||||
);
|
||||
return List.castFrom<dynamic, Map<String, int>>(segments);
|
||||
} catch (e, stack) {
|
||||
Catcher.reportCheckedError(e, stack);
|
||||
return List.castFrom<dynamic, Map<String, int>>([]);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,14 +9,12 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:metadata_god/metadata_god.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
||||
import 'package:spotube/entities/cache_track.dart';
|
||||
import 'package:spotube/collections/routes.dart';
|
||||
import 'package:spotube/collections/intents.dart';
|
||||
import 'package:spotube/l10n/l10n.dart';
|
||||
@ -97,9 +95,6 @@ Future<void> main(List<String> rawArgs) async {
|
||||
cacheDir: (await getApplicationSupportDirectory()).path,
|
||||
);
|
||||
await PersistedStateNotifier.initializeBoxes();
|
||||
Hive.registerAdapter(CacheTrackAdapter());
|
||||
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
||||
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
|
||||
|
||||
Catcher(
|
||||
enableLogger: arguments["verbose"],
|
||||
|
@ -14,12 +14,16 @@ import 'package:spotube/provider/user_preferences_provider.dart';
|
||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||
import 'package:spotube/services/audio_services/audio_services.dart';
|
||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||
|
||||
/// Things to implement:
|
||||
/// * [x] Sponsor-Block skip
|
||||
/// * [x] Prefetch next track as [SpotubeTrack] on 80% of current track
|
||||
/// * [ ] Mixed Queue containing both [SpotubeTrack] and [LocalTrack]
|
||||
/// * [ ] Modification of the Queue
|
||||
/// * [ ] Add track at the end
|
||||
/// * [ ] Add track at the beginning
|
||||
/// * [ ] Remove track
|
||||
/// * [ ] Reorder track
|
||||
/// * [ ] Caching and loading of cache of tracks
|
||||
/// * [ ] Shuffling and loop => playlist, track, none
|
||||
/// * [ ] Alternative Track Source
|
||||
|
Loading…
Reference in New Issue
Block a user