From 295b6933f65e8ac931cf834a86e36b720b175c1b Mon Sep 17 00:00:00 2001 From: Balackburn <93828569+Balackburn@users.noreply.github.com> Date: Fri, 7 Jul 2023 17:44:32 +0200 Subject: [PATCH] updated github pages to includes altstore source --- .github/workflows/update_source.yml | 50 +++++++++++++ Altstore/apps.json | 108 ++++++++++++++++++++++++++++ Altstore/index.html | 24 ------- Altstore/scripts/update_json.py | 61 ++++++++++++++++ images/image_0.png | Bin 10748 -> 8825 bytes index.html | 4 +- 6 files changed, 222 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/update_source.yml create mode 100644 Altstore/apps.json delete mode 100644 Altstore/index.html create mode 100644 Altstore/scripts/update_json.py diff --git a/.github/workflows/update_source.yml b/.github/workflows/update_source.yml new file mode 100644 index 0000000..4539108 --- /dev/null +++ b/.github/workflows/update_source.yml @@ -0,0 +1,50 @@ +name: Update apps.json everyday + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + repository_dispatch: + types: [update-altstore-source-trigger] + +jobs: + update_json: + runs-on: ubuntu-latest + + steps: + - name: Delay for repository_dispatch event + if: github.event_name == 'repository_dispatch' + run: | + echo "Waiting for 8 minutes..." + sleep 480 # 8 minutes x 60 seconds + + - name: Check out repository + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.x + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests + + - name: Run script + run: | + python Altstore/scripts/update_json.py + + - name: Check for changes + id: check_changes + run: | + git diff --exit-code || echo "::set-output name=has_changes::true" + + - name: Commit and push changes + if: steps.check_changes.outputs.has_changes == 'true' + run: | + git config --global user.email "actions@github.com" + git config --global user.name "GitHub Actions" + git add . + git commit -m "Update JSON file with latest release" + git push \ No newline at end of file diff --git a/Altstore/apps.json b/Altstore/apps.json new file mode 100644 index 0000000..e4d38a8 --- /dev/null +++ b/Altstore/apps.json @@ -0,0 +1,108 @@ +{ + "name": "YTLitePlus (for Altstore)", + "identifier": "com.ytlite.source", + "apps": [ + { + "beta": false, + "name": "Youtube (YTLitePlus)", + "bundleIdentifier": "com.google.ios.youtube", + "developerName": "Dayanch96 & Arichorn", + "subtitle": "YTLite with more features!", + "version": "18.25.1", + "versionDate": "2023-07-07T11:40:48Z", + "versionDescription": "Current YouTube IPA: \"18.25.1\" \r\nCurrent YTLitePlus Version: \"2.2\" \r\nCurrent App Compatibility: \"iOS/iPadOS 14.0\" or later\r\n\r\nRELEASE 18.25.1\u20222.2: (2023\u202207\u202207)\r\n\r\n\u2022 Updated YTLite from \"2.1\" to \"2.2\" (@dayanch96) \r\n \u2022 Added:\r\n \u2022 Extra speed options\r\n \u2022 Auto fullscreen\r\n \u2022 Remove 'Play next in queue' from the menu\r\n \u2022 Remove 'Continue watching' block\r\n \u2022 Fixed:\r\n \u2022 'Classic Video Quality' option for newer YT versions (See line 278)\r\n \u2022 'Disable Double Tap To Seek' option for newer YT versions\r\n \u2022 Some Shorts was appearing in Search results\r\n \u2022 Enabled ads was displaying blank blocks instead of ads in home feed\r\n\r\n\u2022 Added \"YTNoCommunityPosts\" (@arichorn)\r\n \u2022 Tweak to add a setting to disable all Community Posts on the YouTube app\r\n \r\n\u2022 Added \"AppVersionSpoofer\" (@arichorn)\r\n \u2022 Mimic YouTube versions to access specific features, layouts, and resolve issues.\r\n\r\n\u2022 Fixed issue 3 \r\n\r\nIssues in this Release:\r\n\u2022 LowContrastMode doesn't work (it work with older YT version)\r\n\u2022 YTSpeed not working (both broken in v18.19.1+)", + "downloadURL": "https://github.com/Balackburn/YTLitePlus/releases/download/v18.25.1-2.2/YTLitePlus_18.25.1_2.2.ipa", + "localizedDescription": "YTLite with more features! \n\nSupercharge your YouTube experience with +15 tweaks: \n\n\u2022 YTLite: Ad-blocking & background playback, +50 options\n\u2022 iSponsorBlock: Skip sponsor ads\n\u2022 YouPiP: Native PiP mode\n\u2022 YTUHD: 2K & 4K video quality\n\u2022 YouTube Dislike Return: Reinstate dislike counts\n\u2022 YTClassicVideoQuality: Old video quality selector\n\u2022 YTNoHoverCards: Disable suggested videos\n\u2022 YTABGoodies: Disable A/B testing features\n\u2022 NOYTPremium: Remove Premium upsell alerts\n\u2022 YTSpeed: Add 2.25x to 4x playback speeds\n\u2022 YTMiniplayerEnabler: Enable Miniplayer\n\u2022 DontEatMyContent: Prevent notch issues\n\u2022 YTShortsProgress: Enable progress bar for Shorts\n\u2022 YTABConfig: Control A/B testing flags\n\u2022 YouMute: Mute/unmute videos\n\u2022 LowContrastMode: Reduce interface contrast\n\u2022 And many more...", + "iconURL": "https://balackburn.github.io/YTLitePlus/images/image_0.png", + "tintColor": "e22a41", + "size": 102617217, + "screenshotURLs": [ + "https://balackburn.github.io/YTLitePlus/images/image_6.png", + "https://balackburn.github.io/YTLitePlus/images/image_7.png", + "https://balackburn.github.io/YTLitePlus/images/image_8.png", + "https://balackburn.github.io/YTLitePlus/images/image_9.png", + "https://balackburn.github.io/YTLitePlus/images/image_10.png", + "https://balackburn.github.io/YTLitePlus/images/image_11.png", + "https://balackburn.github.io/YTLitePlus/images/image_12.png", + "https://balackburn.github.io/YTLitePlus/images/image_13.png" + ], + "appPermissions": { + "entitlements": [ + { + "name": "com.apple.security.application-groups" + }, + { + "name": "com.apple.developer.associated-domains" + }, + { + "name": "com.apple.developer.coremedia.allow-alternate-video-decoder-selection" + }, + { + "name": "com.apple.developer.usernotifications.time-sensitive" + }, + { + "name": "com.apple.developer.coremedia.allow-alternate-video-decoder-selection" + }, + { + "name": "com.apple.developer.usernotifications.time-sensitive" + }, + { + "name": "get-task-allow" + }, + { + "name": "com.apple.developer.device-information.user-assigned-device-name" + }, + { + "name": "com.apple.developer.group-session" + }, + { + "name": "keychain-access-groups" + }, + { + "name": "com.apple.developer.networking.multicast" + }, + { + "name": "aps-environment" + }, + { + "name": "com.apple.developer.networking.wifi-info" + } + ], + "privacy": [ + { + "name": "AppleMusic", + "usageDescription": "YTLitePlus requires access to your Apple Music library." + }, + { + "name": "BluetoothPeripheral", + "usageDescription": "YTLitePlus requires Bluetooth access to connect with nearby peripherals." + }, + { + "name": "Camera", + "usageDescription": "YTLitePlus requires access to the camera to capture photos and videos." + }, + { + "name": "Contacts", + "usageDescription": "YTLitePlus requires access to your contacts to help you share content with your friends." + }, + { + "name": "LocalNetwork", + "usageDescription": "YTLitePlus requires local network access to connect and communicate with nearby devices." + }, + { + "name": "LocationWhenInUse", + "usageDescription": "YTLitePlus requires access to your location while using the app to provide personalized recommendations." + }, + { + "name": "Microphone", + "usageDescription": "YTLitePlus requires access to your microphone to record audio." + }, + { + "name": "PhotoLibrary", + "usageDescription": "YTLitePlus requires access to your Photo Library to save photos and videos." + } + ] + } + } + ] +} \ No newline at end of file diff --git a/Altstore/index.html b/Altstore/index.html deleted file mode 100644 index de0567b..0000000 --- a/Altstore/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Altstore JSON Content - - - - - \ No newline at end of file diff --git a/Altstore/scripts/update_json.py b/Altstore/scripts/update_json.py new file mode 100644 index 0000000..7a316ef --- /dev/null +++ b/Altstore/scripts/update_json.py @@ -0,0 +1,61 @@ +import json +import re +import requests + +# Fetch the latest release information from GitHub +def fetch_latest_release(repo_url, keyword): + api_url = f"https://api.github.com/repos/{repo_url}/releases" + headers = {"Accept": "application/vnd.github+json"} + response = requests.get(api_url, headers=headers) + releases = response.json() + sorted_releases = sorted(releases, key=lambda x: x["published_at"], reverse=True) + + for release in sorted_releases: + if keyword in release["name"]: + return release + + raise ValueError(f"No release found containing the keyword '{keyword}'.") + +# Update the JSON file with the fetched data +def remove_tags(text): + text = re.sub('<[^<]+?>', '', text) # Remove HTML tags + text = re.sub(r'#{1,6}\s?', '', text) # Remove markdown header tags + return text + +def update_json_file(json_file, fetched_data): + with open(json_file, "r") as file: + data = json.load(file) + + app = data["apps"][0] + version = re.search(r"(\d+\.\d+\.\d+)", fetched_data["tag_name"]).group(1) + app["version"] = version + app["versionDate"] = fetched_data["published_at"] + + description = fetched_data["body"] + keyword = "YTLitePlus Release Information" + if keyword in description: + description = description.split(keyword, 1)[1].strip() + + description = remove_tags(description) + description = re.sub(r'\*{2}', '', description) + description = re.sub(r'-', '•', description) + description = re.sub(r'`', '"', description) + + app["versionDescription"] = description + app["downloadURL"] = fetched_data["assets"][0]["browser_download_url"] + app["size"] = fetched_data["assets"][0]["size"] + + with open(json_file, "w") as file: + json.dump(data, file, indent=2) + +# Main function +def main(): + repo_url = "Balackburn/YTLitePlus" + json_file = "../apps.json" + keyword = "YTLitePlus" + + fetched_data = fetch_latest_release(repo_url, keyword) + update_json_file(json_file, fetched_data) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/images/image_0.png b/images/image_0.png index 39e053368e5d1a5370aa338482dba4c8db027756..0753d353654f8ee606146733178d2f69ebe5a47b 100644 GIT binary patch literal 8825 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 literal 10748 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 with more features!