mirror of
https://github.com/madari-media/madari-oss.git
synced 2026-05-14 23:40:38 +00:00
mark watched from Trakt
This commit is contained in:
parent
f129eb7360
commit
6f044446f9
3 changed files with 185 additions and 3 deletions
|
|
@ -41,6 +41,7 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
||||||
late Meta meta = widget.meta;
|
late Meta meta = widget.meta;
|
||||||
|
|
||||||
final Map<String, double> _progress = {};
|
final Map<String, double> _progress = {};
|
||||||
|
Map<int, Set<int>> watchedEpisodesBySeason = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
@ -64,6 +65,7 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
||||||
});
|
});
|
||||||
|
|
||||||
getWatchHistory();
|
getWatchHistory();
|
||||||
|
getWatchedHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getSelectedSeason() {
|
int getSelectedSeason() {
|
||||||
|
|
@ -74,6 +76,52 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
||||||
widget.season ??
|
widget.season ??
|
||||||
0;
|
0;
|
||||||
}
|
}
|
||||||
|
getWatchedHistory() async {
|
||||||
|
final traktService = TraktService.instance;
|
||||||
|
try {
|
||||||
|
|
||||||
|
final result = await traktService!.getWatchedShowsWithEpisodes(widget.meta);
|
||||||
|
watchedEpisodesBySeason.clear();
|
||||||
|
print("Trakt Result: $result"); // Print the raw Trakt result
|
||||||
|
|
||||||
|
for (final show in result) {
|
||||||
|
print("Show Title: ${show.title}"); // Print the show title
|
||||||
|
if (show.episodes != null) {
|
||||||
|
print("Episodes for ${show.title}:");
|
||||||
|
for (final episode in show.episodes!) {
|
||||||
|
print(" - Season: ${episode.season}, Episode: ${episode.episode}, Watched At: ${episode.watchedAt}");
|
||||||
|
if (!watchedEpisodesBySeason.containsKey(episode.season)) {
|
||||||
|
watchedEpisodesBySeason[episode.season] = {};
|
||||||
|
}
|
||||||
|
watchedEpisodesBySeason[episode.season]!.add(episode.episode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("No episodes found for ${show.title}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Watched Episodes By Season: $watchedEpisodesBySeason"); // Print the final map
|
||||||
|
setState(() {});
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (e, stack) {
|
||||||
|
print("Error fetching Trakt data: $e");
|
||||||
|
print("Stack Trace: $stack");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool isEpisodeWatched(int season, int episode) {
|
||||||
|
return watchedEpisodesBySeason.containsKey(season) &&
|
||||||
|
watchedEpisodesBySeason[season]!.contains(episode);
|
||||||
|
}
|
||||||
|
bool isSeasonWatched(int season) {
|
||||||
|
if (!watchedEpisodesBySeason.containsKey(season)) {
|
||||||
|
return false; // No episodes watched in this season
|
||||||
|
}
|
||||||
|
if (seasonMap.containsKey(season)) {
|
||||||
|
return watchedEpisodesBySeason[season]!.length == seasonMap[season]!.length;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
getWatchHistory() async {
|
getWatchHistory() async {
|
||||||
final traktService = TraktService.instance;
|
final traktService = TraktService.instance;
|
||||||
|
|
@ -245,9 +293,14 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
||||||
splashBorderRadius: BorderRadius.circular(8),
|
splashBorderRadius: BorderRadius.circular(8),
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
tabs: seasons.map((season) {
|
tabs: seasons.map((season) {
|
||||||
|
final isWatched = isSeasonWatched(season);
|
||||||
return Tab(
|
return Tab(
|
||||||
text: season == 0 ? "Specials" : 'Season $season',
|
child: Text(
|
||||||
height: 40,
|
season == 0 ? "Specials" : 'Season $season',
|
||||||
|
style: TextStyle(
|
||||||
|
color: isWatched? Colors.green : Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
|
|
@ -354,7 +407,7 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (progress > .9)
|
if (isEpisodeWatched(currentSeason, episode.episode!))
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import '../../../engine/engine.dart';
|
||||||
import '../../connections/service/base_connection_service.dart';
|
import '../../connections/service/base_connection_service.dart';
|
||||||
import '../../connections/types/stremio/stremio_base.types.dart';
|
import '../../connections/types/stremio/stremio_base.types.dart';
|
||||||
import '../../settings/types/connection.dart';
|
import '../../settings/types/connection.dart';
|
||||||
|
import '../types/common.dart';
|
||||||
|
|
||||||
class TraktService {
|
class TraktService {
|
||||||
static final Logger _logger = Logger('TraktService');
|
static final Logger _logger = Logger('TraktService');
|
||||||
|
|
@ -1033,4 +1034,81 @@ class TraktService {
|
||||||
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
Future<List<TraktShowWatched>> getWatchedShowsWithEpisodes(Meta meta) async {
|
||||||
|
if (!isEnabled()) {
|
||||||
|
_logger.info('Trakt integration is not enabled');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (meta.type == "series" ) {
|
||||||
|
final watchedShows = await getWatchedShows();
|
||||||
|
for (final show in watchedShows) {
|
||||||
|
if(show.ids.imdb==meta.imdbId) {
|
||||||
|
// await Future.delayed(const Duration(seconds: 5));
|
||||||
|
show.episodes = await _getWatchedEpisodes(show.ids.trakt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return watchedShows;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
Future<List<TraktShowWatched>> getWatchedShows() async {
|
||||||
|
if (!isEnabled()) {
|
||||||
|
_logger.info('Trakt integration is not enabled');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final body = await _makeRequest(
|
||||||
|
"$_baseUrl/sync/watched/shows/",
|
||||||
|
bypassCache: true,
|
||||||
|
);
|
||||||
|
final List<TraktShowWatched> result = [];
|
||||||
|
for (final item in body) {
|
||||||
|
try {
|
||||||
|
result.add(
|
||||||
|
TraktShowWatched(
|
||||||
|
title: item["show"]["title"],
|
||||||
|
seasons: item["seasons"],
|
||||||
|
ids: TraktIds.fromJson(item["show"]["ids"]),
|
||||||
|
lastWatchedAt: item["last_watched_at"] != null ? DateTime.parse(item["last_watched_at"]) : null,
|
||||||
|
plays: item["plays"],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (e, stack) {
|
||||||
|
_logger.warning('Error parsing watched show: $e\n$stack item: $item');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (e, stack) {
|
||||||
|
_logger.severe('Error fetching watched shows: $e\n$stack');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Future<List<TraktEpisodeWatched>> _getWatchedEpisodes(int? traktId) async {
|
||||||
|
if (traktId == null) return [];
|
||||||
|
int page = 1;
|
||||||
|
const int limit = 1000;
|
||||||
|
try {
|
||||||
|
final body = await _makeRequest(
|
||||||
|
"$_baseUrl/sync/history/shows/$traktId?page=$page&limit=$limit",
|
||||||
|
bypassCache: true,
|
||||||
|
);
|
||||||
|
final List<TraktEpisodeWatched> episodes = [];
|
||||||
|
for (final item in body) {
|
||||||
|
if (item['episode'] != null) {
|
||||||
|
episodes.add(
|
||||||
|
TraktEpisodeWatched(
|
||||||
|
season: item['episode']['season'],
|
||||||
|
episode: item['episode']['number'],
|
||||||
|
watchedAt: DateTime.parse(item['watched_at']),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return episodes;
|
||||||
|
} catch (e, stack) {
|
||||||
|
_logger.severe('Error fetching watched episodes: $e\n$stack');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,54 @@ class TraktProgress {
|
||||||
this.traktId,
|
this.traktId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TraktShowWatched {
|
||||||
|
final String title;
|
||||||
|
final List<dynamic> seasons;
|
||||||
|
final TraktIds ids;
|
||||||
|
final DateTime? lastWatchedAt;
|
||||||
|
final int plays;
|
||||||
|
List<TraktEpisodeWatched>? episodes; // Add episodes list
|
||||||
|
|
||||||
|
TraktShowWatched({
|
||||||
|
required this.title,
|
||||||
|
required this.seasons,
|
||||||
|
required this.ids,
|
||||||
|
this.lastWatchedAt,
|
||||||
|
required this.plays,
|
||||||
|
this.episodes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class TraktIds {
|
||||||
|
final int? trakt;
|
||||||
|
final String? slug;
|
||||||
|
final String? imdb;
|
||||||
|
final int? tmdb;
|
||||||
|
|
||||||
|
TraktIds({
|
||||||
|
this.trakt,
|
||||||
|
this.slug,
|
||||||
|
this.imdb,
|
||||||
|
this.tmdb,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory TraktIds.fromJson(Map<String, dynamic> json) => TraktIds(
|
||||||
|
trakt: json['trakt'],
|
||||||
|
slug: json['slug'],
|
||||||
|
imdb: json['imdb'],
|
||||||
|
tmdb: json['tmdb'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TraktEpisodeWatched {
|
||||||
|
final int season;
|
||||||
|
final int episode;
|
||||||
|
final DateTime watchedAt;
|
||||||
|
|
||||||
|
TraktEpisodeWatched({
|
||||||
|
required this.season,
|
||||||
|
required this.episode,
|
||||||
|
required this.watchedAt,
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue