Compare commits
No commits in common. "master" and "1.1" have entirely different histories.
5 changed files with 140 additions and 81 deletions
30
.github/workflows/dotnet.yml
vendored
Normal file
30
.github/workflows/dotnet.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
name: .NET
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: 3.1.x
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build --no-restore
|
||||||
|
- name: Test
|
||||||
|
run: dotnet test --no-build --verbosity normal
|
||||||
|
- name: capture build artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Build
|
||||||
|
path: RepoFullDownloader-Core/bin/Debug/netcoreapp3.1/
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 KawaiiZenbo
|
Copyright (c) 2021 Chloe (kawaiizenbo)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RepoFullDownloader
|
# RepoFullDownloader-Core
|
||||||
Cross-Platform Cydia/Installer repo downloader
|
Cross-Platform Cydia/Installer repo downloader
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
@ -7,4 +7,4 @@ An internet connection.
|
||||||
|
|
||||||
## Command Line Options
|
## Command Line Options
|
||||||
`dotnet RepoFullDownloader-Core.dll <url>`
|
`dotnet RepoFullDownloader-Core.dll <url>`
|
||||||
Running with no URL will use the repo list from `repos.txt`
|
Running with no URL will use the repo list from `options.json`
|
||||||
|
|
62
RepoFullDownloader-Core/DataClasses.cs
Normal file
62
RepoFullDownloader-Core/DataClasses.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RepoFullDownloader
|
||||||
|
{
|
||||||
|
class Options
|
||||||
|
{
|
||||||
|
public bool originalFilenames { get; set; } = false;
|
||||||
|
public Repo[] repos { get; set; } = {
|
||||||
|
new Repo()
|
||||||
|
{
|
||||||
|
url = "http://repo.kawaiizenbo.me/",
|
||||||
|
type = "cydia"
|
||||||
|
},
|
||||||
|
new Repo()
|
||||||
|
{
|
||||||
|
url = "http://apptapp.saurik.com/",
|
||||||
|
type = "installer"
|
||||||
|
},
|
||||||
|
new Repo()
|
||||||
|
{
|
||||||
|
url = "http://apt.saurik.com/",
|
||||||
|
type = "dist",
|
||||||
|
distAttributes = new DistAttributes()
|
||||||
|
{
|
||||||
|
suites = "ios/",
|
||||||
|
components = "main",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public int delay { get; set; } = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Repo
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public DistAttributes distAttributes { get; set; } = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DistAttributes
|
||||||
|
{
|
||||||
|
public string suites { get; set; }
|
||||||
|
public string components { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class CydiaPackage
|
||||||
|
{
|
||||||
|
public CydiaPackage(string _link, string _name, string _version)
|
||||||
|
{
|
||||||
|
this.link = _link;
|
||||||
|
this.name = _name;
|
||||||
|
this.version = _version;
|
||||||
|
}
|
||||||
|
public string link { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,21 +3,21 @@ using ICSharpCode.SharpZipLib.GZip;
|
||||||
|
|
||||||
using PlistCS;
|
using PlistCS;
|
||||||
|
|
||||||
|
using RepoFullDownloader;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace RepoFullDownloader_Core
|
namespace RepoFullDownloader_Core
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
private static List<string> repos = new List<string>();
|
private static Options options = new Options();
|
||||||
private static bool originalFilenames;
|
|
||||||
private static int delayMS;
|
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -33,19 +33,17 @@ namespace RepoFullDownloader_Core
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory("./output/");
|
Directory.CreateDirectory("./output/");
|
||||||
}
|
}
|
||||||
// Load Options from 'options.ini'
|
// Load Options from 'options.json'
|
||||||
if (!File.Exists("./options.ini"))
|
if (!File.Exists("./options.json"))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Could not find options.ini");
|
Console.WriteLine("Could not find options.json");
|
||||||
Console.WriteLine("Generating example...");
|
Console.WriteLine("Generating example...");
|
||||||
// generate example options
|
// generate example options
|
||||||
File.WriteAllText("options.ini",
|
File.WriteAllText("./options.json", JsonSerializer.Serialize(new Options()));
|
||||||
"delayMS=1\n" +
|
return;
|
||||||
"originalFilenames=false");
|
|
||||||
}
|
}
|
||||||
string[] options = File.ReadAllLines("options.ini");
|
string optionsJson = File.ReadAllText("./options.json");
|
||||||
delayMS = int.Parse(options[0].Split('=')[1]);
|
options = JsonSerializer.Deserialize<Options>(optionsJson);
|
||||||
originalFilenames = bool.Parse(options[1].Split('=')[1]);
|
|
||||||
if (args.Length != 0)
|
if (args.Length != 0)
|
||||||
{
|
{
|
||||||
string url = args[0];
|
string url = args[0];
|
||||||
|
@ -69,47 +67,30 @@ namespace RepoFullDownloader_Core
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (File.Exists("repos.txt"))
|
|
||||||
|
foreach (Repo r in options.repos)
|
||||||
{
|
{
|
||||||
foreach (string r in File.ReadAllLines("repos.txt"))
|
if (r.type.ToLower() == "installer")
|
||||||
{
|
{
|
||||||
if (r.StartsWith('#')) continue;
|
DownloadInstallerRepo(r.url);
|
||||||
string[] repoWAttributes = r.Split(' ');
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (repoWAttributes[1])
|
|
||||||
{
|
|
||||||
case "installer":
|
|
||||||
DownloadInstallerRepo(repoWAttributes[0]);
|
|
||||||
break;
|
|
||||||
case "cydia":
|
|
||||||
DownloadRepo(repoWAttributes[0]);
|
|
||||||
break;
|
|
||||||
case "dist":
|
|
||||||
DownloadDistRepo(repoWAttributes[0], repoWAttributes[2], repoWAttributes[3]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Console.WriteLine($"Invalid repo type {repoWAttributes[1]} on {repoWAttributes[0]}");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else if (r.type.ToLower() == "cydia")
|
||||||
catch (Exception e)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Invalid formatting on {r}");
|
DownloadRepo(r.url);
|
||||||
Console.WriteLine(e);
|
|
||||||
}
|
}
|
||||||
|
else if (r.type.ToLower() == "dist")
|
||||||
|
{
|
||||||
|
if(r.distAttributes == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"No dist attributes were defined for {r.url} :(");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
DownloadDistRepo(r.url, r.distAttributes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Could not find repos.txt");
|
Console.WriteLine($"Invalid repo type {r.type} on {r.url}");
|
||||||
Console.WriteLine("Generating example...");
|
}
|
||||||
// generate example repo list
|
|
||||||
File.WriteAllText("repos.txt",
|
|
||||||
"http://repo.kawaiizenbo.me cydia\n" +
|
|
||||||
"http://apptapp.saurik.com installer\n" +
|
|
||||||
"http://apt.saurik.com dist ios/ main"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +130,7 @@ namespace RepoFullDownloader_Core
|
||||||
{
|
{
|
||||||
Console.WriteLine("Could not download " + link + "Packages.bz2: " + e.Message);
|
Console.WriteLine("Could not download " + link + "Packages.bz2: " + e.Message);
|
||||||
Console.WriteLine("Attempting to download " + link + "Packages.gz");
|
Console.WriteLine("Attempting to download " + link + "Packages.gz");
|
||||||
Stream packagesGz = webClient.GetStreamAsync(link + "Packages.gz").Result;
|
Stream packagesGz = webClient.GetStreamAsync(link + "Packages.bz2").Result;
|
||||||
FileStream packagesGzDecompressed = File.Create($"./output/{cleanLink}/Packages");
|
FileStream packagesGzDecompressed = File.Create($"./output/{cleanLink}/Packages");
|
||||||
GZip.Decompress(packagesGz, packagesGzDecompressed, true);
|
GZip.Decompress(packagesGz, packagesGzDecompressed, true);
|
||||||
}
|
}
|
||||||
|
@ -208,14 +189,14 @@ namespace RepoFullDownloader_Core
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] choppedUp = p.link.Split('/');
|
string[] choppedUp = p.link.Split('/');
|
||||||
string fileToDownload = originalFilenames ? $"./output/{cleanLink}/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
|
string fileToDownload = options.originalFilenames ? $"./output/{cleanLink}/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
|
||||||
if (File.Exists(fileToDownload))
|
if (File.Exists(fileToDownload))
|
||||||
{
|
{
|
||||||
fileToDownload += "_" + r.Next(0000, 9999);
|
fileToDownload += "_" + r.Next(0000, 9999);
|
||||||
}
|
}
|
||||||
using (WebClient wc = new WebClient())
|
using (WebClient wc = new WebClient())
|
||||||
{
|
{
|
||||||
wc.DownloadFile(new Uri(link + p.link), fileToDownload);
|
wc.DownloadFileAsync(new Uri(link + p.link), fileToDownload);
|
||||||
}
|
}
|
||||||
Console.WriteLine("Successfully downloaded " + link + p.link + " as " + fileToDownload);
|
Console.WriteLine("Successfully downloaded " + link + p.link + " as " + fileToDownload);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +206,7 @@ namespace RepoFullDownloader_Core
|
||||||
Console.WriteLine(e.Message);
|
Console.WriteLine(e.Message);
|
||||||
failed.Add(link + p.link);
|
failed.Add(link + p.link);
|
||||||
}
|
}
|
||||||
Thread.Sleep(delayMS);
|
Thread.Sleep(options.delay);
|
||||||
}
|
}
|
||||||
Console.WriteLine("Finished downloading " + link);
|
Console.WriteLine("Finished downloading " + link);
|
||||||
if(failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}/failed.txt", failed);
|
if(failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}/failed.txt", failed);
|
||||||
|
@ -255,8 +236,7 @@ namespace RepoFullDownloader_Core
|
||||||
Console.WriteLine("Could not download package list from " + link + ": " + e.Message);
|
Console.WriteLine("Could not download package list from " + link + ": " + e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Dictionary<string, object> plist = (Dictionary<string, object>)Plist.readPlistSource(Regex.Replace(File.ReadAllText($"./output/{cleanLink}/packages.plist"),
|
Dictionary<string, object> plist = (Dictionary<string, object>)Plist.readPlist($"./output/{cleanLink}/packages.plist");
|
||||||
"<!--([^|]+)-->", ""));
|
|
||||||
foreach (Dictionary<string, object> d in (List<object>)plist["packages"])
|
foreach (Dictionary<string, object> d in (List<object>)plist["packages"])
|
||||||
{
|
{
|
||||||
Random r = new Random();
|
Random r = new Random();
|
||||||
|
@ -301,7 +281,7 @@ namespace RepoFullDownloader_Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DownloadDistRepo(string link, string suites, string components)
|
static void DownloadDistRepo(string link, DistAttributes da)
|
||||||
{
|
{
|
||||||
// clean up link so no issues can ever arise
|
// clean up link so no issues can ever arise
|
||||||
if (!link.StartsWith("https://") && !link.StartsWith("http://"))
|
if (!link.StartsWith("https://") && !link.StartsWith("http://"))
|
||||||
|
@ -315,15 +295,15 @@ namespace RepoFullDownloader_Core
|
||||||
|
|
||||||
// make that good dist path
|
// make that good dist path
|
||||||
string distPath;
|
string distPath;
|
||||||
if(!suites.EndsWith("/"))
|
if(!da.suites.EndsWith("/"))
|
||||||
{
|
{
|
||||||
suites += "/";
|
da.suites += "/";
|
||||||
}
|
}
|
||||||
if (!components.EndsWith("/"))
|
if (!da.components.EndsWith("/"))
|
||||||
{
|
{
|
||||||
components += "/";
|
da.components += "/";
|
||||||
}
|
}
|
||||||
distPath = suites + components;
|
distPath = da.suites + da.components;
|
||||||
string poolpfLink = link + "dists/" + distPath + "binary-iphoneos-arm/";
|
string poolpfLink = link + "dists/" + distPath + "binary-iphoneos-arm/";
|
||||||
|
|
||||||
string cleanLink = link.TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/", "_").Replace(":", "_");
|
string cleanLink = link.TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/", "_").Replace(":", "_");
|
||||||
|
@ -407,7 +387,7 @@ namespace RepoFullDownloader_Core
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] choppedUp = p.link.Split('/');
|
string[] choppedUp = p.link.Split('/');
|
||||||
string fileToDownload = originalFilenames ? $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
|
string fileToDownload = options.originalFilenames ? $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
|
||||||
if (File.Exists(fileToDownload))
|
if (File.Exists(fileToDownload))
|
||||||
{
|
{
|
||||||
fileToDownload += "_" + r.Next(0000, 9999);
|
fileToDownload += "_" + r.Next(0000, 9999);
|
||||||
|
@ -424,23 +404,10 @@ namespace RepoFullDownloader_Core
|
||||||
Console.WriteLine(e.Message);
|
Console.WriteLine(e.Message);
|
||||||
failed.Add(link + p.link);
|
failed.Add(link + p.link);
|
||||||
}
|
}
|
||||||
Thread.Sleep(delayMS);
|
Thread.Sleep(options.delay);
|
||||||
}
|
}
|
||||||
Console.WriteLine("Finished downloading " + link);
|
Console.WriteLine("Finished downloading " + link);
|
||||||
if (failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/failed.txt", failed);
|
if (failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/failed.txt", failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CydiaPackage
|
|
||||||
{
|
|
||||||
public CydiaPackage(string _link, string _name, string _version)
|
|
||||||
{
|
|
||||||
this.link = _link;
|
|
||||||
this.name = _name;
|
|
||||||
this.version = _version;
|
|
||||||
}
|
|
||||||
public string link { get; set; }
|
|
||||||
public string name { get; set; }
|
|
||||||
public string version { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue