From 76d77da29c5386cb9ea3b64c07fe43571cfcd246 Mon Sep 17 00:00:00 2001 From: Donald Shan Date: Sun, 23 Oct 2022 14:13:00 -0700 Subject: Fixed bug where files don't download due to missing thumbnail code will now check multiple formats for thumbnails. Resolution may be lost but its better than nothing --- FileUtility.java | 189 ++++++++++++++++++++++++++++++++++++++++ Main.java | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 FileUtility.java create mode 100644 Main.java diff --git a/FileUtility.java b/FileUtility.java new file mode 100644 index 0000000..3a1504a --- /dev/null +++ b/FileUtility.java @@ -0,0 +1,189 @@ +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FileUtility { + public void deleteFile(String fileName) { + File file = new File(fileName); + if (file.exists()) { + file.delete(); + } + } + + public void downloadImage(String url, String fileName,String[] formats) { + boolean successfulDownload = false; + int formatIndex = 0; + while(!successfulDownload) { + try { + FileOutputStream fos = new FileOutputStream(fileName); + URL urlObj = new URL(url+formats[formatIndex]); + InputStream is = urlObj.openStream(); + byte[] b = new byte[2048]; + int length; + while ((length = is.read(b)) != -1) { + fos.write(b, 0, length); + } + fos.close(); + is.close(); + successfulDownload = true; + } catch (Exception e) { + formatIndex++; + } + } + + } + + public void moveFile(String source, String destination) { + File sourceFile = new File(source); + File destinationFile = new File(destination); + sourceFile.renameTo(destinationFile); + System.out.println("Moved file to Completed Folder"); + } + public String removeNonAlphaNumeric(String str) { + return str.replaceAll("[^a-zA-Z0-9]", ""); + } + public static String showTextFileChooser() { + javax.swing.JFileChooser chooser = new javax.swing.JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Text File", "txt", "text"); + chooser.setFileFilter(filter); + chooser.setDialogTitle("Select a text file"); + chooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(null) == javax.swing.JFileChooser.APPROVE_OPTION) { + return chooser.getSelectedFile().getAbsolutePath(); + } else { + return null; + } + } + public static File findMP3File(String directory){ + File dir = new File(directory); + File[] files = dir.listFiles(); + for(File file : files){ + if(file.getName().endsWith(".mp3")){ + return file; + } + } + return null; + } + + public static String findJsonFile(String folderName) { + File folder = new File(folderName); + File[] listOfFiles = folder.listFiles(); + for (int i = 0; i < listOfFiles.length; i++) { + if (listOfFiles[i].isFile()) { + if (listOfFiles[i].getName().endsWith(".json")) { + return listOfFiles[i].getAbsolutePath(); + } + } + } + return null; + } + public static String[] parseJson(String json) { + String title = ""; + String uploader = ""; + String id = ""; + Pattern titlePattern = Pattern.compile("\"fulltitle\": \"(.*?)\","); + Matcher titleMatcher = titlePattern.matcher(json); + Pattern uploaderPattern = Pattern.compile("\"uploader\": \"(.*?)\","); + Matcher uploaderMatcher = uploaderPattern.matcher(json); + Pattern idPattern = Pattern.compile("\"id\": \"(.*?)\","); + Matcher idMatcher = idPattern.matcher(json); + titleMatcher.find(); + idMatcher.find(); + uploaderMatcher.find(); + title = titleMatcher.group(1); + uploader = uploaderMatcher.group(1); + id = idMatcher.group(1); + String[] info = {title,uploader,id}; + return info; + + } + public static String jsonToString(String fileName) { + String json = ""; + try { + BufferedReader br = new BufferedReader(new FileReader(fileName)); + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + line = br.readLine(); + } + json = sb.toString(); + br.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + public static void deleteAllFilesDir(String path) { + File folder = new File(path); + File[] files = folder.listFiles(); + if (files != null) { + for (File f : files) { + f.delete(); + } + } + } + + public static String showImageFileChooser() { + javax.swing.JFileChooser chooser = new javax.swing.JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("JPEG Image File", "jpg", "jpeg"); + chooser.setFileFilter(filter); + chooser.setDialogTitle("Select a image file"); + chooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(null) == javax.swing.JFileChooser.APPROVE_OPTION) { + return chooser.getSelectedFile().getAbsolutePath(); + } else { + return null; + } + } + public static ArrayList txtToArrayList(String fileName) { + ArrayList lines = new ArrayList(); + try { + FileReader fr = new FileReader(fileName); + BufferedReader br = new BufferedReader(fr); + String line; + while ((line = br.readLine()) != null) { + lines.add(line); + } + br.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return lines; + } + public String showDirectoryChooser(){ + try { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int result = fileChooser.showOpenDialog(null); + if (result == JFileChooser.APPROVE_OPTION) { + return fileChooser.getSelectedFile().getAbsolutePath(); + } + } + catch(Exception e){ + JOptionPane.showMessageDialog(null,"An unexpected error has occured"); + } + return ""; + } + //get the path of all mp3 files in a directory and return them as a file arraylist + public ArrayList getMp3Files(String path){ + ArrayList mp3Files = new ArrayList(); + File folder = new File(path); + File[] listOfFiles = folder.listFiles(); + + for(int i=0;i songs = fileUtil.txtToArrayList(textPath); + progress = 0; + String timeAppend = ""; + boolean partFlag = false; + for(int i = 0;i splitStamp = null; + try{ + splitStamp = new ArrayList<>(Arrays.asList(songs.get(i).split(","))); + } + catch(Exception e) { + + } + if(splitStamp.size()>=2){ + timeAppend = youtubeToMP3Part(splitStamp.get(0),splitStamp.get(1)); + partFlag = true; + } + else{ + youtubeToMP3Full(songs.get(i)); + } + + String info[] = fileUtil.parseJson(fileUtil.jsonToString(fileUtil.findJsonFile("downloaded"))); //title,uploader + String uploader = info[1]; + String title = info[0]; + AudioFile f = AudioFileIO.read(fileUtil.findMP3File("downloaded")); + Tag tag = f.getTag(); + tag.setField(FieldKey.ARTIST, uploader); + tag.setField(FieldKey.TITLE, title); + fileUtil.downloadImage("https://img.youtube.com/vi/"+info[2]+"/","img.jpg",formats); + Artwork cover = Artwork.createArtworkFromFile(new File("img.jpg")); + tag.addField(cover); + f.commit(); + fileUtil.deleteFile("img.jpg"); + if(partFlag){ + fileUtil.moveFile(fileUtil.findMP3File("downloaded").getAbsolutePath(), "completed/" + + fileUtil.removeNonAlphaNumeric(info[0]) + + " ["+info[2]+ "]"+timeAppend+".mp3"); + } + else{ + fileUtil.moveFile(fileUtil.findMP3File("downloaded").getAbsolutePath(), "completed/" + + fileUtil.removeNonAlphaNumeric(info[0]) + " ["+info[2]+ "].mp3"); + } + outputArea.setText(outputArea.getText()+"\n"+"Moved file to Completed Folder"); + progress = i; + System.out.println("Current Progress " + calculatePercentage(i+1,songs.size())); + progressBar.setValue(calculatePercentage(i+1,songs.size())); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private int calculatePercentage(int current, int total){//Calculate the percentage when give numerator and denominator + double currentD = current; + double totalD = total; + return (int)((currentD/totalD)*100); + } + + public static void showWarning(String message) { + JOptionPane.showMessageDialog(null, message, "JUST YOUR FRIENDLY NEIGHBORLY REMINDER", JOptionPane.WARNING_MESSAGE); + } + + public static void youtubeToMP3Full(String url) {//Download mp3 of youtube video using yt-dlp.exe. Ran from cmd + try { + ProcessBuilder builder = new ProcessBuilder( + "yt-dlp.exe", + "--extract-audio", + "--audio-format", "mp3", + "--audio-quality", "0", + "--output", "downloaded/%(title)s_%(id)s.mp3", + "--ffmpeg-location","ffmpeg.exe", + "--write-info-json", + url + ); + builder.redirectErrorStream(true); + Process p = builder.start(); + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + while (true) { + line = r.readLine(); + if (line == null) { + break; + } + outputArea.setText(outputArea.getText()+"\n"+line); + System.out.println(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + public static String youtubeToMP3Part(String url,String stamp) {//Download mp3 of youtube video using yt-dlp.exe. Ran from cmd + System.out.println(url + " " + stamp); + ArrayList times = new ArrayList<>(Arrays.asList(stamp.split("-"))); + ArrayList startTimeComponents = new ArrayList<>(Arrays.asList(times.get(0).split(":"))); + ArrayList endTimeComponents = new ArrayList<>(Arrays.asList(times.get(1).split(":"))); + int startSec = 0; + int endSec = 0; + if(startTimeComponents.size()==3){ + startSec = Integer.parseInt(startTimeComponents.get(0))*60*60+Integer.parseInt(startTimeComponents.get(1))*60+Integer.parseInt(startTimeComponents.get(2)); + } + else if(startTimeComponents.size()==2){ + startSec = Integer.parseInt(startTimeComponents.get(0))*60+Integer.parseInt(startTimeComponents.get(1)); + } + if(endTimeComponents.size()==3){ + endSec = Integer.parseInt(endTimeComponents.get(0))*60*60+Integer.parseInt(endTimeComponents.get(1))*60+Integer.parseInt(endTimeComponents.get(2)); + } + else if(endTimeComponents.size()==2){ + endSec = Integer.parseInt(endTimeComponents.get(0))*60+Integer.parseInt(endTimeComponents.get(1)); + } + try { + ProcessBuilder builder = new ProcessBuilder( + "yt-dlp.exe", + "--extract-audio", + "--audio-format", "mp3", + "--audio-quality", "0", + "--output", "downloaded/%(title)s_%(id)s.mp3", + "--ffmpeg-location","ffmpeg.exe", + "--write-info-json","--download-sections","\"*"+startSec+"-"+endSec+"\"", + "--force-keyframes-at-cuts", + url + ); + builder.redirectErrorStream(true); + Process p = builder.start(); + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + while (true) { + line = r.readLine(); + if (line == null) { + break; + } + outputArea.setText(outputArea.getText()+"\n"+line); + System.out.println(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + return startSec+"to"+endSec; + } + + + private void initializeComponents(){//Initiate GUI components + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + this.setLocationRelativeTo(null); + this.add(panel); + panel.setLayout(new BoxLayout(panel,BoxLayout.PAGE_AXIS)); + scrollPane = new JScrollPane(outputArea); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + outputArea.setEditable(true); + outputArea.setLineWrap(true); + DefaultCaret caret = (DefaultCaret)outputArea.getCaret(); + caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); + panel.add(Box.createRigidArea(new Dimension(0,5))); + panel.setBorder(BorderFactory.createEmptyBorder(25,10,20,10)); + startButton.setAlignmentX(CENTER_ALIGNMENT); + title.setAlignmentX(Component.CENTER_ALIGNMENT); + editButton.setAlignmentX(Component.CENTER_ALIGNMENT); + progressBar.setStringPainted(true); + title.setFont(new Font("Verdana", Font.PLAIN, 14)); + panel.add(title); + panel.add(Box.createVerticalStrut(10)); + panel.add(progressBar); + panel.add(Box.createVerticalStrut(10)); + panel.add(startButton); + panel.add(Box.createVerticalStrut(8)); + panel.add(scrollPane); + panel.add(Box.createVerticalStrut(5)); + panel.add(editButton); + this.setSize(550,450); + this.setTitle("YTMP3Tagger"); + } + + private void initializeActionsListeners(){//Add all actionlisteners for buttons + startButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if(readyState==false){ + outputArea.setText(outputArea.getText()+"\n"+"txt path has not been set. Launching chooserPane"); + System.out.println(".txt path has not been set. Launching chooserPane"); + textPath = fileUtil.showTextFileChooser(); + try { + if (!textPath.equals("")) { + showWarning("File has been set.\nMake sure you add a new line for each URL"); + readyState = true; + startButton.setText("Start Download"); + outputArea.setText(outputArea.getText() + "\n" + "Ready to begin downloading. Press the button"); + System.out.println("Ready to begin downloading. Press the button"); + } + } + catch(Exception ex){ + + } + } + else{ + Runnable runnable = () -> { + outputArea.setText(""); + startButton.setEnabled(false); + downloadAndTag(); + startButton.setEnabled(true); + + }; + Thread thread = new Thread(runnable); + thread.start(); + } + } + }); + editButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e){ + new TagEditorScreen().setVisible(true); + } + }); + } + + +} \ No newline at end of file -- cgit v1.2.3