mirror of
https://github.com/Realmzer/MySign-Repo.git
synced 2026-04-21 04:22:03 +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