commit 568e577173459c6dff8a3e7667efed72d12a6128 Author: marc barbier Date: Wed Jan 13 22:49:31 2021 +0100 initial version diff --git a/downloader/CurseForgeModFile.java b/downloader/CurseForgeModFile.java new file mode 100644 index 0000000..dd364c4 --- /dev/null +++ b/downloader/CurseForgeModFile.java @@ -0,0 +1,30 @@ +package downloader; + +public class CurseForgeModFile extends ProjectInfo{ + + private int projectID; + private int fileID; + private boolean clientOnly; + + public CurseForgeModFile(ProjectInfo pj,int projectID,int fileID,boolean clientOnly) + { + this(pj.getSlug(),pj.getName(),pj.getDesc(),projectID,fileID,clientOnly); + } + + public CurseForgeModFile(String slug, String name, String desc,int projectID,int fileID,boolean clientOnly) { + super(slug, name, desc); + this.projectID=projectID; + this.fileID=fileID; + this.clientOnly=clientOnly; + } + + public int getFileID() { + return fileID; + } + public int getProjectID() { + return projectID; + } + public boolean isClientOnly() { + return clientOnly; + } +} diff --git a/downloader/DBConnector.java b/downloader/DBConnector.java new file mode 100644 index 0000000..1bb32d7 --- /dev/null +++ b/downloader/DBConnector.java @@ -0,0 +1,43 @@ +package downloader; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class DBConnector { + private Connection conn; + + /** + * Connect to a sample database + * + * @throws SQLException + */ + public void connect(String dbFile) throws SQLException { + conn = null; + try { + // db parameters + String url = "jdbc:sqlite:" + dbFile; + System.out.println(url); + // create a connection to the database + conn = DriverManager.getConnection(url); + + } catch (SQLException e) { + System.out.println(e.getMessage()); + throw e; + } + } + + public void close() throws SQLException { + conn.close(); + } + + public ResultSet executeRequest(String sql) { + try { + return conn.createStatement().executeQuery(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/downloader/Database.java b/downloader/Database.java new file mode 100644 index 0000000..9f1ff8d --- /dev/null +++ b/downloader/Database.java @@ -0,0 +1,184 @@ +package downloader; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +import org.apache.commons.compress.utils.IOUtils; + +import com.google.gson.Gson; + +import downloader.forgeSvc.ForgeSvcEntry; +import downloader.forgeSvc.ForgeSvcFile; + +public class Database { + + String version; + DBConnector connector; + Gson gson; + + public Database() { + + // Todo save ver + this.version = ""; + gson = new Gson(); + + } + + public void updateDatabase() { + try { + String dbVersion = HttpHelper.readStringFromUrl("http://files.mcdex.net/data/latest.v5"); + if (dbVersion.equals(version)) { + println("alredy up to date"); + return; + } + if (dbVersion.equals("error")) { + println("an error ocured"); + return; + } + + println("newer version found"); + if (!this.version.isEmpty()) { + println("current=" + this.version + " remote=" + dbVersion); + } else { + println("new=" + dbVersion); + } + + println("fetching=" + "http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); + File archive = HttpHelper.readFileFromUrl(null,"http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); + println("download finished"); + println("decompressing db"); + File decompressedDatabase; + try { + decompressedDatabase = decompressBz2(archive, "database.dat"); + } catch (IOException e) { + println("cannot extract database"); + return; + } + println("done"); + println("loading the database"); + connector = new DBConnector(); + try { + connector.connect(decompressedDatabase.getAbsolutePath()); + } catch (SQLException e) { + return; + } + println("database loaded"); + this.version = dbVersion; + + } catch (MalformedURLException e) { + println("database link is dead"); + System.exit(1); + } + } + + private void print(String message) { + System.out.print("db : " + message); + } + + private void println(String message) { + print(message + "\n"); + } + + private File decompressBz2(File inputFile, String outputFile) throws IOException { + BZip2CompressorInputStream input = new BZip2CompressorInputStream( + new BufferedInputStream(new FileInputStream(inputFile))); + File decompressedFile = new File(outputFile); + FileOutputStream output = new FileOutputStream(decompressedFile); + IOUtils.copy(input, output); + return decompressedFile; + } + + private int findProjectBySlug(String slug, int ptype) { + int modID = -1; + ResultSet rs = connector.executeRequest("select projectid from projects where type =" + ptype + " and slug =\"" + + slug.trim().toLowerCase() + "\""); + try { + if (rs.next()) { + modID = rs.getInt("projectid"); + System.out.println("modid:" + modID); + } else { + System.out.println("not found " + slug); + return -1; + } + } catch (SQLException e) { + e.printStackTrace(); + return -1; + } + return modID; + } + + private int findModBySlug(String slug) { + return findProjectBySlug(slug, 0); + } + + private ProjectInfo getProjectInfo(int projectId) { + System.out.println( + "select slug, name, description from projects where projectid = " + projectId + " and type = 0"); + ResultSet rs = connector.executeRequest( + "select slug, name, description from projects where projectid = " + projectId + " and type = 0"); + try { + if (rs.next()) { + return new ProjectInfo(rs.getString("slug"), rs.getString("name"), rs.getString("description")); + } + } catch (SQLException e) { + } + return null; + } + + public boolean fetchMod(String string) { + String name = string.split("/")[5]; + int modID = findModBySlug(name); + if (modID == -1) + return false; + ProjectInfo pj = getProjectInfo(modID); + if (pj == null) + return false; + CurseForgeModFile modfile = new CurseForgeModFile(pj, modID, -1, false); + ForgeSvcFile file = getLastestFile("1.12.2", modfile); + if (file != null) { + try { + print("downloading " + pj.getName()); + HttpHelper.readFileFromUrlToFolder(pj.getSlug(),file.getDownloadUrl(modID), "mods"); + println("download finished"); + return true; + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } else { + System.out.println("no file in server"); + } + return false; + } + + public ForgeSvcFile getLastestFile(String minecraftVer, CurseForgeModFile mod) { + String projectUrl = "https://addons-ecs.forgesvc.net/api/v2/addon/" + mod.getProjectID(); + String jsonProject; + try { + jsonProject = HttpHelper.readStringFromUrl(projectUrl); + if(jsonProject.equals("error"))return null; + } catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + + ForgeSvcEntry entry = gson.fromJson(jsonProject, ForgeSvcEntry.class); + + for (ForgeSvcFile f : entry.getFiles()) { + if (f.getGameVersion().equals(minecraftVer)) { + return f; + } + } + return null; + } + + + + +} diff --git a/downloader/Downloader.java b/downloader/Downloader.java new file mode 100644 index 0000000..522a025 --- /dev/null +++ b/downloader/Downloader.java @@ -0,0 +1,44 @@ +package downloader; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.URISyntaxException; + +public class Downloader { + public static void main(String[] args) throws FileNotFoundException, IOException, URISyntaxException { + System.out.println("hello"); + + Database db = new Database(); + db.updateDatabase(); + + File f = new File("modpack.txt"); + BufferedReader in = new BufferedReader(new FileReader(f)); + while (in.ready()) { + String line = in.readLine(); + if (!line.startsWith("//")) { + if (line.split("/").length >= 5 && ! line.startsWith("direct=")) { + if (!db.fetchMod(line)) { + System.err.println("error could not get " + line); + } + }else { + if(line.startsWith("direct@")) + { + char[] chars = new char[line.length()-line.indexOf("@")-"direct=".length()+1]; + line.getChars("direct=".length(), line.indexOf("@"), chars, 0); + String slug = new String(chars); + + String[] url = line.replace("direct=*@", "").split("/"); + System.out.println("downloading "+ url[url.length -1 ]); + HttpHelper.readFileFromUrlToFolder(slug,line.replace("direct@", ""),"mods"); + System.out.println("done"); + } + } + } + } + in.close(); + } + +} diff --git a/downloader/HttpHelper.java b/downloader/HttpHelper.java new file mode 100644 index 0000000..46c524c --- /dev/null +++ b/downloader/HttpHelper.java @@ -0,0 +1,162 @@ +package downloader; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.zip.ZipFile; + +public class HttpHelper { + + public static String[] fileList; + + public static String readStringFromUrl(String urlToFetch) throws MalformedURLException { + URL url = new URL(urlToFetch); + HttpURLConnection con; + try { + con = (HttpURLConnection) url.openConnection(); + } catch (IOException e1) { + e1.printStackTrace(); + return "error"; + } + + String str = ""; + + try (InputStream in = con.getInputStream()) { + // par tranche de 4mo + for (;;) { + byte[] buffer = new byte[4096]; + int nbBytesRead = in.read(buffer); + if (nbBytesRead < 0) + break; + + for (int i = 0; i < nbBytesRead; i++) { + str += (char) buffer[i]; + } + } + + } catch (IOException e) { + } + + return str; + } + + public static File readFileFromUrl(String slug, String urlToFetch) throws MalformedURLException { + String[] url = urlToFetch.split("/"); + if (url.length == 0) + throw new MalformedURLException(); + + return readFileFromUrl(slug, urlToFetch, url[url.length - 1]); + } + + public static File readFileFromUrl(String slug, String urlToFetch, String filename) throws MalformedURLException { + return readFileFromUrl(slug, urlToFetch, new File(filename)); + } + + static File readFileFromUrlToFolder(String slug, String urlToFetch, String folder) throws MalformedURLException { + try { + Files.createDirectories(Paths.get(folder)); + } catch (IOException e) { + System.out.println("could not create folder"); + return null; + } + + if (!folder.endsWith("/")) + folder += "/"; + + String[] url = urlToFetch.split("/"); + if (url.length == 0) + throw new MalformedURLException(); + String name = url[url.length - 1]; + + return readFileFromUrl(slug, urlToFetch, new File(folder + name)); + } + + private static File readFileFromUrl(String slug, String urlToFetch, File destination) throws MalformedURLException { + URL url = new URL(urlToFetch); + HttpURLConnection con; + try { + con = (HttpURLConnection) url.openConnection(); + } catch (IOException e1) { + e1.printStackTrace(); + return null; + } + + File downloadingFile = destination; + + if (slug != null) + checkAndDelete(downloadingFile, slug); + + if (downloadingFile.exists()) { + return downloadingFile; + } else { + try { + downloadingFile.createNewFile(); + } catch (IOException e) { + System.out.println("permission error could not write file"); + System.exit(1); + } + } + FileOutputStream downloadingWriter; + try { + downloadingWriter = new FileOutputStream(downloadingFile); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + return null; + // imposible vu qu'on l'a crée precedament + } + + try (InputStream in = con.getInputStream()) { + int totalRead = 0; + // on lit par tranche de 4mo + byte[] buffer = new byte[4096]; + + while (true) { + int bytesRead = in.read(buffer); + if (bytesRead < 0) + break; + totalRead += bytesRead; + downloadingWriter.write(buffer, 0, bytesRead); + System.out.println("\r" + totalRead); + } + downloadingWriter.close(); + return downloadingFile; + } catch (IOException e) { + } + return null; + + } + + // suprime les versions obselettes + private static void checkAndDelete(File fForgeSvcFile, String slug) { + if (fileList == null) { + fileList = new File("mods").list(); + } + + if (fForgeSvcFile.exists()) { + try { + //si sa balance une exception sa veut dire que le jar n'est pas lisible + new ZipFile(fForgeSvcFile).close(); + } catch (IOException e) { + fForgeSvcFile.delete(); + return; + } + + for (String s : fileList) { + if (s.contains(slug)) { + if (!fForgeSvcFile.getName().contains(s)) { + new File(s).delete(); + } + return; + } + } + + } + } +} diff --git a/downloader/ProjectInfo.java b/downloader/ProjectInfo.java new file mode 100644 index 0000000..da8553f --- /dev/null +++ b/downloader/ProjectInfo.java @@ -0,0 +1,24 @@ +package downloader; + +public class ProjectInfo { + private String slug, name, desc; + + public ProjectInfo(String slug, String name, String desc) { + super(); + this.slug = slug; + this.name = name; + this.desc = desc; + } + + public String getDesc() { + return desc; + } + public String getName() { + return name; + } + public String getSlug() { + return slug; + } + + +} diff --git a/downloader/forgeSvc/ForgeSvcEntry.java b/downloader/forgeSvc/ForgeSvcEntry.java new file mode 100644 index 0000000..8a8d63b --- /dev/null +++ b/downloader/forgeSvc/ForgeSvcEntry.java @@ -0,0 +1,9 @@ +package downloader.forgeSvc; + +public class ForgeSvcEntry { + private ForgeSvcFile[] gameVersionLatestFiles; + + public ForgeSvcFile[] getFiles() { + return gameVersionLatestFiles; + } +} diff --git a/downloader/forgeSvc/ForgeSvcFile.java b/downloader/forgeSvc/ForgeSvcFile.java new file mode 100644 index 0000000..8985a54 --- /dev/null +++ b/downloader/forgeSvc/ForgeSvcFile.java @@ -0,0 +1,37 @@ +package downloader.forgeSvc; + +import java.net.MalformedURLException; + +import downloader.HttpHelper; + +public class ForgeSvcFile { + private String gameVersion; + private int fileType; + private int projectFileId; + private String projectFileName; + + public String getGameVersion() { + return gameVersion; + } + + public int getFileType() { + return fileType; + } + public int getProjectFileId() { + return projectFileId; + } + + public String getProjectFileName() { + return projectFileName; + } + + public String getDownloadUrl(int modID) throws MalformedURLException { + System.out.println("https://addons-ecs.forgesvc.net/api/v2/addon/"+modID+"/file/"+getProjectFileId()); + return HttpHelper.readStringFromUrl("https://addons-ecs.forgesvc.net/api/v2/addon/"+modID+"/file/"+projectFileId+"/download-url"); + } + + public String getMD5(int modID) + { + return "https://addons-ecs.forgesvc.net/api/v2/addon/"+modID+"/file/"+getProjectFileId(); + } +}