Skip to content

Commit

Permalink
Project import generated by Copybara.
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 478aa0586cb2eea16867f7ca78cdf7913e5d3795
  • Loading branch information
Madari Developers committed Jan 5, 2025
1 parent c38cd84 commit e8e1c5e
Show file tree
Hide file tree
Showing 12 changed files with 575 additions and 411 deletions.
4 changes: 4 additions & 0 deletions lib/database/quries/watch_history_queries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ class WatchHistoryQueries extends DatabaseAccessor<AppDatabase>
return (select(watchHistoryTable)..where((t) => t.id.equals(id)))
.getSingleOrNull();
}

Future<void> clearWatchHistory() async {
await delete(watchHistoryTable).go();
}
}
3 changes: 1 addition & 2 deletions lib/engine/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ class AppEngine {

AppEngine(AuthStore authStore) {
pb = PocketBase(
// 'https://zeee.fly.dev' ??
(kDebugMode ? 'http://100.64.0.1:8090' : 'https://zeee.fly.dev'),
(kDebugMode ? 'http://100.64.0.1:8090' : 'https://api.madari.media'),
authStore: authStore,
);
_databaseProvider = DatabaseProvider();
Expand Down
15 changes: 14 additions & 1 deletion lib/features/connections/service/base_connection_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ abstract class BaseConnectionService {

Future<LibraryItem?> getItemById(LibraryItem id);

Stream<List<StreamList>> getStreams(
Future<void> getStreams(
LibraryRecord library,
LibraryItem id, {
String? season,
String? episode,
OnStreamCallback? callback,
});

BaseConnectionService({
Expand All @@ -106,11 +107,23 @@ class StreamList {
final String title;
final String? description;
final DocSource source;
final StreamSource? streamSource;

StreamList({
required this.title,
this.description,
required this.source,
this.streamSource,
});
}

class StreamSource {
final String title;
final String id;

StreamSource({
required this.title,
required this.id,
});
}

Expand Down
212 changes: 132 additions & 80 deletions lib/features/connections/service/stremio_connection_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ part 'stremio_connection_service.g.dart';

final Map<String, String> manifestCache = {};

typedef OnStreamCallback = void Function(List<StreamList>? items, Error?);

class StremioConnectionService extends BaseConnectionService {
final StremioConfig config;

Expand Down Expand Up @@ -224,120 +226,170 @@ class StremioConnectionService extends BaseConnectionService {
}

@override
Stream<List<StreamList>> getStreams(
Future<void> getStreams(
LibraryRecord library,
LibraryItem id, {
String? season,
String? episode,
}) async* {
OnStreamCallback? callback,
}) async {
final List<StreamList> streams = [];
final meta = id as Meta;

for (final addon in config.addons) {
final addonManifest = await _getManifest(addon);

for (final _resource in (addonManifest.resources ?? [])) {
final resource = _resource as ResourceObject;

if (resource.name != "stream") {
continue;
}

final idPrefixes = resource.idPrefixes ?? addonManifest.idPrefixes;
final types = resource.types ?? addonManifest.types;
final List<Future<void>> promises = [];

if (types == null || !types.contains(meta.type)) {
continue;
}
for (final addon in config.addons) {
final future = Future.delayed(const Duration(seconds: 0), () async {
final addonManifest = await _getManifest(addon);

final hasIdPrefix = (idPrefixes ?? []).where(
(item) => meta.id.startsWith(item),
);
for (final resource_ in (addonManifest.resources ?? [])) {
final resource = resource_ as ResourceObject;

if (hasIdPrefix.isEmpty) {
continue;
}
if (!doesAddonSupportStream(resource, addonManifest, meta)) {
continue;
}

try {
final url =
"${_getAddonBaseURL(addon)}/stream/${meta.type}/${Uri.encodeComponent(id.id)}.json";

final result = await http.get(Uri.parse(url), headers: {});

if (result.statusCode == 404) {
if (callback != null) {
callback(
null,
ArgumentError(
"Invalid status code for the addon ${addonManifest.name} with id ${addonManifest.id}",
),
);
}
continue;
}

final body = StreamResponse.fromJson(jsonDecode(result.body));

streams.addAll(
body.streams
.map((item) {
String streamTitle = item.title ?? item.name ?? "No title";

try {
streamTitle = utf8.decode(
(item.title ?? item.name ?? "No Title").runes.toList(),
);
} catch (e) {}

final streamDescription = item.description != null
? utf8.decode(
(item.description!).runes.toList(),
)
: null;

String title = meta.name ?? item.title ?? "No title";

if (season != null) title += " S$season";
if (episode != null) title += " E$episode";

DocSource? source;

if (item.url != null) {
source = MediaURLSource(
title: title,
url: item.url!,
id: meta.id,
);
}

if (item.infoHash != null) {
source = TorrentSource(
title: title,
infoHash: item.infoHash!,
id: meta.id,
fileName: "$title.mp4",
season: season,
episode: episode,
);
}

if (source == null) {
return null;
}

return StreamList(
title: streamTitle,
description: streamDescription,
source: source,
);
})
.map(
(item) => videoStreamToStreamList(
item, meta, season, episode, addonManifest),
)
.whereType<StreamList>()
.toList(),
);
} catch (e) {
continue;

if (callback != null) {
callback(streams, null);
}
}
}).catchError((error) {
if (callback != null) callback(null, error);
});

if (streams.isNotEmpty) yield streams;
}
promises.add(future);
}

yield streams;
await Future.wait(promises);

return;
}

bool doesAddonSupportStream(
ResourceObject resource,
StremioManifest addonManifest,
Meta meta,
) {
if (resource.name != "stream") {
return false;
}

final idPrefixes = resource.idPrefixes ?? addonManifest.idPrefixes;
final types = resource.types ?? addonManifest.types;

if (types == null || !types.contains(meta.type)) {
return false;
}

final hasIdPrefix = (idPrefixes ?? []).where(
(item) => meta.id.startsWith(item),
);

if (hasIdPrefix.isEmpty) {
return false;
}

return true;
}

StreamList? videoStreamToStreamList(
VideoStream item,
Meta meta,
String? season,
String? episode,
StremioManifest addonManifest,
) {
String streamTitle =
(item.name != null ? "${item.name} ${item.title}" : item.title) ??
"No title";

try {
streamTitle = utf8.decode(streamTitle.runes.toList());
} catch (e) {}

final streamDescription = item.description != null
? utf8.decode(
(item.description!).runes.toList(),
)
: null;

String title = meta.name ?? item.title ?? "No title";

if (season != null) title += " S$season";
if (episode != null) title += " E$episode";

DocSource? source;

if (item.url != null) {
source = MediaURLSource(
title: title,
url: item.url!,
id: meta.id,
);
}

if (item.infoHash != null) {
source = TorrentSource(
title: title,
infoHash: item.infoHash!,
id: meta.id,
fileName: "$title.mp4",
season: season,
episode: episode,
);
}

if (source == null) {
return null;
}

String addonName = addonManifest.name;

try {
addonName = utf8.decode(
(addonName).runes.toList(),
);
} catch (e) {}

return StreamList(
title: streamTitle,
description: streamDescription,
source: source,
streamSource: StreamSource(
title: addonName,
id: addonManifest.id,
),
);
}
}

@JsonSerializable()
Expand Down
20 changes: 14 additions & 6 deletions lib/features/connections/types/stremio/stremio_base.types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ class Meta extends LibraryItem {
@JsonKey(name: "genre")
final List<String>? genre;
@JsonKey(name: "imdbRating")
final String? imdbRating;
final dynamic imdbRating_;
@JsonKey(name: "poster")
String? poster;
@JsonKey(name: "released")
Expand Down Expand Up @@ -281,7 +281,7 @@ class Meta extends LibraryItem {
@JsonKey(name: "genres")
final List<String>? genres;
@JsonKey(name: "releaseInfo")
final String? releaseInfo;
final dynamic releaseInfo_;
@JsonKey(name: "trailerStreams")
final List<TrailerStream>? trailerStreams;
@JsonKey(name: "links")
Expand All @@ -297,6 +297,14 @@ class Meta extends LibraryItem {
@JsonKey(name: "dvdRelease")
final DateTime? dvdRelease;

String get imdbRating {
return (imdbRating_ ?? "").toString();
}

String get releaseInfo {
return (releaseInfo_).toString();
}

Meta({
this.imdbId,
this.name,
Expand All @@ -306,7 +314,7 @@ class Meta extends LibraryItem {
this.country,
this.description,
this.genre,
this.imdbRating,
this.imdbRating_,
this.poster,
this.released,
this.slug,
Expand All @@ -325,7 +333,7 @@ class Meta extends LibraryItem {
required this.id,
this.videos,
this.genres,
this.releaseInfo,
this.releaseInfo_,
this.trailerStreams,
this.links,
this.behaviorHints,
Expand Down Expand Up @@ -381,7 +389,7 @@ class Meta extends LibraryItem {
country: country ?? this.country,
description: description ?? this.description,
genre: genre ?? this.genre,
imdbRating: imdbRating ?? this.imdbRating,
imdbRating_: imdbRating ?? imdbRating_.toString(),
poster: poster ?? this.poster,
released: released ?? this.released,
slug: slug ?? this.slug,
Expand All @@ -400,7 +408,7 @@ class Meta extends LibraryItem {
id: id ?? this.id,
videos: videos ?? this.videos,
genres: genres ?? this.genres,
releaseInfo: releaseInfo ?? this.releaseInfo,
releaseInfo_: releaseInfo ?? this.releaseInfo,
trailerStreams: trailerStreams ?? this.trailerStreams,
links: links ?? this.links,
behaviorHints: behaviorHints ?? this.behaviorHints,
Expand Down
Loading

0 comments on commit e8e1c5e

Please sign in to comment.