Compare commits
No commits in common. "main" and "0.1.1" have entirely different histories.
61
.github/workflows/schedule.yml
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repo content
|
||||
uses: actions/checkout@v3 # checkout the repository content to github runner.
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8 #install the python needed
|
||||
- name: install python packages
|
||||
run: |
|
||||
pip install PyGithub pandas mistletoe lxml beautifulsoup4
|
||||
- name: execute py script # run the run.py to get the latest data
|
||||
env:
|
||||
EMAIL_ADDRESS: ${{ secrets.EMAIL_ADDRESS }}
|
||||
EMAIL_PASSWORD: ${{ secrets.EMAIL_PASSWORD }}
|
||||
EMAIL_RECIPIENT: ${{ secrets.EMAIL_RECIPIENT }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
python generate_json.py -t ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
env:
|
||||
EMAIL_ADDRESS: ${{ secrets.EMAIL_ADDRESS }}
|
||||
EMAIL_PASSWORD: ${{ secrets.EMAIL_PASSWORD }}
|
||||
EMAIL_RECIPIENT: ${{ secrets.EMAIL_RECIPIENT }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
commit_message: Automated Change
|
||||
# Optional. Options used by `git-commit`.
|
||||
# See https://git-scm.com/docs/git-commit#_options
|
||||
commit_options: '--no-verify --signoff'
|
||||
file_pattern: 'app-repo.json app-repo-esign.json bundleId.csv icons/*'
|
||||
|
||||
# Optional commit user and author settings
|
||||
commit_user_name: My GitHub Actions Bot # defaults to "github-actions[bot]"
|
||||
commit_user_email: my-github-actions-bot@example.org # defaults to "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
commit_author: Author <actions@github.com> # defaults to author of the commit that triggered the run
|
||||
|
||||
push_options: '--force'
|
||||
|
||||
# - name: commit files
|
||||
# run: |
|
||||
# git config --local user.email "action@github.com"
|
||||
# git config --local user.name "GitHub Action"
|
||||
# git add -A
|
||||
# git commit -m "update apps.json" -a
|
||||
|
||||
# - name: push changes
|
||||
# uses: ad-m/github-push-action@v0.6.0
|
||||
# with:
|
||||
# github_token: ${{ secrets.SECRET_NAME }}
|
||||
# branch: main
|
||||
|
||||
1
.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
.DS_Store
|
||||
68
README.md
|
|
@ -1,66 +1,2 @@
|
|||
# Update
|
||||
|
||||
- Until further notice we are no longer updating this repo until Jan 7th. Cheers!
|
||||
|
||||
# Tutorial
|
||||
|
||||
- Copy this https://raw.githubusercontent.com/Realmzer/MySign-Repo/refs/heads/main/app-repo.json
|
||||
- Open your IPA signer and head to where you would add a repostiory (repostiories are JSON files that contain info that your IPA signer reads and displays)
|
||||
- Click add repository (repositories are also called repos)
|
||||
- Paste in the repo url
|
||||
- Reopen your signer and you should see MySign in your repo list
|
||||
|
||||
# MySign IPA Repository
|
||||
|
||||
Star our repo if you find it useful! (Thank you)
|
||||
|
||||
If you would like to request a IPA, ask for one in our [discord server](https://discord.gg/hUK5m9MGFc)
|
||||
|
||||
# Status Legend for IPAs
|
||||
✅ = Working
|
||||
|
||||
❌ = Not Working or discontinued
|
||||
|
||||
✨ = Tweak
|
||||
|
||||
❔ = Unknown if its still getting updates or source doesn't exist
|
||||
|
||||
🔵 = TrollStore only
|
||||
|
||||
💸 = Paid, not Cracked
|
||||
|
||||
🔥 = Recommended by MySign
|
||||
|
||||
🌟= Premium features unlocked
|
||||
|
||||
# IPA Reposters
|
||||
|
||||
| **Reposter** | **Source** |
|
||||
|:-------------|------------------------------|
|
||||
| [IPAUniverse: Telegram channel](https://t.me/lPAUniverse) → [IPAUniverse: GitHub repository](https://github.com/abdoomaster/IPA_Archive/) → [IPAUniverse: Website](https://www.ipauniverse.com/) **(MASSIVE CLONE, UNSAFE)** | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) / [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [iOSGods!](https://iosgods.com/) / [DPixel](https://t.me/dpixel) / [binnichtaktiv's iPA Library](https://t.me/binnichtaktivsipas) / [CyPwn IPA Library](https://ipa.cypwn.xyz) / [AppDB](https://appdb.to/) / [ipalibrary.me](https://ipalibrary.me) / [Kanji's discord](https://discord.gg/iotatweak) / [BandarHL](https://github.com/BandarHL/BHTikTok) / [dayanch96](https://github.com/dayanch96/BHTikTok) / [Manpreet Singh @thisismanpreeets](https://t.me/AppleTesters) / [iOS Tutorials + App Cracks](https://t.me/iOS_Randy420) / [whoeevee](https://github.com/whoeevee/EeveeSpotify) / [EeveeSpotify IPAs](https://t.me/SpotilifeIPAs) |
|
||||
| [CyPwn IPA Library](https://ipa.cypwn.xyz) | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) / [iOSGods!](https://iosgods.com/) |
|
||||
| [LEOZIN_IPA](https://t.me/LEOZIN_IPA) **(UNSAFE)** | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) / [Sultan Mods](https://t.me/SultanModsIPAs) |
|
||||
| [AppCake](https://www.iphonecake.com/tweak_index.php) **(CLONE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) / [iOSGods!](https://iosgods.com/) / [CyPwn IPA Library](https://ipa.cypwn.xyz) |
|
||||
| [KAMO HACkS](https://t.me/kamohacks) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [iOSGods!](https://iosgods.com/) |
|
||||
| [AppleFavour iPA Library](https://t.me/iparsiv) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) |
|
||||
| [IPA-GOLD](https://t.me/Proxy_Matrix) **(UNSAFE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [HertzSign iPA Library](https://t.me/HertzSign) / [binnichtaktiv's iPA Library](https://t.me/binnichtaktivsipas) |
|
||||
| [iOS_MATRIX](https://t.me/iOS_MATRIX) **(UNSAFE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) / [iOSGods!](https://iosgods.com/) / [iStorePlus](https://t.me/iStoreplus) / [LazyShop](https://lazyshop.app/) |
|
||||
| [IPA Fire](https://t.me/ipafire) **(UNSAFE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) / [Crack Hub](https://t.me/crackhub_69) / [Blatant](https://t.me/notblatant) |
|
||||
| [Panda Helper](https://pandahelp.vip/) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) / [iOSGods!](https://iosgods.com/) |
|
||||
| [AppValley VIP](https://signulous.app-valley.vip/) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) / [iOSGods!](https://iosgods.com/) |
|
||||
| [DVC iPA](https://t.me/dvcipaios) **(UNSAFE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [HertzSign iPA Library](https://t.me/HertzSign) |
|
||||
| [ipa.tweakdoor](https://ipa.tweakdoor.com/) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) |
|
||||
| [WuXu1](https://github.com/WuXu1/WuXu1.github.io/) → [AppDB](https://appdb.to/) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [Haidar_Phantom](https://iosgods.com/topic/171723-ytkillerplus_v18229_2214-cracked/) / [CyPwn IPA Library](https://ipa.cypwn.xyz) |
|
||||
| [Sultan Mods](https://t.me/SultanModsIPAs) | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) |
|
||||
| [Da StashSpot 2.0](https://t.me/DaStashSpot) **(UNSAFE)** | [zxcvbn's tweaked IPAs](https://t.me/zxcvbn_tweaked) / [AppDB](https://appdb.to/) / [BandarHL](https://github.com/BandarHL/BHTikTok) / [dayanch96](https://github.com/dayanch96/BHTikTok) / [ipalibrary.me](https://ipalibrary.me) / [DPixel](https://t.me/dpixel) / [iOSGods!](https://iosgods.com/) |
|
||||
| [Makarr iOS TikTok mod](https://t.me/MakarrIOS) | [iStorePlus](https://t.me/iStoreplus) / [LazyShop](https://lazyshop.app/) / [DzMoha](https://twitter.com/contact_nadhir) / [BandarHL](https://github.com/BandarHL/BHTikTok) / [dayanch96](https://github.com/dayanch96/BHTikTok) |
|
||||
| [ipaomtk](https://ipaomtk.com/) | [iOSGods!](https://iosgods.com/) / [AppDB](https://appdb.to/) |
|
||||
| [IPA Free](https://t.me/IPA_FREE_RAK) | [iOSGods!](https://iosgods.com/) / [ipalibrary.me](https://ipalibrary.me) |
|
||||
| [Trollstore+jailbreak](https://t.me/trollstorebootstrap) | [nowesr1](https://twitter.com/nowesr1) |
|
||||
| [TrollStore AppsUpdates](https://t.me/TrollStoreApps) | [nowesr1](https://twitter.com/nowesr1) |
|
||||
| [Zappfree](https://zappfree.com/ipa-library/) → [TweakHome: Website](https://tweakhome.app/) **(UNSAFE)** | [iOSGods!](https://iosgods.com/) |
|
||||
| [TweakHome: Telegram channel](https://t.me/tweakhomeapps) **(UNSAFE)** | [iOSGods!](https://iosgods.com/) |
|
||||
| [IAppsBestLibrary](https://t.me/IAppsBestLibrary) | [iOS Tutorials + App Cracks](https://t.me/iOS_Randy420) |
|
||||
| [iexmo](https://iexmo.com/ipastore/) **(CLONE)** | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) / [ipalibrary.me](https://ipalibrary.me) |
|
||||
| [shuyuan](https://github.com/shidahuilang/shuyuan) **(CLONE)** | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IPAs) |
|
||||
| [ThuthuatJB](https://ipa.thuthuatjb.com/) | [TrollStore-IPAs](https://github.com/swaggyP36000/TrollStore-IP)
|
||||
# IPA-Repo
|
||||
Realmzer's IPA Repo
|
||||
|
|
|
|||
6339
app-repo.json
184
generate_json.py
|
|
@ -1,12 +1,69 @@
|
|||
from github import Github
|
||||
import json
|
||||
import argparse
|
||||
import pandas as pd
|
||||
from get_bundle_id import get_single_bundle_id
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from io import StringIO
|
||||
|
||||
REPO_NAME = "Realmzer/MySign-Repo"
|
||||
import mistletoe
|
||||
import pandas as pd
|
||||
from bs4 import BeautifulSoup
|
||||
from github import Github
|
||||
|
||||
from get_bundle_id import get_single_bundle_id
|
||||
|
||||
|
||||
def transform_object(original_object):
|
||||
transformed_object = {**original_object, "app-repo": None}
|
||||
|
||||
app_map = {}
|
||||
|
||||
for app in original_object["app-repo"]:
|
||||
(
|
||||
name,
|
||||
bundle_identifier,
|
||||
version,
|
||||
version_date,
|
||||
size,
|
||||
download_url,
|
||||
developer_name,
|
||||
localized_description,
|
||||
icon_url,
|
||||
) = (
|
||||
app["name"],
|
||||
app["bundleIdentifier"],
|
||||
app["version"],
|
||||
app["versionDate"],
|
||||
app["size"],
|
||||
app["downloadURL"],
|
||||
app["developerName"],
|
||||
app["localizedDescription"],
|
||||
app["iconURL"],
|
||||
)
|
||||
|
||||
if name not in app_map:
|
||||
app_map[name] = {
|
||||
"name": name,
|
||||
"bundleIdentifier": bundle_identifier,
|
||||
"developerName": developer_name,
|
||||
"iconURL": icon_url,
|
||||
"versions": [],
|
||||
}
|
||||
|
||||
app_map[name]["versions"].append(
|
||||
{
|
||||
"version": version,
|
||||
"date": version_date,
|
||||
"size": size,
|
||||
"downloadURL": download_url,
|
||||
"localizedDescription": localized_description,
|
||||
}
|
||||
)
|
||||
|
||||
for name, app_info in app_map.items():
|
||||
app_info["versions"].sort(key=lambda x: x["date"], reverse=True)
|
||||
|
||||
transformed_object["app-repo"] = list(app_map.values())
|
||||
|
||||
return transformed_object
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
@ -15,91 +72,80 @@ if __name__ == "__main__":
|
|||
args = parser.parse_args()
|
||||
token = args.token
|
||||
|
||||
out_file = "apps-repo.json"
|
||||
|
||||
with open(out_file, "r") as f:
|
||||
with open("app-repo.json", "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if os.path.isfile("bundleId.csv"):
|
||||
if os.path.exists("bundleId.csv"):
|
||||
df = pd.read_csv("bundleId.csv")
|
||||
else:
|
||||
df = pd.DataFrame(columns=["name", "bundleId", "genre"])
|
||||
df = pd.DataFrame(columns=["name", "bundleId"])
|
||||
|
||||
md_df = None
|
||||
if os.path.exists("README.md"):
|
||||
with open("README.md", "r", encoding="utf-8") as f:
|
||||
raw_md = f.read()
|
||||
html = mistletoe.markdown(raw_md)
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
table = soup.find_all("table")[1]
|
||||
md_df = pd.read_html(StringIO(str(table)), keep_default_na=False)[0]
|
||||
md_df["App Name"] = md_df["App Name"].str.replace(" ", "").str.lower()
|
||||
|
||||
# clear apps
|
||||
data["apps"] = []
|
||||
data["app-repo"] = []
|
||||
|
||||
g = Github(token)
|
||||
repo = g.get_repo(REPO_NAME)
|
||||
repo = g.get_repo("Realmzer/IPA-Repo")
|
||||
releases = repo.get_releases()
|
||||
|
||||
for release in releases:
|
||||
print(release.title)
|
||||
|
||||
for asset in release.get_assets():
|
||||
if (spl := asset.name.split("."))[-1] not in ("ipa", "dylib", "deb"):
|
||||
if asset.name[-3:] != "ipa":
|
||||
continue
|
||||
IS_IPA = spl[-1] == "ipa"
|
||||
name = ".".join(spl[:-1])
|
||||
name = asset.name[:-4]
|
||||
date = asset.created_at.strftime("%Y-%m-%d")
|
||||
full_date = asset.created_at.strftime("%Y%m%d%H%M%S")
|
||||
try:
|
||||
app_name, version, tweaks = name.split("_", 2)
|
||||
tweaks, _ = tweaks.split("@", 1)
|
||||
if tweaks:
|
||||
tweaks = f"Injected with {tweaks[:-1].replace("_", " ")}"
|
||||
except Exception:
|
||||
app_name, version = name.split("-", 1)
|
||||
except:
|
||||
app_name = name
|
||||
version = "Unknown"
|
||||
tweaks = None
|
||||
version = "1.0"
|
||||
|
||||
if IS_IPA:
|
||||
if app_name in df.name.values:
|
||||
info = {"bundle": df[df.name == app_name].bundleId.values[0], "genre": df[df.name == app_name].genre.values[0]}
|
||||
else:
|
||||
info: dict = get_single_bundle_id(asset.browser_download_url)
|
||||
|
||||
if "error" in info:
|
||||
print(f"[*] error detected in '{name}', deleting")
|
||||
asset.delete_asset()
|
||||
continue
|
||||
|
||||
df = pd.concat([df, pd.DataFrame(
|
||||
{"name": [app_name], "bundleId": [info["bundle"]], "genre": [info["genre"]]})], ignore_index=True)
|
||||
|
||||
data["apps"].append({
|
||||
"name": app_name,
|
||||
"type": int(info["genre"]),
|
||||
"bundleID": str(info["bundle"]),
|
||||
"bundleIdentifier": str(info["bundle"]),
|
||||
"version": version,
|
||||
"versionDate": date,
|
||||
"fullDate": full_date,
|
||||
"size": int(asset.size),
|
||||
"down": asset.browser_download_url,
|
||||
"downloadURL": asset.browser_download_url,
|
||||
"developerName": "",
|
||||
"localizedDescription": tweaks,
|
||||
"icon": f"https://raw.githubusercontent.com/{REPO_NAME}/main/icons/{info["bundle"]}.png",
|
||||
"iconURL": f"https://raw.githubusercontent.com/{REPO_NAME}/main/icons/{info["bundle"]}.png"
|
||||
})
|
||||
if app_name in df.name.values:
|
||||
bundle_id = str(df[df.name == app_name].bundleId.values[0])
|
||||
else:
|
||||
data["apps"].append({
|
||||
bundle_id = get_single_bundle_id(asset.browser_download_url)
|
||||
df = pd.concat([df, pd.DataFrame({"name": [app_name], "bundleId": [bundle_id]})], ignore_index=True)
|
||||
|
||||
desc = ""
|
||||
dev_name = ""
|
||||
if md_df is not None:
|
||||
row = md_df.loc[md_df["App Name"] == app_name.replace(" ", "").lower()]
|
||||
if len(row.values):
|
||||
raw_desc = row["Description"].values[0]
|
||||
raw_last_updated = row["Last Updated"].values[0]
|
||||
raw_status = row["Status"].values[0]
|
||||
desc = f"{raw_desc}\nLast updated: {raw_last_updated}\nStatus: {raw_status}"
|
||||
dev_name = f"{row['Source/Maintainer'].values[0]}"
|
||||
|
||||
data["app-repo"].append(
|
||||
{
|
||||
"name": app_name,
|
||||
"type": 5, # type: dylib
|
||||
"bundleId": f"com.mysign.{app_name.lower()}",
|
||||
"bundleIdentifier": f"com.mysign.{app_name.lower()}",
|
||||
"bundleIdentifier": bundle_id,
|
||||
"version": version,
|
||||
"versionDate": date,
|
||||
"fullDate": full_date,
|
||||
"size": int(asset.size),
|
||||
"down": asset.browser_download_url,
|
||||
"size": asset.size,
|
||||
"downloadURL": asset.browser_download_url,
|
||||
"developerName": "",
|
||||
"localizedDescription": app_name,
|
||||
"icon": "https://cdn1.realmzer.xyz//IMG_3830-tF.png",
|
||||
"iconURL": "https://cdn1.realmzer.xyz//IMG_3830-tF.png"
|
||||
})
|
||||
"developerName": dev_name,
|
||||
"localizedDescription": desc,
|
||||
"iconURL": f"https://raw.githubusercontent.com/Realmzer/IPA-Repo/main/icons/{bundle_id}.png",
|
||||
}
|
||||
)
|
||||
|
||||
data["apps"].sort(key=lambda x: x["fullDate"], reverse=True)
|
||||
df.to_csv("bundleId.csv", index=False)
|
||||
|
||||
with open(out_file, 'w') as json_file:
|
||||
json.dump(data, json_file, indent=4)
|
||||
with open("app-repo-esign.json", "w") as json_file:
|
||||
json.dump(data, json_file, indent=2)
|
||||
|
||||
with open("app-repo.json", "w") as file:
|
||||
json.dump(transform_object(data), file, indent=2)
|
||||
171
get_bundle_id.py
|
|
@ -1,96 +1,99 @@
|
|||
import os
|
||||
import requests
|
||||
import zipfile
|
||||
import plistlib
|
||||
from tempfile import NamedTemporaryFile as NTF
|
||||
|
||||
import requests
|
||||
from PIL import Image
|
||||
import github
|
||||
import pandas as pd
|
||||
import shutil
|
||||
import os
|
||||
|
||||
|
||||
# returns genre id
|
||||
def save_appstore_icon(bundle: str) -> dict:
|
||||
x = requests.get(f"https://itunes.apple.com/lookup?bundleId={bundle}&limit=1&country=US").json()
|
||||
try:
|
||||
icon_url = x["results"][0]["artworkUrl512"]
|
||||
genres = x["results"][0]["genreIds"]
|
||||
except (KeyError, IndexError):
|
||||
# type 1 = app
|
||||
return {"genre": 1, "err": True} # invalid appstore app, will have to extract from ipa
|
||||
|
||||
with NTF() as tmp:
|
||||
tmp.write(requests.get(icon_url).content)
|
||||
with Image.open(tmp.name) as img:
|
||||
img.save(f"icons/{bundle}.png", "PNG") # usually jpg, so we save as png instead
|
||||
|
||||
if "6014" in genres or any(genre.startswith("70") for genre in genres):
|
||||
return {"genre": 2, "err": False} # type 2 = game
|
||||
return {"genre": 1, "err": False}
|
||||
def get_single_bundle_id(url, name="temp.ipa"):
|
||||
reponse = requests.get(url)
|
||||
open(name, 'wb').write(reponse.content)
|
||||
|
||||
icon_folder = "icons/"
|
||||
if not os.path.exists(icon_folder):
|
||||
os.mkdir(icon_folder)
|
||||
|
||||
with zipfile.ZipFile(name, mode="r") as archive:
|
||||
for file_name in archive.namelist():
|
||||
if file_name.endswith(".app/Info.plist"):
|
||||
info_file = file_name
|
||||
folder_path = os.path.dirname(info_file)
|
||||
|
||||
with archive.open(info_file) as fp:
|
||||
pl = plistlib.load(fp)
|
||||
icon_path = ""
|
||||
bundleId = pl["CFBundleIdentifier"]
|
||||
if "CFBundleIconFiles" in pl.keys():
|
||||
try:
|
||||
icon_path = os.path.join(
|
||||
folder_path, pl["CFBundleIconFiles"][0])
|
||||
except:
|
||||
# index [0] out-of-range: empty icon list
|
||||
return bundleId
|
||||
if "CFBundleIcons" in pl.keys():
|
||||
try:
|
||||
icon_prefix = pl["CFBundleIcons"]["CFBundlePrimaryIcon"]["CFBundleIconFiles"][0]
|
||||
except:
|
||||
icon_prefix = pl["CFBundleIcons"]["CFBundlePrimaryIcon"]["CFBundleIconName"]
|
||||
for file_name in archive.namelist():
|
||||
if icon_prefix in file_name:
|
||||
icon_path = file_name
|
||||
if icon_path:
|
||||
try:
|
||||
with archive.open(icon_path) as origin, open(icon_folder + bundleId + ".png", "wb") as dst:
|
||||
shutil.copyfileobj(origin, dst)
|
||||
except:
|
||||
pass
|
||||
else: # no icon info
|
||||
pass
|
||||
|
||||
return bundleId
|
||||
|
||||
return "com.example.app"
|
||||
|
||||
|
||||
# this is shit so gotta seperate into its own func lol
|
||||
# TIL: the namelist doesnt always have the .app name??
|
||||
def get_app_name(nl: list[str]) -> str:
|
||||
for name in nl:
|
||||
if ".app/" in name and len(name.split("/")) >= 2:
|
||||
return "/".join(name.split("/")[:2])
|
||||
return ""
|
||||
def generate_bundle_id_csv(token):
|
||||
g = github.Github(token)
|
||||
repo = g.get_repo("Realmzer/IPA-Repo")
|
||||
releases = repo.get_releases()
|
||||
|
||||
df = pd.DataFrame(columns=["name", "bundleId"])
|
||||
|
||||
# uses same method as seashell cli:
|
||||
# https://github.com/EntySec/SeaShell/blob/8ae1ecba722ba303c961c537633b663717fcfbe7/seashell/core/ipa.py#L189
|
||||
def no_seashell(path: str) -> dict:
|
||||
with zipfile.ZipFile(path) as zf:
|
||||
app: str = get_app_name((nl := zf.namelist()))
|
||||
for release in releases:
|
||||
date = release.created_at.strftime("%Y-%m-%d")
|
||||
if date > "2022-11-10":
|
||||
continue
|
||||
print(release.title)
|
||||
for asset in release.get_assets():
|
||||
if (asset.name[-3:] != "ipa"):
|
||||
continue
|
||||
name = asset.name[:-4]
|
||||
print(asset.name)
|
||||
|
||||
if f"{app}/mussel" in nl:
|
||||
return {"unsafe": 1}
|
||||
|
||||
# note: `CFBundleSignature` is now appearing in the real world?
|
||||
# why is this even becoming an official key? whatever
|
||||
|
||||
with zf.open((pl_name := f"{app}/Info.plist")) as pl:
|
||||
plist = plistlib.load(pl)
|
||||
|
||||
# if "CFBundleSignature" in plist:
|
||||
# return {"unsafe": 1}
|
||||
|
||||
return {"pl": plist, "nl": nl, "pl_name": pl_name}
|
||||
|
||||
|
||||
# if called, guaranteed that icon is not yet saved
|
||||
def get_single_bundle_id(url, name = "temp.ipa") -> dict:
|
||||
with open(name, "wb") as f:
|
||||
f.write(requests.get(url).content)
|
||||
|
||||
os.makedirs("icons", exist_ok=True)
|
||||
|
||||
try:
|
||||
assert(zipfile.is_zipfile(name))
|
||||
except AssertionError:
|
||||
print(f"[!] bad zipfile: {os.path.basename(url)} ({url})")
|
||||
return {"error": 1}
|
||||
|
||||
try:
|
||||
assert("unsafe" not in (sscheck := no_seashell(name)))
|
||||
except AssertionError:
|
||||
print(f"[!] seashell detected in: {os.path.basename(url)} ({url})")
|
||||
return {"error": 1}
|
||||
|
||||
with zipfile.ZipFile(name) as archive:
|
||||
bundleId = sscheck["pl"]["CFBundleIdentifier"]
|
||||
|
||||
if (res := save_appstore_icon(bundleId))["err"]:
|
||||
try:
|
||||
icon_path = sscheck["pl"]["CFBundleIcons"]["CFBundlePrimaryIcon"]["CFBundleIconFiles"][0]
|
||||
for name in sscheck["nl"]:
|
||||
if icon_path in name:
|
||||
icon_path = name # im so tired
|
||||
break
|
||||
except (KeyError, IndexError):
|
||||
# is this doing what i think it's doing..?
|
||||
icon_path = f"{os.path.dirname(sscheck["pl_name"])}/{sscheck["pl"]["CFBundleIconFiles"][0]}"
|
||||
app_name = name.split("-", 1)[0]
|
||||
except:
|
||||
app_name = name
|
||||
|
||||
with archive.open(icon_path) as orig, open(f"icons/{bundleId}.png", "wb") as new:
|
||||
new.write(orig.read())
|
||||
if app_name in df.name.values:
|
||||
continue
|
||||
df = pd.concat(
|
||||
[
|
||||
df,
|
||||
pd.DataFrame(
|
||||
{
|
||||
"name": [app_name],
|
||||
"bundleId": get_single_bundle_id(asset.browser_download_url)
|
||||
}
|
||||
)
|
||||
],
|
||||
ignore_index=True
|
||||
)
|
||||
|
||||
return {"bundle": bundleId, "genre": res["genre"]}
|
||||
df.to_csv("bundleIdmap.csv", index=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
Before Width: | Height: | Size: 8.3 KiB |
BIN
images/Azula.png
|
Before Width: | Height: | Size: 46 KiB |
BIN
images/FCM.png
|
Before Width: | Height: | Size: 676 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
BIN
images/esign.png
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 553 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 288 KiB |
BIN
images/osu.png
|
Before Width: | Height: | Size: 438 KiB |
|
Before Width: | Height: | Size: 957 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
|
@ -1 +0,0 @@
|
|||
This folder contains the images for the IPA's and my website.
|
||||
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 10 KiB |