137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package debrid_client
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"path/filepath"
|
|
"seanime/internal/api/anilist"
|
|
"seanime/internal/api/metadata"
|
|
"seanime/internal/util"
|
|
"strings"
|
|
)
|
|
|
|
func (s *StreamManager) getMediaInfo(ctx context.Context, mediaId int) (media *anilist.CompleteAnime, animeMetadata *metadata.AnimeMetadata, err error) {
|
|
// Get the media
|
|
var found bool
|
|
media, found = s.repository.completeAnimeCache.Get(mediaId)
|
|
if !found {
|
|
// Fetch the media
|
|
media, err = s.repository.platform.GetAnimeWithRelations(ctx, mediaId)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("torrentstream: Failed to fetch media: %w", err)
|
|
}
|
|
}
|
|
|
|
// Get the media
|
|
animeMetadata, err = s.repository.metadataProvider.GetAnimeMetadata(metadata.AnilistPlatform, mediaId)
|
|
if err != nil {
|
|
//return nil, nil, fmt.Errorf("torrentstream: Could not fetch AniDB media: %w", err)
|
|
animeMetadata = &metadata.AnimeMetadata{
|
|
Titles: make(map[string]string),
|
|
Episodes: make(map[string]*metadata.EpisodeMetadata),
|
|
EpisodeCount: 0,
|
|
SpecialCount: 0,
|
|
Mappings: &metadata.AnimeMappings{
|
|
AnilistId: media.GetID(),
|
|
},
|
|
}
|
|
animeMetadata.Titles["en"] = media.GetTitleSafe()
|
|
animeMetadata.Titles["x-jat"] = media.GetRomajiTitleSafe()
|
|
err = nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func CanStream(streamUrl string) (bool, string) {
|
|
hasExtension, isArchive := IsArchive(streamUrl)
|
|
|
|
// If we were able to verify that the stream URL is an archive, we can't stream it
|
|
if isArchive {
|
|
return false, "Stream URL is an archive"
|
|
}
|
|
|
|
// If the stream URL has an extension, we can stream it
|
|
if hasExtension {
|
|
ext := filepath.Ext(streamUrl)
|
|
if util.IsValidVideoExtension(ext) {
|
|
return true, ""
|
|
}
|
|
// If the extension is not a valid video extension, we can't stream it
|
|
return false, "Stream URL is not a valid video extension"
|
|
}
|
|
|
|
// If the stream URL doesn't have an extension, we'll get the headers to check if it's a video
|
|
// If the headers are not available, we can't stream it
|
|
|
|
contentType, err := GetContentType(streamUrl)
|
|
if err != nil {
|
|
return false, "Failed to get content type"
|
|
}
|
|
|
|
if strings.HasPrefix(contentType, "video/") {
|
|
return true, ""
|
|
}
|
|
|
|
return false, fmt.Sprintf("Stream URL of type %q is not a video", contentType)
|
|
}
|
|
|
|
func IsArchive(streamUrl string) (hasExtension bool, isArchive bool) {
|
|
ext := filepath.Ext(streamUrl)
|
|
if ext == ".zip" || ext == ".rar" {
|
|
return true, true
|
|
}
|
|
|
|
if ext != "" {
|
|
return true, false
|
|
}
|
|
|
|
return false, false
|
|
}
|
|
|
|
func GetContentTypeHead(url string) string {
|
|
resp, err := http.Head(url)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
return resp.Header.Get("Content-Type")
|
|
}
|
|
|
|
func GetContentType(url string) (string, error) {
|
|
// Try using HEAD request
|
|
if cType := GetContentTypeHead(url); cType != "" {
|
|
return cType, nil
|
|
}
|
|
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Only read a small amount of data to determine the content type.
|
|
req.Header.Set("Range", "bytes=0-511")
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Read the first 512 bytes
|
|
buf := make([]byte, 512)
|
|
n, err := resp.Body.Read(buf)
|
|
if err != nil && err != io.EOF {
|
|
return "", err
|
|
}
|
|
|
|
// Detect content type based on the read bytes
|
|
contentType := http.DetectContentType(buf[:n])
|
|
|
|
return contentType, nil
|
|
}
|