diff --git a/src/com/tivo/kmttg/JSON/JSONConverter.java b/src/com/tivo/kmttg/JSON/JSONConverter.java index ab9b2d06..da29600e 100644 --- a/src/com/tivo/kmttg/JSON/JSONConverter.java +++ b/src/com/tivo/kmttg/JSON/JSONConverter.java @@ -169,11 +169,35 @@ public static String makeShowTitle(JSONObject entry) { return title; } + /** + * Gets the start time as a local Date + * @param entry + * @return + */ public static String printableTimeFromJSON(JSONObject entry) { long start = getStartTime(entry); SimpleDateFormat sdf = new SimpleDateFormat("E MM/dd/yy hh:mm a"); return sdf.format(start); } + + /** + * Returns the selected key as a local timestamp or a empty string on error + * @param entry json object + * @param key json key + * @return + */ + public static String printableTimeFromJSON(JSONObject entry, String key) { + if (entry.has(key)) { + try { + String dateString = entry.getString(key); + long start = getLongDateFromString(dateString); + SimpleDateFormat sdf = new SimpleDateFormat("E MM/dd/yy hh:mm a"); + return sdf.format(start); + } catch (JSONException e) { + } + } + return ""; + } // Return friendly name of a partner based on id, such as Netflix, Hulu, etc. static public String getPartnerName(JSONObject entry) { diff --git a/src/com/tivo/kmttg/gui/remote/deleted.java b/src/com/tivo/kmttg/gui/remote/deleted.java index 3743e808..50bd44db 100755 --- a/src/com/tivo/kmttg/gui/remote/deleted.java +++ b/src/com/tivo/kmttg/gui/remote/deleted.java @@ -18,14 +18,19 @@ */ package com.tivo.kmttg.gui.remote; +import java.io.File; + import com.tivo.kmttg.gui.table.TableUtil; import com.tivo.kmttg.gui.table.deletedTable; import com.tivo.kmttg.main.config; import com.tivo.kmttg.main.jobData; import com.tivo.kmttg.main.jobMonitor; +import com.tivo.kmttg.rpc.Remote; +import com.tivo.kmttg.util.log; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; +import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; @@ -36,7 +41,9 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; import javafx.stage.Stage; +import javafx.stage.FileChooser.ExtensionFilter; public class deleted { public VBox panel = null; @@ -84,14 +91,7 @@ public void handle(ActionEvent e) { label.setText(""); String tivoName = tivo.getValue(); if (tivoName != null && tivoName.length() > 0) { - jobData job = new jobData(); - job.source = tivoName; - job.tivoName = tivoName; - job.type = "remote"; - job.name = "Remote"; - job.remote_deleted = true; - job.deleted = tab; - jobMonitor.submitNewJob(job); + deletedJob(tivoName); } } }); @@ -118,6 +118,40 @@ public void handle(ActionEvent e) { } }); + Button export = new Button("Export"); + export.setTooltip(tooltip.getToolTip("export_deleted")); + export.setOnAction(new EventHandler() { + public void handle(ActionEvent e) { + String tivoName = tivo.getValue(); + if (tivoName == null || tivoName.length() == 0) { + log.warn("select a tivo to export the deleted list" ); + return; + } + config.gui.remote_gui.Browser.getExtensionFilters().clear(); + config.gui.remote_gui.Browser.getExtensionFilters().addAll(new ExtensionFilter("CSV Files", "*.csv")); + config.gui.remote_gui.Browser.getExtensionFilters().add(new FileChooser.ExtensionFilter("ALL FILES", "*")); + config.gui.remote_gui.Browser.setTitle("Save to file"); + config.gui.remote_gui.Browser.setInitialDirectory(new File(config.programDir)); + config.gui.remote_gui.Browser.setInitialFileName(tivoName + "_deleted.csv"); + final File selectedFile = config.gui.remote_gui.Browser.showSaveDialog(frame); + if (selectedFile != null) { + Task task = new Task() { + @Override public Void call() { + log.warn("Exporting '" + tivoName + "' deleted list to csv file: " + selectedFile.getAbsolutePath()); + Remote r = config.initRemote(tivoName); + if (r.success) { + jobData job = deletedJob(tivoName); + r.DeletedShowsCSV(selectedFile, job); + r.disconnect(); + } + return null; + } + }; + new Thread(task).start(); + } + } + }); + label = new Label(); row1.getChildren().add(title); @@ -126,6 +160,7 @@ public void handle(ActionEvent e) { row1.getChildren().add(refresh); row1.getChildren().add(recover); row1.getChildren().add(permDelete); + row1.getChildren().add(export); row1.getChildren().add(label); tab = new deletedTable(); @@ -136,4 +171,16 @@ public void handle(ActionEvent e) { panel.getChildren().addAll(row1, tab.TABLE); } + + private jobData deletedJob(String tivoName) { + jobData job = new jobData(); + job.source = tivoName; + job.tivoName = tivoName; + job.type = "remote"; + job.name = "Remote"; + job.remote_deleted = true; + job.deleted = tab; + jobMonitor.submitNewJob(job); + return job; + } } diff --git a/src/com/tivo/kmttg/gui/remote/tooltip.java b/src/com/tivo/kmttg/gui/remote/tooltip.java index dae2cebd..2432f642 100755 --- a/src/com/tivo/kmttg/gui/remote/tooltip.java +++ b/src/com/tivo/kmttg/gui/remote/tooltip.java @@ -232,6 +232,10 @@ else if (component.equals("permDelete_deleted")){ text += "Permanently delete selected individual show(s) in table on specified TiVo.
"; text += "NOTE: Once deleted these shows are removed from Recently Deleted and can't be recovered."; } + else if (component.equals("export_deleted")){ + text = "Export
"; + text += "Export the list of deleted shows to a csv"; + } else if (component.equals("tivo_thumbs")) { text = "Select TiVo for which to display list of thumbed shows."; } diff --git a/src/com/tivo/kmttg/rpc/Remote.java b/src/com/tivo/kmttg/rpc/Remote.java index 7ababc2b..b2bf9aef 100755 --- a/src/com/tivo/kmttg/rpc/Remote.java +++ b/src/com/tivo/kmttg/rpc/Remote.java @@ -21,6 +21,7 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; +import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.URISyntaxException; @@ -46,6 +47,7 @@ import com.tivo.kmttg.main.config; import com.tivo.kmttg.main.jobData; import com.tivo.kmttg.main.jobMonitor; +import com.tivo.kmttg.util.file; import com.tivo.kmttg.util.log; import com.tivo.kmttg.util.string; @@ -1351,6 +1353,51 @@ public JSONArray DeletedShows(jobData job) { return JSONConverter.sortByLatestStartDate(allShows); } + public void DeletedShowsCSV(File csvFile, jobData job) { + try { + BufferedWriter ofp = new BufferedWriter(new FileWriter(csvFile)); + ofp.write("Title,Subtitle,Description,Season,Episode,Orginal Air Date,Movie Year,Channel,Start Time,Delete time,Delete Reason,Delete Policy,Content ID,Recording id,Size,Duration\r\n"); + JSONArray allShows = DeletedShows(job); + for (int i = 0; i < allShows.length(); i++) { + JSONObject show = allShows.getJSONObject(i); + String episodeNum = "" + JSONConverter.getEpisodeNum(show); + + ofp.write( + file.csvField(getStringIfHas(show, "title")) + + file.csvField(getStringIfHas(show, "subtitle")) + + file.csvField(getStringIfHas(show,"description")) + + file.csvField(getStringIfHas(show, "seasonNumber")) + + file.csvField(episodeNum) + + file.csvField(getStringIfHas(show, "originalAirdate")) + + file.csvField(getStringIfHas(show, "movieYear")) + + file.csvField(JSONConverter.makeChannelName(show)) + + file.csvField(JSONConverter.printableTimeFromJSON(show)) + + file.csvField(JSONConverter.printableTimeFromJSON(show, "deletionTime")) + + file.csvField(getStringIfHas(show, "deletionReason")) + + file.csvField(getStringIfHas(show, "contentId")) + + file.csvField(getStringIfHas(show, "recordingId")) + + file.csvField(getStringIfHas(show, "size")) + + file.csvField(getStringIfHas(show, "duration")) + + "\r\n" + ); + } + ofp.close(); + } catch (IOException | JSONException e) { + log.error("Error writing to csv: " + e.getMessage()); + } + } + + + protected String getStringIfHas(JSONObject json, String key) { + if (json.has(key)) { + try { + return json.get(key).toString(); + } catch (JSONException e) { + } + } + return ""; + } + // Get all season passes public JSONArray SeasonPasses(jobData job) { JSONObject result = null; diff --git a/src/com/tivo/kmttg/util/file.java b/src/com/tivo/kmttg/util/file.java index 797f5029..86dcfe5d 100644 --- a/src/com/tivo/kmttg/util/file.java +++ b/src/com/tivo/kmttg/util/file.java @@ -407,4 +407,9 @@ public static String vrdreviewFileSearch(String startFile) { } return null; } + + public static String csvField(String field) { + return "\"" + field + .replace("\"", "\"\"")+ "\","; + } }