mirror of
https://github.com/cranci1/Sora.git
synced 2026-04-21 00:22:12 +00:00
base user agent + mac catalist
This commit is contained in:
parent
f36e16e20a
commit
db11dc7f06
12 changed files with 99 additions and 9 deletions
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
|
|
@ -5,7 +5,7 @@ on:
|
||||||
- main
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build IPA
|
name: Build IPA and Mac Catalyst
|
||||||
runs-on: macOS-latest
|
runs-on: macOS-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Use Node.js 20
|
- name: Use Node.js 20
|
||||||
|
|
@ -27,3 +27,15 @@ jobs:
|
||||||
name: Sora-IPA
|
name: Sora-IPA
|
||||||
path: build/Sora.ipa
|
path: build/Sora.ipa
|
||||||
compression-level: 0
|
compression-level: 0
|
||||||
|
|
||||||
|
- name: Run macbuild.sh
|
||||||
|
run: |
|
||||||
|
chmod +x macbuild.sh
|
||||||
|
./macbuild.sh
|
||||||
|
|
||||||
|
- name: Upload Mac Catalyst artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Sora-Catalyst
|
||||||
|
path: build/Sora-catalyst.zip
|
||||||
|
compression-level: 0
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D42D13240200B4F2D2 /* EpisodeCell.swift */; };
|
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D42D13240200B4F2D2 /* EpisodeCell.swift */; };
|
||||||
132417D72D13242400B4F2D2 /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D62D13242400B4F2D2 /* CircularProgressBar.swift */; };
|
132417D72D13242400B4F2D2 /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D62D13242400B4F2D2 /* CircularProgressBar.swift */; };
|
||||||
132417D92D1328B900B4F2D2 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */; };
|
132417D92D1328B900B4F2D2 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */; };
|
||||||
|
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1352BA702D1ABC30000A9AF9 /* URLSession.swift */; };
|
||||||
13B3A4B22D1477F100BCC0D5 /* StorageSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */; };
|
13B3A4B22D1477F100BCC0D5 /* StorageSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -73,6 +74,8 @@
|
||||||
132417D42D13240200B4F2D2 /* EpisodeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeCell.swift; sourceTree = "<group>"; };
|
132417D42D13240200B4F2D2 /* EpisodeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeCell.swift; sourceTree = "<group>"; };
|
||||||
132417D62D13242400B4F2D2 /* CircularProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressBar.swift; sourceTree = "<group>"; };
|
132417D62D13242400B4F2D2 /* CircularProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressBar.swift; sourceTree = "<group>"; };
|
||||||
132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
|
132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
|
||||||
|
1352BA6F2D1AB113000A9AF9 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
|
||||||
|
1352BA702D1ABC30000A9AF9 /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = "<group>"; };
|
||||||
13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageSettingsView.swift; sourceTree = "<group>"; };
|
13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageSettingsView.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
|
@ -126,6 +129,7 @@
|
||||||
132417822D13198000B4F2D2 /* Sora */ = {
|
132417822D13198000B4F2D2 /* Sora */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
1352BA6F2D1AB113000A9AF9 /* Sora.entitlements */,
|
||||||
132417C52D131AA500B4F2D2 /* Info.plist */,
|
132417C52D131AA500B4F2D2 /* Info.plist */,
|
||||||
132417912D1319E800B4F2D2 /* Utils */,
|
132417912D1319E800B4F2D2 /* Utils */,
|
||||||
132417A52D131A0600B4F2D2 /* Views */,
|
132417A52D131A0600B4F2D2 /* Views */,
|
||||||
|
|
@ -170,6 +174,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
132417952D1319E800B4F2D2 /* Notification.swift */,
|
132417952D1319E800B4F2D2 /* Notification.swift */,
|
||||||
|
1352BA702D1ABC30000A9AF9 /* URLSession.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -376,6 +381,7 @@
|
||||||
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
||||||
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
||||||
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
||||||
|
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */,
|
||||||
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
@ -504,6 +510,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Sora/Sora.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
||||||
|
|
@ -524,6 +531,7 @@
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
@ -535,6 +543,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Sora/Sora.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
||||||
|
|
@ -555,6 +564,7 @@
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
|
||||||
Binary file not shown.
10
Sora/Sora.entitlements
Normal file
10
Sora/Sora.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
18
Sora/Utils/Extensions/URLSession.swift
Normal file
18
Sora/Utils/Extensions/URLSession.swift
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// URLSession.swift
|
||||||
|
// Sora
|
||||||
|
//
|
||||||
|
// Created by Francesco on 24/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension URLSession {
|
||||||
|
static let custom: URLSession = {
|
||||||
|
let configuration = URLSessionConfiguration.default
|
||||||
|
configuration.httpAdditionalHeaders = [
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
||||||
|
]
|
||||||
|
return URLSession(configuration: configuration)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
@ -71,6 +71,7 @@ struct ModuleStruct: Codable {
|
||||||
struct Episodes: Codable, Hashable {
|
struct Episodes: Codable, Hashable {
|
||||||
let selector: String
|
let selector: String
|
||||||
let order: String
|
let order: String
|
||||||
|
let pattern: String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class ModulesManager: ObservableObject {
|
||||||
completion(.failure(ModuleError.invalidURL))
|
completion(.failure(ModuleError.invalidURL))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let task = URLSession.shared.dataTask(with: url) { data, response, error in
|
let task = URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
guard let data = data, error == nil else {
|
guard let data = data, error == nil else {
|
||||||
completion(.failure(error ?? ModuleError.unknown))
|
completion(.failure(error ?? ModuleError.unknown))
|
||||||
return
|
return
|
||||||
|
|
@ -67,7 +67,7 @@ class ModulesManager: ObservableObject {
|
||||||
func refreshModules() {
|
func refreshModules() {
|
||||||
for (name, urlString) in moduleURLs {
|
for (name, urlString) in moduleURLs {
|
||||||
guard let url = URL(string: urlString) else { continue }
|
guard let url = URL(string: urlString) else { continue }
|
||||||
let task = URLSession.shared.dataTask(with: url) { data, response, error in
|
let task = URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
guard let data = data, error == nil else { return }
|
guard let data = data, error == nil else { return }
|
||||||
do {
|
do {
|
||||||
let updatedModule = try JSONDecoder().decode(ModuleStruct.self, from: data)
|
let updatedModule = try JSONDecoder().decode(ModuleStruct.self, from: data)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ extension AnimeInfoView {
|
||||||
func fetchAnimeDetails() {
|
func fetchAnimeDetails() {
|
||||||
guard let url = URL(string: anime.href.hasPrefix("https") ? anime.href : "\(module.module[0].details.baseURL)\(anime.href)") else { return }
|
guard let url = URL(string: anime.href.hasPrefix("https") ? anime.href : "\(module.module[0].details.baseURL)\(anime.href)") else { return }
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
defer { isLoading = false }
|
defer { isLoading = false }
|
||||||
guard let data = data, error == nil else { return }
|
guard let data = data, error == nil else { return }
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ extension AnimeInfoView {
|
||||||
guard let url = URL(string: urlString) else { return }
|
guard let url = URL(string: urlString) else { return }
|
||||||
|
|
||||||
Logger.shared.log("Pressed episode button")
|
Logger.shared.log("Pressed episode button")
|
||||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
guard let data = data, error == nil else { return }
|
guard let data = data, error == nil else { return }
|
||||||
|
|
||||||
let html = String(data: data, encoding: .utf8) ?? ""
|
let html = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ struct AnimeInfoView: View {
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
|
|
||||||
ForEach(episodes.indices, id: \.self) { index in
|
ForEach(episodes.indices, id: \.self) { index in
|
||||||
let episodeURL = "\(module.module[0].details.baseURL)\(episodes[index])"
|
let episodeURL = episodes[index].hasPrefix("https") ? episodes[index] : "\(module.module[0].details.baseURL)\(episodes[index])"
|
||||||
let lastPlayedTime = UserDefaults.standard.double(forKey: "lastPlayedTime_\(episodeURL)")
|
let lastPlayedTime = UserDefaults.standard.double(forKey: "lastPlayedTime_\(episodeURL)")
|
||||||
let totalTime = UserDefaults.standard.double(forKey: "totalTime_\(episodeURL)")
|
let totalTime = UserDefaults.standard.double(forKey: "totalTime_\(episodeURL)")
|
||||||
let progress = totalTime > 0 ? lastPlayedTime / totalTime : 0
|
let progress = totalTime > 0 ? lastPlayedTime / totalTime : 0
|
||||||
|
|
@ -278,7 +278,7 @@ struct AnimeInfoView: View {
|
||||||
let parameters: [String: Any] = ["query": query]
|
let parameters: [String: Any] = ["query": query]
|
||||||
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
|
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: request) { data, response, error in
|
URLSession.custom.dataTask(with: request) { data, response, error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ struct EpisodeCell: View {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("Failed to fetch episode details: \(error)")
|
print("Failed to fetch episode details: \(error)")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ struct SearchResultsView: View {
|
||||||
let urlString = "\(module.module[0].search.url)?\(module.module[0].search.parameter)=\(encodedSearchText)"
|
let urlString = "\(module.module[0].search.url)?\(module.module[0].search.parameter)=\(encodedSearchText)"
|
||||||
guard let url = URL(string: urlString) else { return }
|
guard let url = URL(string: urlString) else { return }
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
URLSession.custom.dataTask(with: url) { data, response, error in
|
||||||
defer { isLoading = false }
|
defer { isLoading = false }
|
||||||
guard let data = data, error == nil else { return }
|
guard let data = data, error == nil else { return }
|
||||||
|
|
||||||
|
|
|
||||||
39
macbuild.sh
Executable file
39
macbuild.sh
Executable file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
WORKING_LOCATION="$(pwd)"
|
||||||
|
APPLICATION_NAME=Sora
|
||||||
|
|
||||||
|
if [ ! -d "build" ]; then
|
||||||
|
mkdir build
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd build
|
||||||
|
|
||||||
|
xcodebuild -project "$WORKING_LOCATION/$APPLICATION_NAME.xcodeproj" \
|
||||||
|
-scheme "$APPLICATION_NAME" \
|
||||||
|
-configuration Release \
|
||||||
|
-derivedDataPath "$WORKING_LOCATION/build/DerivedDataApp" \
|
||||||
|
-destination 'platform=macOS,variant=Mac Catalyst' \
|
||||||
|
clean build \
|
||||||
|
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
|
||||||
|
|
||||||
|
DD_APP_PATH="$WORKING_LOCATION/build/DerivedDataApp/Build/Products/Release-maccatalyst/$APPLICATION_NAME.app"
|
||||||
|
TARGET_APP="$WORKING_LOCATION/build/$APPLICATION_NAME.app"
|
||||||
|
|
||||||
|
if [ -e "$TARGET_APP" ]; then
|
||||||
|
rm -rf "$TARGET_APP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp -r "$DD_APP_PATH" "$TARGET_APP"
|
||||||
|
|
||||||
|
codesign --remove "$TARGET_APP"
|
||||||
|
if [ -e "$TARGET_APP/_CodeSignature" ]; then
|
||||||
|
rm -rf "$TARGET_APP/_CodeSignature"
|
||||||
|
fi
|
||||||
|
|
||||||
|
zip -vr "$APPLICATION_NAME-catalyst.zip" "$APPLICATION_NAME.app"
|
||||||
|
rm -rf "$APPLICATION_NAME.app"
|
||||||
Loading…
Reference in a new issue