mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-07 20:15:24 +00:00
edited anime episode to stream response (better experience)
This commit is contained in:
parent
594db0272a
commit
6b22a90688
@ -2,6 +2,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
|
from django.http import StreamingHttpResponse
|
||||||
|
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
@ -50,7 +51,6 @@ class SearchView(viewsets.ViewSet):
|
|||||||
self.media_id = request.query_params.get("media_id")
|
self.media_id = request.query_params.get("media_id")
|
||||||
self.media_slug = request.data.get("media_slug")
|
self.media_slug = request.data.get("media_slug")
|
||||||
self.type_media = request.query_params.get("type_media")
|
self.type_media = request.query_params.get("type_media")
|
||||||
self.page = self.request.query_params.get("page")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
match self.type_media:
|
match self.type_media:
|
||||||
@ -81,22 +81,18 @@ class SearchView(viewsets.ViewSet):
|
|||||||
|
|
||||||
return Response({"episodes": episodes})
|
return Response({"episodes": episodes})
|
||||||
case "TV_ANIME":
|
case "TV_ANIME":
|
||||||
episodes = []
|
def stream_episodes():
|
||||||
episodes_downloader = EpisodeDownloader(
|
episodes_downloader = EpisodeDownloader(self.media_id, self.media_slug)
|
||||||
self.media_id, self.media_slug
|
|
||||||
)
|
|
||||||
episoded_count = episodes_downloader.get_count_episodes()
|
episoded_count = episodes_downloader.get_count_episodes()
|
||||||
items_per_page = 5
|
|
||||||
paginator = Paginator(range(episoded_count), items_per_page)
|
|
||||||
|
|
||||||
page_number = self.page if self.page else 1
|
for i in range(1, episoded_count+1):
|
||||||
page_indices = paginator.page(page_number)
|
|
||||||
|
|
||||||
for i in page_indices:
|
|
||||||
episode_info = episodes_downloader.get_info_episode(index_ep=i)
|
episode_info = episodes_downloader.get_info_episode(index_ep=i)
|
||||||
episode_info["episode_id"] = i
|
episode_info["episode_id"] = i
|
||||||
episodes.append(episode_info)
|
print(f"Getting episode {i} of {episoded_count} info...")
|
||||||
return Response({"episodes": episodes})
|
yield f'data: {json.dumps(episode_info)}\n\n'
|
||||||
|
|
||||||
|
response = StreamingHttpResponse(stream_episodes(), content_type='text/event-stream')
|
||||||
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios'
|
||||||
import type {MediaItemResponse} from "@/api/interfaces";
|
import type {MediaItemResponse} from '@/api/interfaces'
|
||||||
|
|
||||||
const BASE_URL = 'http://127.0.0.1:8000/api'
|
const BASE_URL = 'http://127.0.0.1:8000/api'
|
||||||
|
|
||||||
@ -14,3 +14,18 @@ function get(url: string): Promise<any> {
|
|||||||
export default function search(query: string, type: string) : Promise<MediaItemResponse> {
|
export default function search(query: string, type: string) : Promise<MediaItemResponse> {
|
||||||
return get(`/search?search_terms=${query}&type=${type}`)
|
return get(`/search?search_terms=${query}&type=${type}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getEpisodesInfo(mediaId: number, mediaSlug: string, mediaType: string): Promise<Response> {
|
||||||
|
const url = `${BASE_URL}/search/get_episodes_info?media_id=${mediaId}&media_slug=${mediaSlug}&type_media=${mediaType}`;
|
||||||
|
if (mediaType === 'TV_ANIME') {
|
||||||
|
return await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/event-stream'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(new Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,3 +23,23 @@ export interface MediaItem {
|
|||||||
export interface MediaItemResponse {
|
export interface MediaItemResponse {
|
||||||
media: MediaItem[];
|
media: MediaItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EpisodeAnime {
|
||||||
|
id: number;
|
||||||
|
anime_id: number;
|
||||||
|
user_id: number | null;
|
||||||
|
number: string;
|
||||||
|
created_at: string;
|
||||||
|
link: string;
|
||||||
|
visite: number;
|
||||||
|
hidden: number;
|
||||||
|
public: number;
|
||||||
|
scws_id: number;
|
||||||
|
file_name: string;
|
||||||
|
tg_post: number;
|
||||||
|
episode_id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EpisodeAnimeResponse {
|
||||||
|
episodes: EpisodeAnime[];
|
||||||
|
}
|
@ -1,3 +1,38 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import type { EpisodeAnime, MediaItem } from "@/api/interfaces";
|
||||||
|
import { onMounted, ref, onUnmounted } from "vue";
|
||||||
|
import { getEpisodesInfo } from "@/api/api";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const item: MediaItem = JSON.parse(<string>route.params.item)
|
||||||
|
const imageUrl: string = <string>route.params.imageUrl
|
||||||
|
const episodes = ref<EpisodeAnime[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (item.type !== 'TV_ANIME' && item.type !== 'TV') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loading.value = true
|
||||||
|
const response = await getEpisodesInfo(item.id, item.slug, item.type)
|
||||||
|
if (response && response.body) {
|
||||||
|
loading.value = false;
|
||||||
|
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
||||||
|
while (true) {
|
||||||
|
const {value, done} = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const episodesData:EpisodeAnime = JSON.parse(value.split("a:")[1].trim());
|
||||||
|
episodes.value.push(episodesData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="details-container">
|
<div class="details-container">
|
||||||
<div class="details-card">
|
<div class="details-card">
|
||||||
@ -11,22 +46,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="episodes-container">
|
||||||
|
<div v-if="!loading" v-for="episode in episodes" :key="episode.id" class="episode-item">
|
||||||
|
<div class="episode-title">{{ episode.number }} - {{ episode.file_name }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<p>Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
import type { MediaItem } from "@/api/interfaces";
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const item: MediaItem = JSON.parse(<string>route.params.item)
|
|
||||||
const imageUrl: string = <string>route.params.imageUrl
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.details-container {
|
.details-container {
|
||||||
|
padding-top: 10px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user