Skip to content

Instantly share code, notes, and snippets.

@stefanbc
Last active September 7, 2022 06:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefanbc/2b607c77961d42532043da1ee48d84d1 to your computer and use it in GitHub Desktop.
Save stefanbc/2b607c77961d42532043da1ee48d84d1 to your computer and use it in GitHub Desktop.
Plex Cleanup
{
"timeZone": "Europe/Bucharest",
"dependencies": {
"enabledAdvancedServices": []
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/gmail.metadata"
],
"runtimeVersion": "V8"
}
/**
* Get the script properties
*/
const ENV = PropertiesService.getScriptProperties();
const BASE_URL = ENV.getProperty('BASE_URL'),
TOKEN = ENV.getProperty('TOKEN'),
WEBHOOK = ENV.getProperty('IFTTT_WEBHOOK'),
SECTION = 2;
/**
* Check for max execution time
*/
const GMAIL_USER = /(gmail|googlemail)/.test(Session.getActiveUser().getEmail());
const ONE_SECOND = 1000;
const ONE_MINUTE = ONE_SECOND * 60;
const MAX_EXECUTION_TIME = ONE_MINUTE * (GMAIL_USER ? 6 : 30);
const NOW = Date.now();
const isTimeLeft = () => {
return MAX_EXECUTION_TIME > Date.now() - NOW;
}
const thisFunctionTakesTimeToExecution = () => {
const threads = GmailApp.getInboxThreads(0, 100);
for (let t = 0; t < threads.length && isTimeLeft(); t += 1) {
cleanup()
}
}
/**
* Main cleanup method
*/
const cleanup = () => {
const response = UrlFetchApp.fetch(
`${BASE_URL}/library/sections/${SECTION}/allLeaves`,
{ method: "GET", headers: { "X-Plex-Token": TOKEN } }
),
jsonObject = xmlToJson(response.getContentText()),
videoContainer = jsonObject.MediaContainer.Video;
if (videoContainer) {
let watchedVideos = [];
if (Array.isArray(videoContainer)) {
watchedVideos = videoContainer.filter((video) => video.viewCount >= 1);
} else {
if (videoContainer.viewCount >= 1) watchedVideos.push(videoContainer);
}
if (watchedVideos.length > 0) {
let watchedTitles = "";
watchedVideos.forEach((video, index) => {
Logger.log(video.key);
UrlFetchApp.fetch(BASE_URL + video.key, {
method: "DELETE",
headers: { "X-Plex-Token": TOKEN },
});
watchedTitles += `${video.grandparentTitle} - ${video.title}`;
watchedTitles += "\r\n";
if (index === watchedVideos.length - 1) {
Logger.log(watchedTitles);
Logger.log("Notification sent!");
let notification =
`${watchedVideos.length} watched episodes were removed!` +
"\r\n" +
watchedTitles;
let options = {
method: "POST",
contentType: "application/json",
payload: JSON.stringify({ value1: notification }),
};
UrlFetchApp.fetch(WEBHOOK, options);
}
});
}
} else {
Logger.log("No videos to delete!");
}
}
const xmlToJson = (xml) => {
let doc = XmlService.parse(xml),
result = {},
root = doc.getRootElement();
result[root.getName()] = elementToJson(root);
return result;
}
const elementToJson = (element) => {
let result = {};
// Attributes.
element.getAttributes().forEach(attribute => {
result[attribute.getName()] = attribute.getValue();
});
// Child elements.
element.getChildren().forEach(child => {
let key = child.getName(),
value = elementToJson(child);
if (result[key]) {
if (!(result[key] instanceof Array)) {
result[key] = [result[key]];
}
result[key].push(value);
} else {
result[key] = value;
}
});
// Text content.
if (element.getText()) {
result['Text'] = element.getText();
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment