6
\$\begingroup\$

The idea is to batch download a list of movies (torrents) off a torrent site and add them to your server.

I have a little bit of Java experience (sophomore in college), so I'm looking for things that I could improve on.

Main.java

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
public class Main {
 public static void main(String[] args) throws IOException, JSchException, InterruptedException, SftpException {
 //execution of program
 ConfigReader config = new ConfigReader();
 List < String > info = new ArrayList < String > ();
 info = config.grabUserInfo();
 Login login = new Login(info.get(0), info.get(1));
 Scanner File1 = new Scanner(new File("C:\\IPDownloader\\movies.txt"));
 String token = "";
 List < String > temps = new ArrayList < String > ();
 while (File1.hasNext()) {
 token = File1.nextLine();
 temps.add(token);
 }
 File1.close();
 RemoteConnect connect = new RemoteConnect(info.get(2), info.get(3), info.get(4));
 for (int i = 0; i <= temps.size() - 1; i++) {
 String movie = temps.get(i);
 Search search = new Search(login.grabLogin(), movie);
 TorrentStarter tor = new TorrentStarter(connect.getAuth(), search.searchMovie(), info.get(5), i);
 tor.downloadTorrent();
 if (i % 5 == 0 && i != 0) {
 System.out.println("Waiting 5 seconds");
 Thread.sleep(5000);
 }
 }
 System.exit(0);
 }
}

Login.java

import java.io.IOException;
import org.jsoup.Connection;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
public class Login {
 private String username;
 private String password;
 public Login(String username, String password) {
 this.username = username;
 this.password = password;
 }
 public Connection.Response grabLogin() throws IOException {
 Response loginRes = Jsoup.connect("https://iptorrents.com/")
 .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0") //robots.txt
 .method(Method.GET)
 .execute();
 Connection.Response res = Jsoup.connect("https://iptorrents.com/")
 .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
 .followRedirects(true)
 .data("username", username, "password", password)
 .method(Method.POST)
 .cookies(loginRes.cookies())
 .execute();
 //posting with cookies using connection.response library
 return res;
 }
}

ConfigReader.java

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ConfigReader {
 /*
 * checking for config file or making a new one. can follow format to skip this
 */
 public List < String > grabUserInfo() throws IOException {
 File configDir = new File("C:\\IPDownloader\\");
 File checkFile = new File("C:\\IPDownloader\\config.txt");
 boolean exists = configDir.exists();
 if (exists && checkFile.length() != 0) {
 System.out.println("Reading Config");
 String token = "";
 Scanner File1 = new Scanner(new File("C:\\IPDownloader\\config.txt"));
 List < String > temps = new ArrayList < String > ();
 while (File1.hasNext()) {
 token = File1.next();
 temps.add(token);
 }
 File1.close();
 return temps;
 } else {
 Scanner s = new Scanner(System. in );
 System.out.println("Config not found or it is empty");
 System.out.println("Please input your username");
 String username = s.nextLine();
 System.out.println("Please input your password");
 String password = s.nextLine();
 System.out.println("Please input the server hostname");
 String ipCon = s.nextLine();
 System.out.println("Please input server username");
 String userCon = s.nextLine();
 System.out.println("Please input the server password");
 String passCon = s.nextLine();
 System.out.println("Please input the watch directory (excluding home directory");
 String watchDir = s.nextLine();
 System.out.println("Your information has been stored at C:\\IPDownloader\\");
 new File("C:\\IPDownloader\\").mkdir();
 File configFile = new File("C:\\IPDownloader\\config.txt");
 BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
 writer.write(username);
 writer.newLine();
 writer.write(password);
 writer.newLine();
 writer.write(ipCon);
 writer.newLine();
 writer.write(userCon);
 writer.newLine();
 writer.write(passCon);
 writer.newLine();
 writer.write(watchDir);
 writer.close();
 String token = "";
 Scanner File1 = new Scanner(new File("C:\\IPDownloader\\config.txt"));
 List < String > temps = new ArrayList < String > ();
 while (File1.hasNext()) {
 token = File1.next();
 temps.add(token);
 }
 File1.close();
 return temps;
 }
 }
}

How could I possibly shorten this?

RemoteConnect.java

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import java.io.*;
public class RemoteConnect {
 private String ipCon;
 private String userCon;
 private String passCon;
 public RemoteConnect(String ipCon, String userCon, String passCon) {
 this.ipCon = ipCon;
 this.userCon = userCon;
 this.passCon = passCon;
 }
 public Object[] getAuth() throws JSchException, InterruptedException, SftpException {
 int port = 22;
 //using JSch for this
 JSch jsch = new JSch();
 Session session = jsch.getSession(userCon, ipCon, port);
 session.setPassword(passCon);
 session.setConfig("StrictHostKeyChecking", "no"); //needed
 session.connect(10 * 8000); //timeout
 return new Object[] {
 jsch, session
 }; //need to keep
 }
}

Search.java

import java.io.IOException;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
public class Search {
 private Connection.Response res;
 private String search = "";
 public Search(Connection.Response res, String movie) {
 this.res = res;
 this.search = movie;
 }
 public Object[] searchMovie() throws IOException {
 String downloadLink = "https://iptorrents.com";
 String partLink = "";
 //1080p sorted by top seeded movies
 Document doc = Jsoup.connect("https://iptorrents.com/t?1080p;q=" + search + ";o=seeders#torrents") //uses jsoup to keep login
 .cookies(res.cookies())
 .get();
 //had to scrape the top DL link. works with dynamic tags. using the icon as a reference
 for (Element e: doc.select("td.ac").select("a")) {
 if (e.select("i[class=fa fa-download fa-2x]").size() > 0) {
 partLink = e.attr("href");
 System.out.println(partLink);
 downloadLink += partLink;
 break;
 }
 }
 if (partLink.isEmpty()) {
 System.out.println("going here");
 doc = Jsoup.connect("https://iptorrents.com/t?720p;q=" + search + ";o=seeders#torrents") //uses jsoup to keep login
 .cookies(res.cookies())
 .get();
 //had to scrape the top DL link. works with dynamic tags. using the icon as a reference
 for (Element a: doc.select("td.ac").select("a")) {
 if (a.select("i[class=fa fa-download fa-2x]").size() > 0) {
 partLink = a.attr("href");
 downloadLink += partLink;
 break;
 }
 }
 }
 System.out.println("Added " + downloadLink);
 return new Object[] {
 downloadLink, res
 };
 }
}

TorrentStarter.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.Connection.Response;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
public class TorrentStarter {
 private String homeDirectory = "";
 private String torrent = "";
 private Session session = null;
 private JSch jsch = null;
 private int count = 0;
 private Connection.Response res = null;
 private ChannelSftp channelSftp = null;
 public TorrentStarter(Object[] objectArray, Object[] objectArray2, String watchDir, int count) {
 this.torrent = (String) objectArray2[0];
 this.jsch = (JSch) objectArray[0];
 this.session = (Session) objectArray[1];
 this.res = (Response) objectArray2[1];
 this.homeDirectory = watchDir;
 this.count = count;
 }
 public void downloadTorrent() throws JSchException, InterruptedException, IOException, SftpException {
 //iptorrents requires passkey via cookies for each dl
 res = Jsoup.connect(torrent)
 .cookies(res.cookies())
 .ignoreContentType(true)
 .execute();
 FileOutputStream out = (new FileOutputStream(new java.io.File("C:\\IPDownloader\\" + "torrent1.torrent")));
 out.write(res.bodyAsBytes());
 out.close();
 Channel channel = session.openChannel("sftp"); //we open the channel here
 channel.connect();
 channelSftp = (ChannelSftp) channel;
 channelSftp.cd(channelSftp.getHome());
 File f = new File("C:\\IPDownloader\\torrent1.torrent"); //named torrent1.torrent
 FileInputStream fInput = new FileInputStream(f);
 channelSftp.put(fInput, f.getName());
 fInput.close();
 channelSftp.rename((channelSftp.getHome() + "/torrent1.torrent"), (channelSftp.getHome() + homeDirectory + "torrent" + count +".torrent"));
 //.rename allows to delete from first directory and then move to new directory. works well
 f.delete();
 }
}
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Dec 15, 2015 at 6:12
\$\endgroup\$
1
  • \$\begingroup\$ This question is possibly uninteresting to reviewers. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. See also this meta question. \$\endgroup\$ Commented Dec 19, 2015 at 22:13

1 Answer 1

2
\$\begingroup\$

Some things I noticed while skimming over main:

Encapsulate your configuration

Instead of accessing your configuration through magic indices, you should introduce properly named getters for the properties.

 Login login = new Login(info.get(0), info.get(1));

becomes something much more manageable like:

Login login = new Login(config.getUsername(), config.getPassword());

This similarly applies for the construction of RemoteConnect.

Use of intermediary List and old File API

You're using an intermediary List (which uses memory) and the old File API (which is ... mediocre). Instead of

 Scanner File1 = new Scanner(new File("C:\\IPDownloader\\movies.txt"));
 String token = "";
 List < String > temps = new ArrayList < String > ();
 while (File1.hasNext()) {
 token = File1.nextLine();
 temps.add(token);
 }
 File1.close();

you should be able to process the whole "movies.txt" in a Stream:

try (Stream<String> movies = Files.lines(Paths.get(MOVIES_TXT))) {
 movies.flatMap(line -> Arrays.stream(line.split("[\\s]+")))
 .forEach(movie -> {
 //.. the body of your for-loop, best encapsuled in a method
 });
} catch (IOException e) {
 // handle properly :D
}

Nitpicks

  • The initial comment //execution of program is needlessness incarnate.
  • File1 should have a camelCased variable name and probably not one with a number in it :D
  • System.exit(0); is superfluous
answered Dec 15, 2015 at 8:04
\$\endgroup\$
1
  • \$\begingroup\$ Thank you so much for the advice! And yeah a lot of the Java I know is from old solutions and stuff in my textbooks / classes, which tends to use deprecated things. \$\endgroup\$ Commented Dec 15, 2015 at 10:22

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.