update readme

This commit is contained in:
cranci1 2024-12-24 11:08:13 +01:00
parent db11dc7f06
commit 2241bb2b58
2 changed files with 84 additions and 50 deletions

View file

@ -4,7 +4,7 @@
<img src="https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner.png" width="500px">
[![Build and Release IPA](https://github.com/cranci1/Sora/actions/workflows/build.yml/badge.svg)](https://github.com/cranci1/Sora/actions/workflows/build.yml) [![Platform](https://img.shields.io/badge/Platform-iOS%20%7C%20iPadOS%2015.0%2B-orange?logo=apple&logoColor=white)](https://img.shields.io/badge/Platform-iOS%20%7C%20iPadOS%2014.0%2B-red?logo=apple&logoColor=white) [![Discord](https://img.shields.io/discord/1293430817841741899.svg?logo=discord&color=blue)](https://discord.gg/XR3SrmUbpd)
[![Build and Release IPA](https://github.com/cranci1/Sora/actions/workflows/build.yml/badge.svg)](https://github.com/cranci1/Sora/actions/workflows/build.yml) [![Platform](https://img.shields.io/badge/Platform-iOS%20%7C%20iPadOS%2014.0%2B%7CmacOS%2012.0%2B-red?logo=apple&logoColor=white)](https://img.shields.io/badge/Platform-iOS%20%7C%20iPadOS%2014.0%2B%7CmacOS%2012.0%2B-red?logo=apple&logoColor=white) [![Discord](https://img.shields.io/discord/1293430817841741899.svg?logo=discord&color=blue)](https://discord.gg/XR3SrmUbpd)
A modular web scraping app, **Still in early builds** under the GPLv3.0 License
@ -21,9 +21,9 @@ A modular web scraping app, **Still in early builds** under the GPLv3.0 License
## Features
- [x] iOS/iPadOS 15+ support
- [x] macOS 12+ support
- [x] JSON module support
- [ ] JavaScript module support
- [ ] macOS support
## Frequently Asked Questions

View file

@ -49,54 +49,6 @@ extension AnimeInfoView {
}.resume()
}
func extractStreamURLs(from html: String, streamType: String) -> [String] {
let pattern: String
switch streamType {
case "HLS":
pattern = #"https:\/\/[^"\s<>]+\.m3u8(?:\?[^\s"'<>]+)?"#
case "MP4":
pattern = #"https:\/\/(?:(?!php).)+\.mp4(?:\?[^\s"'<>]+)?"#
default:
return []
}
do {
Logger.shared.log(streamType)
let regex = try NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: html, options: [], range: NSRange(html.startIndex..., in: html))
return matches.compactMap {
Range($0.range, in: html).map { String(html[$0]) }
}
} catch {
print("Invalid regex: \(error)")
Logger.shared.log("Invalid regex: \(error)")
return []
}
}
func extractDubSubURLs(from htmlContent: String) -> [(type: String, url: String)] {
let pattern = #""type":"(SUB|DUB)","url":"(.*?\.m3u8)""#
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
return []
}
let range = NSRange(htmlContent.startIndex..., in: htmlContent)
let matches = regex.matches(in: htmlContent, range: range)
return matches.compactMap { match in
if match.numberOfRanges == 3,
let typeRange = Range(match.range(at: 1), in: htmlContent),
let urlRange = Range(match.range(at: 2), in: htmlContent) {
let type = String(htmlContent[typeRange])
let urlString = String(htmlContent[urlRange]).replacingOccurrences(of: "\\/", with: "/")
Logger.shared.log(urlString)
return (type, urlString)
}
return nil
}
}
func fetchEpisodeStream(urlString: String) {
guard let url = URL(string: urlString) else { return }
@ -123,6 +75,22 @@ extension AnimeInfoView {
self.playStream(urlString: streamURLs.first, fullURL: urlString)
}
}
} else if module.extractor == "pattern-mp4" {
Logger.shared.log("extracting for pattern-mp4")
let patternURL = extractPatternURL(from: html)
guard let patternURL = patternURL else { return }
URLSession.custom.dataTask(with: patternURL) { data, response, error in
guard let data = data, error == nil else { return }
let patternHTML = String(data: data, encoding: .utf8) ?? ""
let mp4URLs = extractStreamURLs(from: patternHTML, streamType: "MP4").map { $0.replacingOccurrences(of: "amp;", with: "") }
DispatchQueue.main.async {
Logger.shared.log("MP4 URLs: \(mp4URLs)")
self.playStream(urlString: mp4URLs.first, fullURL: patternURL.absoluteString)
}
}.resume()
} else {
DispatchQueue.main.async {
Logger.shared.log("stream URLs: \(streamURLs)")
@ -132,6 +100,72 @@ extension AnimeInfoView {
}.resume()
}
func extractStreamURLs(from html: String, streamType: String) -> [String] {
let pattern: String
switch streamType {
case "HLS":
pattern = #"https:\/\/[^"\s<>]+\.m3u8(?:\?[^\s"'<>]+)?"#
case "MP4":
pattern = #"https:\/\/(?:(?!php).)+\.mp4(?:\?[^\s"'<>]+)?"#
default:
return []
}
do {
Logger.shared.log(streamType)
let regex = try NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: html, options: [], range: NSRange(html.startIndex..., in: html))
return matches.compactMap {
Range($0.range, in: html).map { String(html[$0]) }
}
} catch {
print("Invalid regex: \(error)")
Logger.shared.log("Invalid regex: \(error)")
return []
}
}
func extractPatternURL(from html: String) -> URL? {
let pattern = module.module[0].episodes.pattern
do {
let regex = try NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: html, options: [], range: NSRange(html.startIndex..., in: html))
if let match = matches.first, let range = Range(match.range, in: html) {
var urlString = String(html[range])
urlString = urlString.replacingOccurrences(of: "amp;", with: "")
return URL(string: urlString)
}
} catch {
print("Invalid regex: \(error)")
Logger.shared.log("Invalid regex: \(error)")
}
return nil
}
func extractDubSubURLs(from htmlContent: String) -> [(type: String, url: String)] {
let pattern = #""type":"(SUB|DUB)","url":"(.*?\.m3u8)""#
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
return []
}
let range = NSRange(htmlContent.startIndex..., in: htmlContent)
let matches = regex.matches(in: htmlContent, range: range)
return matches.compactMap { match in
if match.numberOfRanges == 3,
let typeRange = Range(match.range(at: 1), in: htmlContent),
let urlRange = Range(match.range(at: 2), in: htmlContent) {
let type = String(htmlContent[typeRange])
let urlString = String(htmlContent[urlRange]).replacingOccurrences(of: "\\/", with: "/")
Logger.shared.log(urlString)
return (type, urlString)
}
return nil
}
}
func presentStreamSelection(subURLs: [String], dubURLs: [String]) {
let uniqueSubURLs = Array(Set(subURLs))
let uniqueDubURLs = Array(Set(dubURLs))