mirror of
https://github.com/Realmzer/MySign-Repo.git
synced 2026-01-12 02:32:25 +00:00
Feather
This commit is contained in:
parent
b74271565d
commit
316dd4de53
5 changed files with 347 additions and 0 deletions
61
.github/workflows/schedule.yml
vendored
Normal file
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
|
||||
|
||||
36
app-repo.json
Normal file
36
app-repo.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "Realmzer IPA Repository",
|
||||
"identifier": "realmzer.ipa-repo",
|
||||
"iconURL": "https://github.com/khcrysalis/Feather/blob/main/iOS/Icons/Main/Mac%403x.png?raw=true",
|
||||
"apps": [
|
||||
{
|
||||
"name": "Feather",
|
||||
"bundleIdentifier": "kh.crysalis.feather",
|
||||
"developerName": "Samara",
|
||||
"iconURL": "https://github.com/Realmzer/IOS-Repo/blob/main/images/feather.png?raw=true",
|
||||
"localizedDescription": "Feather is a free on-device iOS application manager/installer built with UIKit for quality.",
|
||||
"subtitle": "On-device signing application",
|
||||
"tintColor": "848ef9",
|
||||
"versions": [
|
||||
{
|
||||
"version": "v1.0.1",
|
||||
"date": "2024-08-30T18:34:10Z",
|
||||
"size": 12375230,
|
||||
"downloadURL": "https://github.com/Realmzer/IOS-Repo/releases/download/0.1/feather_v1.0.1.ipa"
|
||||
},
|
||||
{
|
||||
"version": "v1.0",
|
||||
"date": "2024-08-24T18:34:10Z",
|
||||
"size": 12375230,
|
||||
"downloadURL": "https://github.com/Realmzer/IOS-Repo/releases/download/0.1/feather_v1.0.ipa"
|
||||
}
|
||||
],
|
||||
"size": 12375230,
|
||||
"version": "v1.0.1",
|
||||
"versionDate": "2024-08-30T18:34:10Z",
|
||||
"downloadURL": "https://github.com/Realmzer/IOS-Repo/releases/download/0.1/feather_v1.0.1.ipa",
|
||||
"appPermissions": {}
|
||||
}
|
||||
],
|
||||
"news": []
|
||||
}
|
||||
151
generate_json.py
Normal file
151
generate_json.py
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import argparse
|
||||
import json
|
||||
import os
|
||||
from io import StringIO
|
||||
|
||||
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__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-t", "--token", help="Github token")
|
||||
args = parser.parse_args()
|
||||
token = args.token
|
||||
|
||||
with open("app-repo.json", "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if os.path.exists("bundleId.csv"):
|
||||
df = pd.read_csv("bundleId.csv")
|
||||
else:
|
||||
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["app-repo"] = []
|
||||
|
||||
g = Github(token)
|
||||
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 asset.name[-3:] != "ipa":
|
||||
continue
|
||||
name = asset.name[:-4]
|
||||
date = asset.created_at.strftime("%Y-%m-%d")
|
||||
try:
|
||||
app_name, version = name.split("-", 1)
|
||||
except:
|
||||
app_name = name
|
||||
version = "1.0"
|
||||
|
||||
if app_name in df.name.values:
|
||||
bundle_id = str(df[df.name == app_name].bundleId.values[0])
|
||||
else:
|
||||
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,
|
||||
"bundleIdentifier": bundle_id,
|
||||
"version": version,
|
||||
"versionDate": date,
|
||||
"size": asset.size,
|
||||
"downloadURL": asset.browser_download_url,
|
||||
"developerName": dev_name,
|
||||
"localizedDescription": desc,
|
||||
"iconURL": f"https://raw.githubusercontent.com/Realmzer/IPA-Repo/main/icons/{bundle_id}.png",
|
||||
}
|
||||
)
|
||||
|
||||
df.to_csv("bundleId.csv", index=False)
|
||||
|
||||
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)
|
||||
99
get_bundle_id.py
Normal file
99
get_bundle_id.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import requests
|
||||
import zipfile
|
||||
import plistlib
|
||||
import github
|
||||
import pandas as pd
|
||||
import shutil
|
||||
import os
|
||||
|
||||
|
||||
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"
|
||||
|
||||
|
||||
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"])
|
||||
|
||||
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)
|
||||
|
||||
try:
|
||||
app_name = name.split("-", 1)[0]
|
||||
except:
|
||||
app_name = name
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
df.to_csv("bundleIdmap.csv", index=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
BIN
images/feather.png
Normal file
BIN
images/feather.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 587 KiB |
Loading…
Reference in a new issue