mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 13:37:24 +00:00
accept plain stremio subtitle text
This commit is contained in:
parent
128b9518a5
commit
9693f65f45
3 changed files with 234 additions and 7 deletions
|
|
@ -97,7 +97,7 @@ final class SubtitleResolver: SubtitleResolving {
|
|||
}
|
||||
|
||||
private func cacheSubtitleDataIfNeeded(_ data: Data, original: SubtitleCandidate) -> SubtitleCandidate? {
|
||||
guard let subtitleType = Self.subtitleType(in: data) else {
|
||||
guard let subtitleType = Self.subtitleType(in: data, sourceURL: original.url) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ final class SubtitleResolver: SubtitleResolving {
|
|||
}
|
||||
}
|
||||
|
||||
private static func subtitleType(in data: Data) -> SubtitlePayloadType? {
|
||||
private static func subtitleType(in data: Data, sourceURL: URL? = nil) -> SubtitlePayloadType? {
|
||||
guard !data.isEmpty,
|
||||
let text = String(data: data.prefix(4096), encoding: .utf8)?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
|
|
@ -228,9 +228,32 @@ final class SubtitleResolver: SubtitleResolving {
|
|||
) != nil {
|
||||
return .srt
|
||||
}
|
||||
if let sourceURL,
|
||||
isStremioSubtitleDownloadURL(sourceURL),
|
||||
isPlausiblePlainSubtitleText(text) {
|
||||
return .srt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func isPlausiblePlainSubtitleText(_ text: String) -> Bool {
|
||||
let lowercased = text.lowercased()
|
||||
guard !lowercased.hasPrefix("{"),
|
||||
!lowercased.hasPrefix("["),
|
||||
!lowercased.hasPrefix("<!doctype"),
|
||||
!lowercased.hasPrefix("<html"),
|
||||
!lowercased.hasPrefix("<?xml")
|
||||
else {
|
||||
return false
|
||||
}
|
||||
|
||||
return lowercased.contains("-->")
|
||||
|| lowercased.contains("<font")
|
||||
|| lowercased.contains("{\\")
|
||||
|| lowercased.contains("\\n")
|
||||
|| lowercased.split(whereSeparator: \.isNewline).count > 1
|
||||
}
|
||||
|
||||
private static func logRejected(_ candidate: SubtitleCandidate, responseURL: URL?, data: Data) -> SubtitleCandidate? {
|
||||
#if DEBUG
|
||||
let responseDescription = responseURL.map { URLRedactor.redactedURLString($0.absoluteString) } ?? "none"
|
||||
|
|
@ -244,10 +267,21 @@ final class SubtitleResolver: SubtitleResolving {
|
|||
} else {
|
||||
bodyKind = "unreadable"
|
||||
}
|
||||
print("[DreamioSubtitles] rejected candidate reason=\(bodyKind) url=\(URLRedactor.redactedURLString(candidate.url.absoluteString)) responseURL=\(responseDescription)")
|
||||
print("[DreamioSubtitles] rejected candidate reason=\(bodyKind) url=\(URLRedactor.redactedURLString(candidate.url.absoluteString)) responseURL=\(responseDescription) preview=\(rejectionPreview(data))")
|
||||
#endif
|
||||
return nil
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static func rejectionPreview(_ data: Data) -> String {
|
||||
guard let text = String(data: data.prefix(180), encoding: .utf8) else {
|
||||
return "unreadable"
|
||||
}
|
||||
return text
|
||||
.replacingOccurrences(of: "\n", with: "\\n")
|
||||
.replacingOccurrences(of: "\r", with: "\\r")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protocol StreamResolving {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ struct StreamResolverTests {
|
|||
testOpenSubtitlesV3DownloadResponseResolution()
|
||||
testOpenSubtitlesNestedDownloadResponseResolution()
|
||||
await testSubtitleResolverCachesStremioDownloadBody()
|
||||
await testSubtitleResolverCachesPlainStremioDownloadBody()
|
||||
await testSubtitleResolverDownloadJSONReturningLink()
|
||||
await testSubtitleResolverRedirectToDirectSubtitle()
|
||||
await testSubtitleResolverRejectsNonSubtitleAPIResponse()
|
||||
|
|
@ -476,6 +477,41 @@ struct StreamResolverTests {
|
|||
assertEqual(cachedBody, subtitleBody)
|
||||
}
|
||||
|
||||
private static func testSubtitleResolverCachesPlainStremioDownloadBody() async {
|
||||
let sourceURL = "https://subs5.strem.io/en/download/subencoding-stremio-utf8/src-api/file/1952341942"
|
||||
let subtitleBody = """
|
||||
00:01.000 --> 00:02.000
|
||||
Plain cue text without an index
|
||||
|
||||
"""
|
||||
MockURLProtocol.handler = nil
|
||||
MockURLProtocol.handlers = [
|
||||
sourceURL: (
|
||||
200,
|
||||
URL(string: sourceURL)!,
|
||||
subtitleBody.data(using: .utf8)!
|
||||
)
|
||||
]
|
||||
|
||||
let cacheDirectory = FileManager.default.temporaryDirectory
|
||||
.appendingPathComponent("DreamioSubtitleResolverTests-\(UUID().uuidString)", isDirectory: true)
|
||||
defer {
|
||||
try? FileManager.default.removeItem(at: cacheDirectory)
|
||||
}
|
||||
|
||||
let resolver = SubtitleResolver(session: mockSession(), cacheDirectory: cacheDirectory)
|
||||
let candidate = await resolver.resolve(SubtitleCandidate(
|
||||
url: URL(string: sourceURL)!,
|
||||
label: "English",
|
||||
language: "eng"
|
||||
))
|
||||
|
||||
assertEqual(candidate?.url.isFileURL, true)
|
||||
assertEqual(candidate?.url.pathExtension, "srt")
|
||||
let cachedBody = try? String(contentsOf: candidate!.url, encoding: .utf8)
|
||||
assertEqual(cachedBody, subtitleBody)
|
||||
}
|
||||
|
||||
private static func testSubtitleResolverDownloadJSONReturningLink() async {
|
||||
MockURLProtocol.handler = nil
|
||||
MockURLProtocol.handlers = [
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue