refactor(playback): simplify service files
This commit is contained in:
@@ -259,12 +259,11 @@ func (s *Service) setPlaybackBaseDataCache(key string, data playbackBaseData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) resolveShowCached(ctx context.Context, malID int, titleCandidates []string) (string, string, error) {
|
func (s *Service) resolveShowCached(ctx context.Context, malID int, titleCandidates []string) (string, string, error) {
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
s.cacheMu.RLock()
|
s.cacheMu.RLock()
|
||||||
item, ok := s.showResolution[malID]
|
item, ok := s.showResolution[malID]
|
||||||
s.cacheMu.RUnlock()
|
s.cacheMu.RUnlock()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
if ok && now.Before(item.ExpiresAt) && strings.TrimSpace(item.ShowID) != "" {
|
if ok && now.Before(item.ExpiresAt) && strings.TrimSpace(item.ShowID) != "" {
|
||||||
return item.ShowID, item.Title, nil
|
return item.ShowID, item.Title, nil
|
||||||
}
|
}
|
||||||
@@ -278,7 +277,7 @@ func (s *Service) resolveShowCached(ctx context.Context, malID int, titleCandida
|
|||||||
s.showResolution[malID] = showResolutionCacheItem{
|
s.showResolution[malID] = showResolutionCacheItem{
|
||||||
ShowID: showID,
|
ShowID: showID,
|
||||||
Title: resolvedTitle,
|
Title: resolvedTitle,
|
||||||
ExpiresAt: time.Now().Add(showResolutionCacheTTL),
|
ExpiresAt: now.Add(showResolutionCacheTTL),
|
||||||
}
|
}
|
||||||
s.cacheMu.Unlock()
|
s.cacheMu.Unlock()
|
||||||
|
|
||||||
@@ -347,7 +346,6 @@ func cloneStringSlice(items []string) []string {
|
|||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned := make([]string, len(items))
|
cloned := make([]string, len(items))
|
||||||
copy(cloned, items)
|
copy(cloned, items)
|
||||||
return cloned
|
return cloned
|
||||||
@@ -357,7 +355,6 @@ func cloneModeSources(modeSources map[string]ModeSource) map[string]ModeSource {
|
|||||||
if len(modeSources) == 0 {
|
if len(modeSources) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned := make(map[string]ModeSource, len(modeSources))
|
cloned := make(map[string]ModeSource, len(modeSources))
|
||||||
for mode, source := range modeSources {
|
for mode, source := range modeSources {
|
||||||
cloned[mode] = ModeSource{
|
cloned[mode] = ModeSource{
|
||||||
@@ -366,7 +363,6 @@ func cloneModeSources(modeSources map[string]ModeSource) map[string]ModeSource {
|
|||||||
Subtitles: cloneSubtitleItems(source.Subtitles),
|
Subtitles: cloneSubtitleItems(source.Subtitles),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cloned
|
return cloned
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +370,6 @@ func cloneSubtitleItems(items []SubtitleItem) []SubtitleItem {
|
|||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned := make([]SubtitleItem, len(items))
|
cloned := make([]SubtitleItem, len(items))
|
||||||
copy(cloned, items)
|
copy(cloned, items)
|
||||||
return cloned
|
return cloned
|
||||||
@@ -384,7 +379,6 @@ func cloneSegments(segments []SkipSegment) []SkipSegment {
|
|||||||
if len(segments) == 0 {
|
if len(segments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned := make([]SkipSegment, len(segments))
|
cloned := make([]SkipSegment, len(segments))
|
||||||
copy(cloned, segments)
|
copy(cloned, segments)
|
||||||
return cloned
|
return cloned
|
||||||
|
|||||||
@@ -49,27 +49,33 @@ func (s *Service) ProxyStream(ctx context.Context, targetURL string, referer str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isM3U8(targetURL string, contentType string) bool {
|
func isM3U8(targetURL string, contentType string) bool {
|
||||||
lowerURL := strings.ToLower(targetURL)
|
if strings.Contains(strings.ToLower(targetURL), ".m3u8") {
|
||||||
lowerType := strings.ToLower(contentType)
|
|
||||||
if strings.Contains(lowerURL, ".m3u8") {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
lowerType := strings.ToLower(contentType)
|
||||||
return strings.Contains(lowerType, "application/vnd.apple.mpegurl") || strings.Contains(lowerType, "application/x-mpegurl")
|
return strings.Contains(lowerType, "application/vnd.apple.mpegurl") || strings.Contains(lowerType, "application/x-mpegurl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hopHeaders = map[string]struct{}{
|
||||||
|
"connection": {},
|
||||||
|
"transfer-encoding": {},
|
||||||
|
"keep-alive": {},
|
||||||
|
"proxy-authenticate": {},
|
||||||
|
"proxy-authorization": {},
|
||||||
|
"te": {},
|
||||||
|
"trailers": {},
|
||||||
|
"upgrade": {},
|
||||||
|
}
|
||||||
|
|
||||||
func cloneHeaders(src http.Header) http.Header {
|
func cloneHeaders(src http.Header) http.Header {
|
||||||
dst := make(http.Header)
|
dst := make(http.Header)
|
||||||
for key, values := range src {
|
for key, values := range src {
|
||||||
lower := strings.ToLower(key)
|
if _, ok := hopHeaders[strings.ToLower(key)]; ok {
|
||||||
if lower == "connection" || lower == "transfer-encoding" || lower == "keep-alive" || lower == "proxy-authenticate" || lower == "proxy-authorization" || lower == "te" || lower == "trailers" || lower == "upgrade" {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
dst.Add(key, value)
|
dst.Add(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,16 +189,12 @@ func extractDigits(value string) string {
|
|||||||
|
|
||||||
func normalizeSourceTypeFromProbe(source StreamSource, contentType string) StreamSource {
|
func normalizeSourceTypeFromProbe(source StreamSource, contentType string) StreamSource {
|
||||||
lower := strings.ToLower(contentType)
|
lower := strings.ToLower(contentType)
|
||||||
if strings.Contains(lower, "video/mp4") {
|
switch {
|
||||||
|
case strings.Contains(lower, "video/mp4"):
|
||||||
source.Type = "mp4"
|
source.Type = "mp4"
|
||||||
return source
|
case strings.Contains(lower, "mpegurl"):
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(lower, "mpegurl") {
|
|
||||||
source.Type = "m3u8"
|
source.Type = "m3u8"
|
||||||
return source
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return source
|
return source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,12 +122,7 @@ func firstNonEmptyTitle(values []string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func normalizeMode(raw string) string {
|
func normalizeMode(raw string) string {
|
||||||
lower := strings.ToLower(strings.TrimSpace(raw))
|
return strings.ToLower(strings.TrimSpace(raw))
|
||||||
if lower == "sub" || lower == "dub" {
|
|
||||||
return lower
|
|
||||||
}
|
|
||||||
|
|
||||||
return lower
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func availableModes(modeSources map[string]ModeSource) []string {
|
func availableModes(modeSources map[string]ModeSource) []string {
|
||||||
|
|||||||
@@ -60,19 +60,16 @@ func (s *Service) choosePlaybackSource(ctx context.Context, ranked []sourceScore
|
|||||||
return StreamSource{}, "", errors.New("no ranked sources available")
|
return StreamSource{}, "", errors.New("no ranked sources available")
|
||||||
}
|
}
|
||||||
|
|
||||||
embedCandidates := make([]StreamSource, 0)
|
embedCandidates := make([]StreamSource, 0, len(ranked))
|
||||||
for _, candidate := range ranked {
|
for _, candidate := range ranked {
|
||||||
source := candidate.source
|
source := candidate.source
|
||||||
sourceType := strings.ToLower(source.Type)
|
switch strings.ToLower(source.Type) {
|
||||||
|
|
||||||
switch sourceType {
|
|
||||||
case "mp4", "m3u8":
|
case "mp4", "m3u8":
|
||||||
return source, "direct-media", nil
|
return source, "direct-media", nil
|
||||||
case "embed":
|
case "embed":
|
||||||
embedCandidates = append(embedCandidates, source)
|
embedCandidates = append(embedCandidates, source)
|
||||||
default:
|
default:
|
||||||
playable, contentType := s.probeDirectMedia(ctx, source)
|
if playable, contentType := s.probeDirectMedia(ctx, source); playable {
|
||||||
if playable {
|
|
||||||
return normalizeSourceTypeFromProbe(source, contentType), "probed-media", nil
|
return normalizeSourceTypeFromProbe(source, contentType), "probed-media", nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,19 +98,16 @@ func (s *Service) choosePlaybackSourceWithCache(
|
|||||||
return StreamSource{}, "", errors.New("no ranked sources available")
|
return StreamSource{}, "", errors.New("no ranked sources available")
|
||||||
}
|
}
|
||||||
|
|
||||||
embedCandidates := make([]StreamSource, 0)
|
embedCandidates := make([]StreamSource, 0, len(ranked))
|
||||||
for _, candidate := range ranked {
|
for _, candidate := range ranked {
|
||||||
source := candidate.source
|
source := candidate.source
|
||||||
sourceType := strings.ToLower(source.Type)
|
switch strings.ToLower(source.Type) {
|
||||||
|
|
||||||
switch sourceType {
|
|
||||||
case "mp4", "m3u8":
|
case "mp4", "m3u8":
|
||||||
return source, "direct-media", nil
|
return source, "direct-media", nil
|
||||||
case "embed":
|
case "embed":
|
||||||
embedCandidates = append(embedCandidates, source)
|
embedCandidates = append(embedCandidates, source)
|
||||||
default:
|
default:
|
||||||
playable, contentType := s.probeDirectMediaCached(ctx, source, probeCache, probeCacheMu)
|
if playable, contentType := s.probeDirectMediaCached(ctx, source, probeCache, probeCacheMu); playable {
|
||||||
if playable {
|
|
||||||
return normalizeSourceTypeFromProbe(source, contentType), "probed-media", nil
|
return normalizeSourceTypeFromProbe(source, contentType), "probed-media", nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,10 +202,10 @@ func (s *Service) probeDirectMedia(ctx context.Context, source StreamSource) (bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) probeEmbedSource(ctx context.Context, source StreamSource) bool {
|
func (s *Service) probeEmbedSource(ctx context.Context, source StreamSource) bool {
|
||||||
probeCtx, cancel := context.WithTimeout(ctx, providerProbeTimeout)
|
ctx, cancel := context.WithTimeout(ctx, providerProbeTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(probeCtx, http.MethodGet, source.URL, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, source.URL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -237,7 +231,7 @@ func (s *Service) probeEmbedSource(ctx context.Context, source StreamSource) boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
content := strings.ToLower(string(body))
|
content := strings.ToLower(string(body))
|
||||||
markers := []string{
|
for _, marker := range []string{
|
||||||
"file was deleted",
|
"file was deleted",
|
||||||
"file has been deleted",
|
"file has been deleted",
|
||||||
"video was deleted",
|
"video was deleted",
|
||||||
@@ -246,8 +240,7 @@ func (s *Service) probeEmbedSource(ctx context.Context, source StreamSource) boo
|
|||||||
"file not found",
|
"file not found",
|
||||||
"this file does not exist",
|
"this file does not exist",
|
||||||
"resource unavailable",
|
"resource unavailable",
|
||||||
}
|
} {
|
||||||
for _, marker := range markers {
|
|
||||||
if strings.Contains(content, marker) {
|
if strings.Contains(content, marker) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user