Initial commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import '../../contracts/trakt/trakt_response.dart';
|
||||
import '../../contracts/trakt/trakt_sync_job.dart';
|
||||
|
||||
|
||||
abstract class AuthedTraktGateway {
|
||||
|
||||
Future<bool> isConnected();
|
||||
|
||||
|
||||
Future<TraktScrobbleOutcome> scrobble(
|
||||
TraktSyncJobType type,
|
||||
Map<String, dynamic> body,
|
||||
);
|
||||
|
||||
|
||||
Future<TraktScrobbleOutcome> syncHistory(
|
||||
TraktSyncJobType type,
|
||||
Map<String, dynamic> body,
|
||||
);
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>> fetchPlayback();
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>> fetchCalendarShows();
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>> fetchCalendarMovies();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import '../../contracts/danmaku.dart';
|
||||
|
||||
abstract class DanmakuGateway {
|
||||
|
||||
|
||||
Future<List<DanmakuMatch>> match(
|
||||
String baseUrl,
|
||||
String fileName,
|
||||
int durationSec,
|
||||
);
|
||||
|
||||
|
||||
Future<List<DanmakuMatch>> searchEpisodes(
|
||||
String baseUrl,
|
||||
String anime,
|
||||
int? episode,
|
||||
);
|
||||
|
||||
|
||||
Future<List<DanmakuComment>> fetchComments(
|
||||
String baseUrl,
|
||||
int episodeId, {
|
||||
int chConvert = 0,
|
||||
});
|
||||
|
||||
|
||||
Future<List<DanmakuBangumiEpisode>> getBangumiEpisodes(
|
||||
String baseUrl,
|
||||
int animeId,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import '../../contracts/danmaku.dart';
|
||||
|
||||
|
||||
abstract class DanmakuSourcesStore {
|
||||
|
||||
Future<List<DanmakuSource>> list();
|
||||
|
||||
|
||||
Future<void> replaceAll(List<DanmakuSource> sources);
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import '../../contracts/cancellation.dart';
|
||||
import '../../contracts/library.dart';
|
||||
import '../../contracts/playback.dart';
|
||||
import '../../contracts/server.dart';
|
||||
|
||||
|
||||
class AuthedRequestContext {
|
||||
final String baseUrl;
|
||||
final String token;
|
||||
final String userId;
|
||||
|
||||
const AuthedRequestContext({
|
||||
required this.baseUrl,
|
||||
required this.token,
|
||||
required this.userId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
class EmbyAuthResult {
|
||||
final String accessToken;
|
||||
final String userId;
|
||||
final String userName;
|
||||
|
||||
const EmbyAuthResult({
|
||||
required this.accessToken,
|
||||
required this.userId,
|
||||
required this.userName,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
abstract class EmbyGateway {
|
||||
Future<ProbePublicInfoRes> probePublicInfo(String baseUrl);
|
||||
|
||||
Future<EmbyAuthResult> authenticateByName({
|
||||
required String baseUrl,
|
||||
required String username,
|
||||
required String password,
|
||||
});
|
||||
|
||||
Future<void> changePassword({
|
||||
required AuthedRequestContext ctx,
|
||||
required String currentPassword,
|
||||
required String newPassword,
|
||||
});
|
||||
|
||||
Future<EmbyRawLibraries> getUserViews(AuthedRequestContext ctx);
|
||||
|
||||
Future<LibraryLatestRes> getLatestItems(
|
||||
AuthedRequestContext ctx,
|
||||
String parentId, {
|
||||
int? limit,
|
||||
CancellationToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<LibraryResumeRes> getResumeItems(
|
||||
AuthedRequestContext ctx, {
|
||||
int? limit,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawItem>> getLibraryItems({
|
||||
required AuthedRequestContext ctx,
|
||||
String? parentId,
|
||||
String? includeItemTypes,
|
||||
List<String>? genreIds,
|
||||
String? searchTerm,
|
||||
String? anyProviderIdEquals,
|
||||
List<String>? personIds,
|
||||
String? fields,
|
||||
String? enableImageTypes,
|
||||
bool? groupProgramsBySeries,
|
||||
int? imageTypeLimit,
|
||||
int? startIndex,
|
||||
int? limit,
|
||||
bool? recursive,
|
||||
String? sortBy,
|
||||
SortOrder? sortOrder,
|
||||
String? filters,
|
||||
CancellationToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawItem>> getFavoriteItems({
|
||||
required AuthedRequestContext ctx,
|
||||
required String includeItemTypes,
|
||||
required String sortBy,
|
||||
SortOrder? sortOrder,
|
||||
});
|
||||
|
||||
Future<ItemCountsRes> getItemCounts(AuthedRequestContext ctx);
|
||||
|
||||
Future<EmbyRawItem> getItemDetail(AuthedRequestContext ctx, String itemId);
|
||||
|
||||
Future<List<EmbyRawItem>> getSeriesNextUp(
|
||||
AuthedRequestContext ctx,
|
||||
String seriesId, {
|
||||
int? limit,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawSeason>> getSeriesSeasons(
|
||||
AuthedRequestContext ctx,
|
||||
String seriesId, {
|
||||
CancellationToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawItem>> getSeriesEpisodes(
|
||||
AuthedRequestContext ctx,
|
||||
String seriesId,
|
||||
String seasonId, {
|
||||
CancellationToken? cancelToken,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawItem>> getSimilarItems(
|
||||
AuthedRequestContext ctx,
|
||||
String itemId, {
|
||||
int? limit,
|
||||
});
|
||||
|
||||
Future<List<EmbyRawItem>> getAdditionalParts(
|
||||
AuthedRequestContext ctx,
|
||||
String itemId,
|
||||
);
|
||||
|
||||
Future<List<EmbyRawItem>> getSpecialFeatures(
|
||||
AuthedRequestContext ctx,
|
||||
String itemId,
|
||||
);
|
||||
|
||||
Future<bool> setFavoriteStatus({
|
||||
required AuthedRequestContext ctx,
|
||||
required String itemId,
|
||||
required bool isFavorite,
|
||||
});
|
||||
|
||||
Future<bool> setPlayedStatus({
|
||||
required AuthedRequestContext ctx,
|
||||
required String itemId,
|
||||
required bool played,
|
||||
});
|
||||
|
||||
Future<bool> hideFromResume({
|
||||
required AuthedRequestContext ctx,
|
||||
required String itemId,
|
||||
required bool hide,
|
||||
});
|
||||
|
||||
Future<void> reportPlaybackStarted({
|
||||
required AuthedRequestContext ctx,
|
||||
required PlaybackReportPayload payload,
|
||||
});
|
||||
|
||||
Future<void> reportPlaybackProgress({
|
||||
required AuthedRequestContext ctx,
|
||||
required PlaybackReportPayload payload,
|
||||
});
|
||||
|
||||
Future<void> reportPlaybackStopped({
|
||||
required AuthedRequestContext ctx,
|
||||
required PlaybackReportPayload payload,
|
||||
});
|
||||
|
||||
|
||||
Future<Map<String, dynamic>> fetchPlaybackInfo({
|
||||
required AuthedRequestContext ctx,
|
||||
required String itemId,
|
||||
String? mediaSourceId,
|
||||
int startTimeTicks = 0,
|
||||
bool isPlayback = false,
|
||||
required Map<String, dynamic> deviceProfile,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class ScriptWidgetRemoteGateway {
|
||||
Future<String> fetchText(String url);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import '../../contracts/script_widget.dart';
|
||||
|
||||
abstract class ScriptWidgetRepository {
|
||||
Future<List<InstalledScriptWidget>> listWidgets();
|
||||
|
||||
Future<InstalledScriptWidget?> findWidget(String widgetId);
|
||||
|
||||
Future<void> upsertWidget(InstalledScriptWidget widget);
|
||||
|
||||
Future<void> deleteWidget(String widgetId);
|
||||
|
||||
Future<List<ScriptWidgetSubscription>> listSubscriptions();
|
||||
|
||||
Future<void> upsertSubscription(ScriptWidgetSubscription subscription);
|
||||
|
||||
|
||||
Future<void> replaceAllWidgets(List<InstalledScriptWidget> widgets);
|
||||
|
||||
|
||||
Future<void> replaceAllSubscriptions(
|
||||
List<ScriptWidgetSubscription> subscriptions,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import '../../contracts/script_widget.dart';
|
||||
|
||||
abstract class ScriptWidgetRuntime {
|
||||
Future<ScriptWidgetManifest> inspectWidget(String scriptSource);
|
||||
|
||||
Future<ScriptWidgetManifest> loadWidget(String scriptSource);
|
||||
|
||||
bool isWidgetLoaded(String widgetId);
|
||||
|
||||
Future<Object?> invokeModuleFunction(
|
||||
String widgetId,
|
||||
String functionName,
|
||||
Map<String, Object?> params,
|
||||
);
|
||||
|
||||
Future<void> unloadWidget(String widgetId);
|
||||
|
||||
Future<void> dispose();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import '../../contracts/server.dart';
|
||||
|
||||
abstract class ServerRepository {
|
||||
Future<List<EmbyServer>> list();
|
||||
Future<EmbyServer?> findById(String id);
|
||||
Future<EmbyServer?> findByBaseUrl(String baseUrl);
|
||||
Future<EmbyServer> create(EmbyServer server);
|
||||
Future<EmbyServer> update(EmbyServer server);
|
||||
Future<void> deleteById(String id);
|
||||
Future<void> touchConnectedAt(String id, String updatedAt);
|
||||
|
||||
|
||||
Future<void> replaceAll(List<EmbyServer> servers);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
library;
|
||||
|
||||
|
||||
class ServerSyncSnapshot {
|
||||
final String? blob;
|
||||
|
||||
const ServerSyncSnapshot({this.blob});
|
||||
|
||||
bool get isEmpty => blob == null || blob!.trim().isEmpty;
|
||||
}
|
||||
|
||||
abstract class ServerSyncGateway {
|
||||
|
||||
|
||||
Future<ServerSyncSnapshot> pull({
|
||||
required String baseUrl,
|
||||
required String accessToken,
|
||||
});
|
||||
|
||||
|
||||
Future<void> push({
|
||||
required String baseUrl,
|
||||
required String accessToken,
|
||||
required String blob,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import '../../contracts/auth.dart';
|
||||
|
||||
abstract class SessionRepository {
|
||||
Future<SessionData> set(SessionData session);
|
||||
|
||||
|
||||
Future<void> setMany(List<SessionData> sessions);
|
||||
|
||||
|
||||
Future<void> replaceAll(List<SessionData> sessions, {String? activeServerId});
|
||||
|
||||
Future<SessionData?> getByServerId(String serverId);
|
||||
Future<SessionData?> getActive();
|
||||
Future<String?> getActiveServerId();
|
||||
Future<List<SessionData>> listAll();
|
||||
Future<void> setActive(String serverId);
|
||||
Future<void> clear([String? serverId]);
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
|
||||
|
||||
library;
|
||||
|
||||
|
||||
class SmLoginResult {
|
||||
final bool ok;
|
||||
final String email;
|
||||
|
||||
|
||||
final String accessToken;
|
||||
|
||||
|
||||
final String refreshToken;
|
||||
|
||||
final int expiresIn;
|
||||
|
||||
|
||||
final bool isVip;
|
||||
|
||||
|
||||
final int? vipExpiresAt;
|
||||
|
||||
|
||||
final bool vipPermanent;
|
||||
|
||||
|
||||
final bool needsVerification;
|
||||
|
||||
final String? message;
|
||||
|
||||
const SmLoginResult({
|
||||
required this.ok,
|
||||
this.email = '',
|
||||
this.accessToken = '',
|
||||
this.refreshToken = '',
|
||||
this.expiresIn = 0,
|
||||
this.isVip = false,
|
||||
this.vipExpiresAt,
|
||||
this.vipPermanent = false,
|
||||
this.needsVerification = false,
|
||||
this.message,
|
||||
});
|
||||
|
||||
factory SmLoginResult.failure(
|
||||
String message, {
|
||||
bool needsVerification = false,
|
||||
}) => SmLoginResult(
|
||||
ok: false,
|
||||
needsVerification: needsVerification,
|
||||
message: message,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class SmTokenRefreshResult {
|
||||
final bool ok;
|
||||
final String accessToken;
|
||||
final String refreshToken;
|
||||
final int expiresIn;
|
||||
|
||||
|
||||
final bool isVip;
|
||||
final int? vipExpiresAt;
|
||||
final bool vipPermanent;
|
||||
|
||||
|
||||
final bool hasVipInfo;
|
||||
|
||||
|
||||
final bool invalidRefreshToken;
|
||||
final String? message;
|
||||
|
||||
const SmTokenRefreshResult({
|
||||
required this.ok,
|
||||
this.accessToken = '',
|
||||
this.refreshToken = '',
|
||||
this.expiresIn = 0,
|
||||
this.isVip = false,
|
||||
this.vipExpiresAt,
|
||||
this.vipPermanent = false,
|
||||
this.hasVipInfo = false,
|
||||
this.invalidRefreshToken = false,
|
||||
this.message,
|
||||
});
|
||||
|
||||
factory SmTokenRefreshResult.failure(
|
||||
String message, {
|
||||
bool invalidRefreshToken = false,
|
||||
}) => SmTokenRefreshResult(
|
||||
ok: false,
|
||||
invalidRefreshToken: invalidRefreshToken,
|
||||
message: message,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class SmActionResult {
|
||||
final bool ok;
|
||||
final String? message;
|
||||
|
||||
const SmActionResult({required this.ok, this.message});
|
||||
|
||||
factory SmActionResult.success() => const SmActionResult(ok: true);
|
||||
|
||||
factory SmActionResult.failure(String message) =>
|
||||
SmActionResult(ok: false, message: message);
|
||||
}
|
||||
|
||||
|
||||
abstract class SmAccountGateway {
|
||||
|
||||
|
||||
Future<SmLoginResult> login({
|
||||
required String baseUrl,
|
||||
required String email,
|
||||
required String password,
|
||||
});
|
||||
|
||||
|
||||
Future<SmActionResult> registerStart({
|
||||
required String baseUrl,
|
||||
required String email,
|
||||
});
|
||||
|
||||
|
||||
Future<SmLoginResult> registerVerify({
|
||||
required String baseUrl,
|
||||
required String email,
|
||||
required String password,
|
||||
required String code,
|
||||
});
|
||||
|
||||
|
||||
Future<SmActionResult> resendCode({
|
||||
required String baseUrl,
|
||||
required String email,
|
||||
});
|
||||
|
||||
|
||||
Future<void> logout({required String baseUrl, required String refreshToken});
|
||||
|
||||
|
||||
Future<SmTokenRefreshResult> refreshAccessToken({
|
||||
required String baseUrl,
|
||||
required String refreshToken,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import '../../contracts/tmdb.dart';
|
||||
|
||||
|
||||
class TmdbRequestConfig {
|
||||
final String apiBaseUrl;
|
||||
final String imageBaseUrl;
|
||||
final String accessToken;
|
||||
final String apiKey;
|
||||
|
||||
|
||||
final Future<String?> Function()? onUnauthorized;
|
||||
|
||||
const TmdbRequestConfig({
|
||||
required this.apiBaseUrl,
|
||||
required this.imageBaseUrl,
|
||||
this.accessToken = '',
|
||||
this.apiKey = '',
|
||||
this.onUnauthorized,
|
||||
});
|
||||
}
|
||||
|
||||
abstract class TmdbGateway {
|
||||
Future<TmdbCreditsRes?> getCredits(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getRecommendations(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbSeasonDetail?> getSeasonDetail(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
int seasonNumber, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbImageSet?> getImages(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbEnrichedDetail?> getEnrichedDetail(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
List<String> appendToResponse,
|
||||
});
|
||||
|
||||
Future<TmdbVideosRes?> getVideos(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbPersonDetail?> getPersonDetail(
|
||||
TmdbRequestConfig config,
|
||||
int personId, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbPersonCreditsRes?> getPersonCredits(
|
||||
TmdbRequestConfig config,
|
||||
int personId, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbMediaDetail?> getMediaDetail(
|
||||
TmdbRequestConfig config,
|
||||
String tmdbId,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getTrending(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
String mediaType,
|
||||
String timeWindow,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getPopularMovies(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getPopularTv(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getAiringTodayTv(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
Future<TmdbRecommendationsRes?> getTopRatedMovies(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
});
|
||||
|
||||
|
||||
Future<TmdbRecommendationsRes?> getDiscover(
|
||||
TmdbRequestConfig config,
|
||||
String mediaType, {
|
||||
required String language,
|
||||
String sortBy = 'popularity.desc',
|
||||
String? withGenres,
|
||||
String? voteCountGte,
|
||||
});
|
||||
|
||||
Future<bool> testConnection(
|
||||
TmdbRequestConfig config, {
|
||||
required String language,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import '../../contracts/trakt/trakt_token.dart';
|
||||
import '../../contracts/trakt/trakt_user.dart';
|
||||
|
||||
|
||||
abstract class TraktGateway {
|
||||
|
||||
Future<TraktToken> exchangeCode(String code);
|
||||
|
||||
|
||||
Future<TraktToken> refreshToken(String refreshToken);
|
||||
|
||||
|
||||
Future<TraktUser> getMe(String accessToken);
|
||||
}
|
||||
Reference in New Issue
Block a user