mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +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
|
||||
jobs:
|
||||
build:
|
||||
name: Build IPA
|
||||
name: Build IPA and Mac Catalyst
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- name: Use Node.js 20
|
||||
|
|
@ -27,3 +27,15 @@ jobs:
|
|||
name: Sora-IPA
|
||||
path: build/Sora.ipa
|
||||
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 */; };
|
||||
132417D72D13242400B4F2D2 /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D62D13242400B4F2D2 /* CircularProgressBar.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 */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
|
@ -73,6 +74,8 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
|
@ -126,6 +129,7 @@
|
|||
132417822D13198000B4F2D2 /* Sora */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1352BA6F2D1AB113000A9AF9 /* Sora.entitlements */,
|
||||
132417C52D131AA500B4F2D2 /* Info.plist */,
|
||||
132417912D1319E800B4F2D2 /* Utils */,
|
||||
132417A52D131A0600B4F2D2 /* Views */,
|
||||
|
|
@ -170,6 +174,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
132417952D1319E800B4F2D2 /* Notification.swift */,
|
||||
1352BA702D1ABC30000A9AF9 /* URLSession.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -376,6 +381,7 @@
|
|||
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
||||
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
||||
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
||||
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */,
|
||||
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -504,6 +510,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Sora/Sora.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
||||
|
|
@ -524,6 +531,7 @@
|
|||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -535,6 +543,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Sora/Sora.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Sora/Preview Content\"";
|
||||
|
|
@ -555,6 +564,7 @@
|
|||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
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 {
|
||||
let selector: String
|
||||
let order: String
|
||||
let pattern: String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class ModulesManager: ObservableObject {
|
|||
completion(.failure(ModuleError.invalidURL))
|
||||
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 {
|
||||
completion(.failure(error ?? ModuleError.unknown))
|
||||
return
|
||||
|
|
@ -67,7 +67,7 @@ class ModulesManager: ObservableObject {
|
|||
func refreshModules() {
|
||||
for (name, urlString) in moduleURLs {
|
||||
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 }
|
||||
do {
|
||||
let updatedModule = try JSONDecoder().decode(ModuleStruct.self, from: data)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ extension AnimeInfoView {
|
|||
func fetchAnimeDetails() {
|
||||
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 }
|
||||
guard let data = data, error == nil else { return }
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ extension AnimeInfoView {
|
|||
guard let url = URL(string: urlString) else { return }
|
||||
|
||||
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 }
|
||||
|
||||
let html = String(data: data, encoding: .utf8) ?? ""
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ struct AnimeInfoView: View {
|
|||
.fontWeight(.bold)
|
||||
|
||||
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 totalTime = UserDefaults.standard.double(forKey: "totalTime_\(episodeURL)")
|
||||
let progress = totalTime > 0 ? lastPlayedTime / totalTime : 0
|
||||
|
|
@ -278,7 +278,7 @@ struct AnimeInfoView: View {
|
|||
let parameters: [String: Any] = ["query": query]
|
||||
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 {
|
||||
completion(.failure(error))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ struct EpisodeCell: View {
|
|||
return
|
||||
}
|
||||
|
||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||
URLSession.custom.dataTask(with: url) { data, response, error in
|
||||
if let error = error {
|
||||
print("Failed to fetch episode details: \(error)")
|
||||
DispatchQueue.main.async {
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ struct SearchResultsView: View {
|
|||
let urlString = "\(module.module[0].search.url)?\(module.module[0].search.parameter)=\(encodedSearchText)"
|
||||
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 }
|
||||
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