Skip to content

Commit a26ee08

Browse files
authored
Merge pull request #8 from kodify-js/aniwave-fix
Refactor aniwave season play fix
2 parents 6944785 + b9b7a57 commit a26ee08

18 files changed

+169
-141
lines changed

lib/api/api.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,10 @@ class Api {
390390
seasons: []);
391391
if (type == ContentType.tv.value) {
392392
for (var data in (response['seasons'] as List)) {
393-
Season season =
394-
Season(id: data['id'], season: data['season_number']);
393+
Season season = Season(
394+
id: data['id'],
395+
season: data['season_number'],
396+
airDate: data['air_date']);
395397
content.seasons?.add(season);
396398
}
397399
}
@@ -428,7 +430,6 @@ class Api {
428430
final response = jsonDecode(data.body);
429431
if (response['status_code'] != null)
430432
throw Exception("Failed to fetch data");
431-
432433
final List<Episode> episodes = (response['episodes'] as List)
433434
.where((episode) => episode['still_path'] != null)
434435
.map((episode) => Episode(

lib/api/class/content_class.dart

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,34 @@ part 'content_class.g.dart';
66
class Contentclass {
77
@HiveField(0)
88
final int id;
9-
9+
1010
@HiveField(1)
1111
final String backdrop;
12-
12+
1313
@HiveField(2)
1414
final String title;
15-
15+
1616
@HiveField(3)
1717
final String language;
18-
18+
1919
@HiveField(4)
2020
final List<dynamic> genres;
21-
21+
2222
@HiveField(5)
2323
final String type;
24-
24+
2525
@HiveField(6)
2626
final String description;
27-
27+
2828
@HiveField(7)
2929
final String poster;
30-
30+
3131
@HiveField(8)
3232
String? logoPath;
33-
33+
3434
@HiveField(9)
3535
double? rating;
36-
36+
3737
@HiveField(10)
3838
List<Season>? seasons;
3939

@@ -90,26 +90,32 @@ class Contentclass {
9090
class Season {
9191
@HiveField(0)
9292
final int id;
93-
93+
9494
@HiveField(1)
9595
final int season;
9696

97+
@HiveField(2)
98+
final String? airDate;
99+
97100
Season({
98101
required this.id,
99102
required this.season,
103+
this.airDate,
100104
});
101105

102106
Map<String, dynamic> toJson() {
103107
return {
104108
'id': id,
105109
'season': season,
110+
'airDate': airDate,
106111
};
107112
}
108113

109114
factory Season.fromJson(Map<String, dynamic> json) {
110115
return Season(
111116
id: json['id'] as int,
112117
season: json['season'] as int,
118+
airDate: json['airDate'] as String?,
113119
);
114120
}
115-
}
121+
}

lib/api/class/episode_class.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
class Episode{
1+
class Episode {
22
final int id;
33
final String name;
44
final int episode;
@@ -13,6 +13,6 @@ class Episode{
1313
required this.season,
1414
required this.description,
1515
required this.airDate,
16-
required this.image
16+
required this.image,
1717
});
18-
}
18+
}

lib/api/contentproviders/anime_providers/aniwave.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ class Aniwave {
2626
final String? name;
2727
bool isError = false;
2828
final List? animeEpisodes;
29+
final String? airDate;
2930
Aniwave(
3031
{required this.title,
3132
required this.type,
3233
this.episodeNumber,
3334
this.seasonNumber,
35+
this.airDate,
3436
this.name = 'Aniwave',
3537
this.animeEpisodes});
3638

@@ -84,9 +86,11 @@ class Aniwave {
8486
try {
8587
List episode = animeEpisodes ?? [];
8688
final List<StreamClass> streams = [];
89+
print(
90+
'https://aniwave.at/catalog?keyword=$title${airDate != null ? ("&year=${airDate?.split("-").first}") : ""}');
8791
if (episode.isEmpty) {
88-
final data = await http
89-
.get(Uri.parse('https://aniwave.at/catalog?keyword=$title'));
92+
final data = await http.get(Uri.parse(
93+
'https://aniwave.at/catalog?keyword=$title${airDate != null ? ("&year=${airDate?.split("-").first}") : ""}'));
9094
final document = parse(data.body);
9195
final results = document.querySelectorAll("div.mt-6 div.grid a");
9296
if (results.isEmpty)

lib/api/contentproviders/contentprovider.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ class ContentProvider {
3939

4040
final bool? isAnime;
4141

42+
final String? airDate;
43+
4244
ContentProvider(
4345
{required this.id,
4446
required this.type,
4547
required this.title,
4648
this.isAnime = false,
4749
this.episodeNumber,
50+
this.airDate,
4851
this.seasonNumber,
4952
this.animeEpisode});
5053

@@ -88,6 +91,7 @@ class ContentProvider {
8891
Aniwave get aniwave => Aniwave(
8992
title: title,
9093
type: type,
94+
airDate: airDate,
9195
episodeNumber: episodeNumber,
9296
seasonNumber: seasonNumber,
9397
animeEpisodes: animeEpisode);

lib/api/contentproviders/movie-tv_providers/embed.dart

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ class Embed {
8787
"Accept": "*/*"
8888
}).timeout(const Duration(seconds: 5));
8989
final data = jsonDecode(response.body);
90-
final sourceUrl =
91-
data['source'].toString().replaceAll("embed.su/api/proxy/viper/", "");
90+
print(data);
91+
final sourceUrl = data['source'].toString();
9292
final sources = await _getSources(url: sourceUrl);
9393
return StreamClass(
9494
language: 'original',
@@ -114,13 +114,20 @@ class Embed {
114114
return [SourceClass(quality: "Auto", url: url)];
115115
}
116116

117-
final response = await http.get(Uri.parse(url));
117+
final response = await http.get(Uri.parse(url), headers: {
118+
"Referer": baseUrl,
119+
"User-Agent":
120+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
121+
"Accept": "*/*"
122+
});
123+
print(response.body);
118124
final sources = _parseM3U8Playlist(response.body, url);
119125
if (sources.isEmpty) throw "No valid sources found";
120126
isError = false;
121127
return sources;
122128
} catch (e) {
123129
isError = true;
130+
print("Error: $e");
124131
return [];
125132
}
126133
}
@@ -133,7 +140,7 @@ class Embed {
133140
if (lines[i].contains('#EXT-X-STREAM-INF')) {
134141
final quality = _extractQuality(lines[i]);
135142
if (quality != null && i + 1 < lines.length) {
136-
final streamUrl = _resolveStreamUrl(lines[i + 1], baseUrl);
143+
final streamUrl = _resolveStreamUrl(lines[i + 1]);
137144
sources.add(SourceClass(quality: quality, url: streamUrl));
138145
}
139146
}
@@ -147,10 +154,9 @@ class Embed {
147154
return match?.group(1);
148155
}
149156

150-
String _resolveStreamUrl(String streamUrl, String baseUrl) {
151-
final resolvedUri = streamUrl
152-
.replaceAll("/api/proxy/viper/", "https://")
153-
.replaceAll(".png", ".m3u8");
157+
String _resolveStreamUrl(String streamUrl) {
158+
final resolvedUri =
159+
Uri.parse(baseUrl).resolve(streamUrl.replaceAll('.png', '.m3u8'));
154160
return resolvedUri.toString();
155161
}
156162
}

lib/api/contentproviders/movie-tv_providers/vidsrcsu.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class VidSrcSu {
113113
? _resolveStreamUrl(
114114
lines[i + 1].split('./')[1].trim(), lines[i + 1])
115115
: lines[i + 1];
116+
print('Stream URL: $streamUrl');
116117
sources.add(SourceClass(quality: quality, url: streamUrl));
117118
}
118119
}

lib/components/carousel.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ class Carousel extends StatelessWidget {
217217
MaterialPageRoute(
218218
builder: (context) => Infopage(
219219
id: data.id,
220-
name: data.title,
220+
title: data.title,
221221
type: data.type,
222222
),
223223
),

lib/components/episodes_list.dart

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import 'package:moviedex/pages/watch_page.dart';
88
class EpisodesList extends StatefulWidget {
99
final Episode episode;
1010
final Contentclass data;
11-
const EpisodesList({super.key,required this.episode,required this.data});
11+
final String? airDate;
12+
const EpisodesList(
13+
{super.key, required this.episode, required this.data, this.airDate});
1214

1315
@override
1416
State<EpisodesList> createState() => _EpisodesListState();
@@ -24,19 +26,27 @@ class _EpisodesListState extends State<EpisodesList> {
2426
super.initState();
2527
Hive.openBox(widget.data.title).then((value) => storage = value);
2628
}
29+
2730
@override
2831
Widget build(BuildContext context) {
2932
final width = MediaQuery.of(context).size.width;
30-
final isMobile = width<600;
33+
final isMobile = width < 600;
3134
final episode = widget.episode;
3235
return GestureDetector(
3336
onTapDown: (_) => setState(() => isPressed = true),
3437
onTapUp: (_) => setState(() => isPressed = false),
3538
onTapCancel: () => setState(() => isPressed = false),
36-
onTap: (){
37-
hivePut(storage:storage,key: "episode",value: 'E${episode.episode}');
38-
hivePut(storage: storage,key: "season",value: 'S${episode.season}');
39-
Navigator.of(context).push(MaterialPageRoute(builder: (context) => WatchPage(data: widget.data,episodeNumber: episode.episode,seasonNumber: episode.season,title: episode.name,)));
39+
onTap: () {
40+
hivePut(storage: storage, key: "episode", value: 'E${episode.episode}');
41+
hivePut(storage: storage, key: "season", value: 'S${episode.season}');
42+
Navigator.of(context).push(MaterialPageRoute(
43+
builder: (context) => WatchPage(
44+
data: widget.data,
45+
episodeNumber: episode.episode,
46+
seasonNumber: episode.season,
47+
airDate: widget.airDate,
48+
title: episode.name,
49+
)));
4050
},
4151
child: MouseRegion(
4252
cursor: SystemMouseCursors.click,
@@ -52,49 +62,70 @@ class _EpisodesListState extends State<EpisodesList> {
5262
spacing: 8,
5363
children: [
5464
Card(
55-
clipBehavior: Clip.antiAlias,
56-
shape: RoundedRectangleBorder(
57-
borderRadius: BorderRadius.circular(8),
58-
),
59-
child: Stack(
60-
alignment: Alignment.center,
61-
children: [
62-
Image.network(episode.image,fit: BoxFit.cover,width: isMobile?width/2.5:200,height: 100,),
63-
Container(
64-
width: isMobile?width/2.5:200,
65-
height: 100,
66-
color: Colors.black.withValues(alpha: 0.3),
67-
child: const Center(
68-
child: Icon(
69-
Icons.play_circle_outline_rounded,
70-
size: 42,
71-
color: Colors.white,
65+
clipBehavior: Clip.antiAlias,
66+
shape: RoundedRectangleBorder(
67+
borderRadius: BorderRadius.circular(8),
68+
),
69+
child: Stack(
70+
alignment: Alignment.center,
71+
children: [
72+
Image.network(
73+
episode.image,
74+
fit: BoxFit.cover,
75+
width: isMobile ? width / 2.5 : 200,
76+
height: 100,
77+
),
78+
Container(
79+
width: isMobile ? width / 2.5 : 200,
80+
height: 100,
81+
color: Colors.black.withValues(alpha: 0.3),
82+
child: const Center(
83+
child: Icon(
84+
Icons.play_circle_outline_rounded,
85+
size: 42,
86+
color: Colors.white,
87+
),
7288
),
7389
),
74-
),
75-
],
76-
)
77-
),
90+
],
91+
)),
7892
SizedBox(
79-
width: width/2,
93+
width: width / 2,
8094
child: Column(
8195
crossAxisAlignment: CrossAxisAlignment.start,
8296
children: [
83-
Text('${episode.episode}. ${episode.name}',maxLines: 2,style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,overflow: TextOverflow.ellipsis),),
84-
Text("Season ${episode.season} Episode ${episode.episode}",style: TextStyle(fontSize: 16,color: Colors.grey)),
85-
Text(episode.airDate,style: TextStyle(fontSize: 14,color: Colors.grey),),
97+
Text(
98+
'${episode.episode}. ${episode.name}',
99+
maxLines: 2,
100+
style: TextStyle(
101+
fontSize: 20,
102+
fontWeight: FontWeight.bold,
103+
overflow: TextOverflow.ellipsis),
104+
),
105+
Text(
106+
"Season ${episode.season} Episode ${episode.episode}",
107+
style: TextStyle(fontSize: 16, color: Colors.grey)),
108+
Text(
109+
episode.airDate,
110+
style: TextStyle(fontSize: 14, color: Colors.grey),
111+
),
86112
],
87113
),
88114
),
89115
],
90116
),
91117
Padding(
92118
padding: const EdgeInsets.all(8.0),
93-
child: Text(episode.description,maxLines: 3, style: TextStyle(fontSize: 14,color: Colors.grey,overflow: TextOverflow.ellipsis)),
119+
child: Text(episode.description,
120+
maxLines: 3,
121+
style: TextStyle(
122+
fontSize: 14,
123+
color: Colors.grey,
124+
overflow: TextOverflow.ellipsis)),
94125
),
95126
],
96127
),
97128
),
98129
);
99130
}
100-
}
131+
}

0 commit comments

Comments
 (0)