diff --git a/.gitignore b/.gitignore
index 559b88f8..3b33b4c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@
_site
*.log
/data
-.idea/
+*.idea/
diff --git a/.meteor/packages b/.meteor/packages
index 3cc86c62..e003b20a 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -43,8 +43,5 @@ multiply:iron-router-progress
useraccounts:bootstrap
npm-container
-lokenx:couchpotatowrapper
-lokenx:sickragewrapper
-# lokenx:sonarrwrapper
meteorhacks:npm
davidyaha:collection2-migrations
diff --git a/.meteor/versions b/.meteor/versions
index dd1bd75a..e297e4ee 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -57,8 +57,6 @@ less@2.5.1
livedata@1.0.15
localstorage@1.0.5
logging@1.0.8
-lokenx:couchpotatowrapper@0.0.7
-lokenx:sickragewrapper@0.0.7
meteor@1.1.10
meteor-base@1.0.1
meteorhacks:async@1.0.0
diff --git a/client/helpers/authentication.js b/client/helpers/authentication.js
index ac7968a9..bb330714 100644
--- a/client/helpers/authentication.js
+++ b/client/helpers/authentication.js
@@ -1,3 +1,5 @@
+//TODO: Get rid of this file as it doesn't look to be needed anymore
+
// Plex user authentication
// Session.get("auth")
diff --git a/client/templates/admin/admin.html b/client/templates/admin/admin.html
index 9073214b..6f09fdf2 100644
--- a/client/templates/admin/admin.html
+++ b/client/templates/admin/admin.html
@@ -33,6 +33,7 @@
Admin
Users
{{/if}}
CouchPotato
+ Radarr
SickRage
Sonarr
Notifications
@@ -175,6 +176,43 @@ Admin
{{/autoForm}}
+
+ {{#autoForm collection="Settings" doc=settings id="updateRadarrSettingsForm" type="update" resetOnSuccess="false"}}
+ {{> afQuickField name='radarrENABLED'}}
+
Enabled Radarr for automated tv downloading.
+
+
+
Test your Radarr server. Remember to save your settings first!
+
+ {{> afQuickField name='radarrURL'}}
+
Enter the IP address or Hostname of your Radarr server. Do not include http:// or any slashes.
+
+ {{> afQuickField name='radarrPORT'}}
+
Enter the port used by Radarr. The default is 8989.
+
+ {{> afQuickField name='radarrAPI' size="40"}}
+
Enter your API from Radarr. It can be found in Sonarr Settings -> General.
+
+ {{> afQuickField name='radarrDIRECTORY' size="40"}}
+
Enter your sub-directory for Radarr if used. It should also include the slash (/) at the start.
+
+ {{> afQuickField name='radarrSSL'}}
+
Enabled if you use SSL on your Radarr server.
+
+ {{> afQuickField name='radarrQUALITYPROFILEID' type='select' options=radarrProfiles firstOption=false}}
+
+
+
+
Select a Radarr Quality Profile.
+
+ {{> afQuickField name='radarrROOTFOLDERPATH'}}
+
Enter the root folder where movies are saved. For example C:\Media\TV.
+
+
+ {{/autoForm}}
+
+
+
{{#autoForm collection="Settings" doc=settings id="updateSickRageSettingsForm" type="update" resetOnSuccess="false"}}
{{> afQuickField name='sickRageENABLED'}}
diff --git a/client/templates/admin/admin.js b/client/templates/admin/admin.js
index d9616b70..8a6944f7 100644
--- a/client/templates/admin/admin.js
+++ b/client/templates/admin/admin.js
@@ -69,6 +69,20 @@ AutoForm.hooks({
Bert.alert('Update failed, please try again', 'danger');
}
},
+ updateRadarrSettingsForm: {
+ onSuccess: function(formType, result) {
+ if (result) {
+ Bert.alert('Updated successfully', 'success');
+ Meteor.call("settingsUpdate");
+ }
+ this.event.preventDefault();
+ return false;
+ },
+ onError: function(formType, error) {
+ console.error(error);
+ Bert.alert('Update failed, please try again', 'danger');
+ }
+ },
updateNotificationsSettingsForm: {
onSuccess: function(formType, result) {
if (result) {
@@ -100,6 +114,14 @@ Template.admin.helpers({
};
});
},
+ radarrProfiles: function () {
+ return Template.instance().radarrProfiles.get().map(function (profile) {
+ return {
+ label: profile.name,
+ value: profile.id
+ };
+ });
+ },
version: function () {
return Template.instance().version.get();
},
@@ -132,6 +154,7 @@ Template.admin.onCreated(function(){
instance.version = new ReactiveVar("");
instance.update = new ReactiveVar(false);
instance.sonarrProfiles = new ReactiveVar([]);
+ instance.radarrProfiles = new ReactiveVar([]);
instance.latestVersion = new ReactiveVar("");
instance.latestNotes = new ReactiveVar("");
instance.previousVersion = new ReactiveVar("");
@@ -164,13 +187,13 @@ Template.admin.onCreated(function(){
instance.latestNotes.set(notesArray.filter(Boolean));
instance.previousVersion.set(result.data[1].name);
- var notesArray = result.data[1].body.split("- ");
+ notesArray = result.data[1].body.split("- ");
instance.previousNotes.set(notesArray.filter(Boolean));
});
});
Template.admin.events({
- 'click .list-group-item' : function (event, template) {
+ 'click .list-group-item' : function (event) {
var target = $(event.target);
//Update permissions collection
@@ -184,10 +207,12 @@ Template.admin.events({
$('.settings-pane').hide();
$('#Settings' + target.text()).show();
},
+
'submit #updateSettingsForm' : function (event) {
event.preventDefault();
return false;
},
+
'click #usersSettingsSubmit' : function (event) {
event.preventDefault();
@@ -200,6 +225,7 @@ Template.admin.events({
Bert.alert('Update failed, please try again', 'danger');
}
},
+
'click #couchPotatoTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -214,6 +240,7 @@ Template.admin.events({
}
})
},
+
'click #sickRageTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -228,6 +255,7 @@ Template.admin.events({
}
})
},
+
'click #sonarrTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -242,6 +270,22 @@ Template.admin.events({
}
})
},
+
+ 'click #radarrTest' : function (event) {
+ event.preventDefault();
+ var btn = $(event.target);
+ btn.html("Testing... ").removeClass().addClass("btn btn-info-outline");
+ Meteor.call("testRadarr", function (error, result) {
+ if (error || !result) {
+ btn.removeClass("btn-info-outline").addClass("btn-danger-outline");
+ btn.html("Error!");
+ } else {
+ btn.removeClass("btn-info-outline").addClass("btn-success-outline");
+ btn.html("Success!");
+ }
+ })
+ },
+
'click #iftttTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -257,6 +301,7 @@ Template.admin.events({
}
})
},
+
'click #pushbulletTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -272,6 +317,7 @@ Template.admin.events({
}
})
},
+
'click #pushoverTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -287,6 +333,7 @@ Template.admin.events({
}
})
},
+
'click #slackTest' : function (event) {
event.preventDefault();
var btn = $(event.target);
@@ -302,6 +349,7 @@ Template.admin.events({
}
})
},
+
'click #plexsubmit' : function (event) {
event.preventDefault();
$('#plexsubmit').html("Getting Token... ");
@@ -323,7 +371,7 @@ Template.admin.events({
event.preventDefault();
var btn = $(event.target);
btn.html("Get Profiles ").removeClass().addClass("btn btn-info-outline");
- Meteor.call("sonarrProfiles", function (error, result) {
+ Meteor.call('SonarrProfiles', function (error, result) {
if (result.length) {
template.sonarrProfiles.set(result);
Bert.alert('Retrieved Sonarr Profiles!', "success");
@@ -332,5 +380,20 @@ Template.admin.events({
}
btn.html("Get Profiles");
});
+ },
+
+ 'click #getRadarrProfiles': function (event, template) {
+ event.preventDefault();
+ var btn = $(event.target);
+ btn.html("Get Profiles ").removeClass().addClass("btn btn-info-outline");
+ Meteor.call("RadarrProfiles", function (error, result) {
+ if (result.length) {
+ template.radarrProfiles.set(result);
+ Bert.alert('Retrieved Radarr Profiles!', "success");
+ } else {
+ Bert.alert('Unable to retrieve Radarr Profiles!', "danger");
+ }
+ btn.html("Get Profiles");
+ });
}
});
diff --git a/lib/collections/collections.js b/lib/collections/collections.js
index 3dc4d04e..31642cfb 100755
--- a/lib/collections/collections.js
+++ b/lib/collections/collections.js
@@ -1,548 +1,609 @@
-// Define Mongodb Collections
-
-Movies = new Mongo.Collection("movies");
-TV = new Mongo.Collection("tv");
-Settings = new Mongo.Collection("settings");
-Permissions = new Mongo.Collection("permissions");
-
-// Movies Collection Schema
-
-var movies = new SimpleSchema (
- {
- title: {
- type: String,
- label: "Movie title",
- max: 200
- },
- id: {
- type: Number,
- label: "TheMovieDB ID"
- },
- imdb: {
- type: String,
- label: "IMDB ID",
- unique: true
- },
- released: {
- type: Date,
- label: "Release date"
- },
- user: {
- type: String,
- label: "Requesting user"
- },
- downloaded: {
- type: Boolean,
- label: "Status of downlaoded content"
- },
- createdAt: {
- type: Number,
- label: "Date of request",
- autoValue: function() {
- if ( this.isInsert ) {
- return Date.now();
- }
- }
- },
- //DEPRECIATED
- approved: {
- type: Boolean,
- label: "DEPRECIATED Approval status",
- optional: true
- },
- //Replacing 'approved'
- approval_status: {
- //0 = awaiting approval, 1 = approved, 3 = denied, -1 = must be updated from 'approved'
- type: Number,
- label: "Approval status",
- defaultValue: -1
- },
- denied_reason: {
- type: String,
- label: "Reason for denial",
- defaultValue: "This request has been denied.",
- optional: true
- },
- poster_path: {
- type: String,
- label: "Poster URL"
- },
- issues: {
- type: [String],
- label: "Reported issues",
- optional: true
- }
-});
-
-// TV Collection Schema
-
-var tv = new SimpleSchema (
- {
- title: {
- type: String,
- label: "TV Show title",
- max: 200
- },
- id: {
- type: Number,
- label: "TheMovieDB ID"
- },
- tvdb: {
- type: Number,
- label: "TVDB ID",
- min: 0
- },
- released: {
- type: Date,
- label: "Release date"
- },
- user: {
- type: String,
- label: "Requesting user"
- },
- "status.downloaded": {
- type: Number,
- label: "Number of downloaded episodes"
- },
- "status.total": {
- type: Number,
- label: "Number of total episodes"
- },
- createdAt: {
- type: Number,
- label: "Date of request",
- autoValue: function() {
- if ( this.isInsert ) {
- return Date.now();
- }
- }
- },
- //DEPRECIATED
- approved: {
- type: Boolean,
- label: "DEPRECIATED Approval status",
- optional: true
- },
- //Replacing 'approved'
- approval_status: {
- //0 = awaiting approval, 1 = approved, 3 = denied, -1 = must be updated from 'approved'
- type: Number,
- label: "Approval status",
- defaultValue: -1
- },
- denied_reason: {
- type: String,
- label: "Reason for denial",
- defaultValue: "This request has been denied.",
- optional: true
- },
- poster_path: {
- type: String,
- label: "Poster URL"
- },
- issues: {
- type: [String],
- label: "Reported issues",
- optional: true
- },
- episodes: {
- type: Boolean,
- label: "Whether to download all or new episodes only",
- optional: true
- },
- seasons: {
- type: Number,
- label: "Number of Seasons",
- defaultValue: -1,
- optional: false
- }
-});
-
-// Settings Collection Schema
-
-var settings = new SimpleSchema ({
- /**
- * GENERAL
- */
- searchOptionsMOVIES: {
- type: Boolean,
- label: "Search for Movies",
- defaultValue: true,
- optional: true
- },
- searchOptionsTV: {
- type: Boolean,
- label: "Search for TV Shows",
- defaultValue: true,
- optional: true
- },
- approval: { // Not used anymore, keeping for achival reference
- type: Boolean,
- label: "Require approval of requests",
- defaultValue: false,
- optional: true
- },
- tvApproval: {
- type: Boolean,
- label: "Require approval of TV requests",
- defaultValue: false,
- optional: true
- },
- movieApproval: {
- type: Boolean,
- label: "Require approval of Movie requests",
- defaultValue: false,
- optional: true
- },
- weeklyLimit: {
- type: Number,
- label: "Weekly user request limit",
- defaultValue: 5,
- optional: true
- },
- tvWeeklyLimit: {
- type: Number,
- label: "Weekly user request limit for TV",
- defaultValue: 5
- },
- movieWeeklyLimit: {
- type: Number,
- label: "Weekly user request limit for Movies",
- defaultValue: 5
- },
-
- /**
- * PLEX
- */
- plexAuthenticationTOKEN: {
- type: String,
- label: "Plex authorization token",
- defaultValue: "abcd1234",
- optional: true
- },
- plexAuthenticationENABLED: {
- type: Boolean,
- label: "Enable user authentication",
- defaultValue: false,
- optional: true
- },
- plexAuthenticationPASSWORDS: {
- type: Boolean,
- label: "Require users to login with their passwords",
- defaultValue: false,
- optional: true
- },
- plexUserPERMISSIONS: {
- type: Boolean,
- label: "Enable user permissions",
- defaultValue: false,
- optional: true
- },
-
- /**
- * COUCHPOTATO
- */
- couchPotatoURL: {
- type: String,
- label: "Couch Potato server IP or Hostname",
- defaultValue: "192.168.0.1",
- optional: true
- },
- couchPotatoPORT: {
- type: Number,
- label: "Couch Potato server port",
- defaultValue: 5050,
- optional: true
- },
- couchPotatoSSL: {
- type: Boolean,
- label: "Enable Couch Potato SSL",
- defaultValue: false,
- optional: true
- },
- couchPotatoAPI: {
- type: String,
- label: "Couch Potato API key",
- defaultValue: "abcd1234",
- optional: true
- },
- couchPotatoDIRECTORY: {
- type: String,
- label: "Couch Potato sub-directory",
- defaultValue: "",
- optional: true
- },
- couchPotatoENABLED: {
- type: Boolean,
- label: "Enable CouchPotato",
- defaultValue: false,
- optional: true
- },
-
- /**
- * SICKRAGE
- */
- sickRageURL: {
- type: String,
- label: "SickRage server IP or Hostname",
- defaultValue: "192.168.0.1",
- optional: true
- },
- sickRagePORT: {
- type: Number,
- label: "SickRage server port",
- defaultValue: 8081,
- optional: true
- },
- sickRageSSL: {
- type: Boolean,
- label: "Enable SickRage SSL",
- defaultValue: false,
- optional: true
- },
- sickRageAPI: {
- type: String,
- label: "SickRage API key",
- defaultValue: "abcd1234",
- optional: true
- },
- sickRageDIRECTORY: {
- type: String,
- label: "SickRage sub-directory",
- defaultValue: "",
- optional: true
- },
- sickRageENABLED: {
- type: Boolean,
- label: "Enable SickRage",
- defaultValue: false,
- optional: true
- },
-
- /**
- * SONARR
- */
- sonarrURL: {
- type: String,
- label: "Sonarr server IP or Hostname",
- defaultValue: "192.168.0.1",
- optional: true
- },
- sonarrPORT: {
- type: Number,
- label: "Sonarr server port",
- defaultValue: 8989,
- optional: true
- },
- sonarrSSL: {
- type: Boolean,
- label: "Enable Sonarr SSL",
- defaultValue: false,
- optional: true
- },
- sonarrAPI: {
- type: String,
- label: "Sonarr API key",
- defaultValue: "abcd1234",
- optional: true
- },
- sonarrDIRECTORY: {
- type: String,
- label: "Sonarr sub-directory",
- defaultValue: "",
- optional: true
- },
- sonarrQUALITYPROFILEID: {
- type: Number,
- label: "Download quality profile",
- defaultValue: 1,
- optional: true
- },
- sonarrROOTFOLDERPATH: {
- type: String,
- label: "Root save directory for TV shows",
- defaultValue: "/path/to/root/tv/folder",
- optional: true
- },
- sonarrSEASONFOLDERS: {
- type: Boolean,
- label: "Enable season folders",
- defaultValue: true,
- optional: true
- },
- sonarrENABLED: {
- type: Boolean,
- label: "Enable Sonarr",
- defaultValue: false,
- optional: true
- },
- customNotificationTEXT: {
- type: String,
- label: "Custom Notification Message",
- defaultValue: "
requested by ",
- optional: true
- },
- customNotificationTITLE: {
- type: String,
- label: "Custom Notification Title",
- defaultValue: "Plex Requests ",
- optional: true
- },
- notificationErrorTEXT: {
- type: String,
- defaultValue: " Issues: ()"
- },
- notificationErrorTitle: {
- type: String,
- defaultValue: "Plex Requests Issue"
- },
-
- /**
- * IFTTT
- */
-
- iftttENABLED: {
- type: Boolean,
- label: "Enable IFTTT Maker",
- defaultValue: false,
- optional: true
- },
- iftttMAKERAPI: {
- type: String,
- label: "IFTTT API key",
- defaultValue: "abc123",
- optional: true
- },
- iftttMAKERCHANNEL: {
- type: String,
- label: "IFTTT Channel Name",
- defaultValue: "plex_requests",
- optional: true
- },
- iftttMAKERVALUE1: {
- type: String,
- label: "IFTTT Value 1",
- optional: true
- },
- iftttMAKERVALUE2: {
- type: String,
- label: "IFTTT Value 2",
- optional: true
- },
- iftttMAKERVALUE3: {
- type: String,
- label: "IFTTT Value 3",
- optional: true
- },
- /**
- * PUSHBULLET
- */
- pushbulletAPI: {
- type: String,
- label: "Pushbullet API key",
- defaultValue: "abcd1234",
- optional: true
- },
- pushbulletChannel: {
- type: String,
- label: "Pushbullet Channel Tag",
- defaultValue: "",
- optional: true
- },
- pushbulletENABLED: {
- type: Boolean,
- label: "Enable Pushbullet notifications",
- defaultValue: false,
- optional: true
- },
-
- /**
- * PUSHOVER
- */
- pushoverAPI: {
- type: String,
- label: "Pushover API key",
- defaultValue: "abcd1234",
- optional: true
- },
- pushoverUSER: {
- type: String,
- label: "Pushover user key",
- defaultValue: "abcd1234",
- optional: true
- },
- pushoverENABLED: {
- type: Boolean,
- label: "Enable Pushover notifications",
- defaultValue: false,
- optional: true
- },
-
- /**
- * SLACK
- */
- slackAPI: {
- type: String,
- label: "Slack webhook url",
- defaultValue: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
- optional: true
- },
- slackUsername: {
- type: String,
- label: "Slack Username",
- defaultValue: "",
- optional: true
- },
- slackChannel: {
- type: String,
- label: "Slack Channel",
- defaultValue: "",
- optional: true
- },
- slackENABLED: {
- type: Boolean,
- label: "Enable Slack notifications",
- defaultValue: false,
- optional: true
- },
- updateDB: {
- type: Boolean,
- label: "Has UpdateDB Run",
- defaultValue: false,
- optional: true
- }
-});
-
-// Permissions Collection Schema
-
-var permissions = new SimpleSchema ({
- permUSER: {
- type: String,
- label: "Username"
- },
- permAPPROVAL: {
- type: Boolean,
- label: "No Approval",
- defaultValue: false,
- optional: true
- },
- permLIMIT: {
- type: Boolean,
- label: "No Limit",
- defaultValue: false,
- optional: true
- },
- permBANNED: {
- type: Boolean,
- label: "Banned",
- defaultValue: false,
- optional: true
- }
-});
-
-// Set Collection Schemas
-
-TV.attachSchema(tv);
-Movies.attachSchema(movies);
-Settings.attachSchema(settings);
+// Define Mongodb Collections
+
+Movies = new Mongo.Collection("movies");
+TV = new Mongo.Collection("tv");
+Settings = new Mongo.Collection("settings");
+Permissions = new Mongo.Collection("permissions");
+
+// Movies Collection Schema
+
+var movies = new SimpleSchema (
+ {
+ title: {
+ type: String,
+ label: "Movie title",
+ max: 200
+ },
+ id: {
+ type: Number,
+ label: "TheMovieDB ID"
+ },
+ imdb: {
+ type: String,
+ label: "IMDB ID",
+ unique: true
+ },
+ released: {
+ type: Date,
+ label: "Release date"
+ },
+ user: {
+ type: String,
+ label: "Requesting user"
+ },
+ downloaded: {
+ type: Boolean,
+ label: "Status of downloaded content"
+ },
+ createdAt: {
+ type: Number,
+ label: "Date of request",
+ autoValue: function() {
+ if ( this.isInsert ) {
+ return Date.now();
+ }
+ }
+ },
+ //DEPRECIATED
+ // TODO: Check that the conversion script replaces this and if so remove this entry
+ approved: {
+ type: Boolean,
+ label: "DEPRECIATED Approval status",
+ optional: true
+ },
+ //Replacing 'approved'
+ approval_status: {
+ //0 = awaiting approval, 1 = approved, 3 = denied, -1 = must be updated from 'approved'
+ type: Number,
+ label: "Approval status",
+ defaultValue: -1
+ },
+ /*
+ How come we have a default value set here? The value is optional therefore shouldn't be set if not done so explicitly...
+ ** UPDATE - Thinking this is set with a default value to ensure the field is present when the document gets inserted initially
+ ** so that it can just be updated. Setting the defaultValue to an empty string instead of a denial reason to prevent confusion
+ #td-done: Test removing the default value and ensure nothing breaks
+ */
+ denied_reason: {
+ type: String,
+ label: "Reason for denial",
+ defaultValue: "",
+ optional: true
+ },
+ poster_path: {
+ type: String,
+ label: "Poster URL"
+ },
+ issues: {
+ type: [String],
+ label: "Reported issues",
+ optional: true
+ }
+});
+
+// TV Collection Schema
+
+var tv = new SimpleSchema (
+ {
+ title: {
+ type: String,
+ label: "TV Show title",
+ max: 200
+ },
+ id: {
+ type: Number,
+ label: "TheMovieDB ID"
+ },
+ tvdb: {
+ type: Number,
+ label: "TVDB ID",
+ min: 0
+ },
+ released: {
+ type: Date,
+ label: "Release date"
+ },
+ user: {
+ type: String,
+ label: "Requesting user"
+ },
+ "status.downloaded": {
+ type: Number,
+ label: "Number of downloaded episodes"
+ },
+ "status.total": {
+ type: Number,
+ label: "Number of total episodes"
+ },
+ createdAt: {
+ type: Number,
+ label: "Date of request",
+ autoValue: function() {
+ if ( this.isInsert ) {
+ return Date.now();
+ }
+ }
+ },
+ //DEPRECIATED
+ approved: {
+ type: Boolean,
+ label: "DEPRECIATED Approval status",
+ optional: true
+ },
+ //Replacing 'approved'
+ approval_status: {
+ //0 = awaiting approval, 1 = approved, 3 = denied, -1 = must be updated from 'approved'
+ type: Number,
+ label: "Approval status",
+ defaultValue: -1
+ },
+ denied_reason: {
+ type: String,
+ label: "Reason for denial",
+ defaultValue: "",
+ optional: true
+ },
+ poster_path: {
+ type: String,
+ label: "Poster URL"
+ },
+ issues: {
+ type: [String],
+ label: "Reported issues",
+ optional: true
+ },
+ episodes: {
+ type: Boolean,
+ label: "Whether to download all or new episodes only",
+ optional: true
+ },
+ seasons: {
+ type: Number,
+ label: "Number of Seasons",
+ defaultValue: -1,
+ optional: false
+ }
+});
+
+// Settings Collection Schema
+
+var settings = new SimpleSchema ({
+ /**
+ * GENERAL
+ */
+ searchOptionsMOVIES: {
+ type: Boolean,
+ label: "Search for Movies",
+ defaultValue: true,
+ optional: true
+ },
+ searchOptionsTV: {
+ type: Boolean,
+ label: "Search for TV Shows",
+ defaultValue: true,
+ optional: true
+ },
+ approval: { // Not used anymore, keeping for achival reference
+ type: Boolean,
+ label: "Require approval of requests",
+ defaultValue: false,
+ optional: true
+ },
+ tvApproval: {
+ type: Boolean,
+ label: "Require approval of TV requests",
+ defaultValue: false,
+ optional: true
+ },
+ movieApproval: {
+ type: Boolean,
+ label: "Require approval of Movie requests",
+ defaultValue: false,
+ optional: true
+ },
+ weeklyLimit: {
+ type: Number,
+ label: "Weekly user request limit",
+ defaultValue: 5,
+ optional: true
+ },
+ tvWeeklyLimit: {
+ type: Number,
+ label: "Weekly user request limit for TV",
+ defaultValue: 5
+ },
+ movieWeeklyLimit: {
+ type: Number,
+ label: "Weekly user request limit for Movies",
+ defaultValue: 5
+ },
+
+ /**
+ * PLEX
+ */
+ plexAuthenticationTOKEN: {
+ type: String,
+ label: "Plex authorization token",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ plexAuthenticationENABLED: {
+ type: Boolean,
+ label: "Enable user authentication",
+ defaultValue: false,
+ optional: true
+ },
+ plexAuthenticationPASSWORDS: {
+ type: Boolean,
+ label: "Require users to login with their passwords",
+ defaultValue: false,
+ optional: true
+ },
+ plexUserPERMISSIONS: {
+ type: Boolean,
+ label: "Enable user permissions",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * COUCHPOTATO
+ */
+ couchPotatoURL: {
+ type: String,
+ label: "Couch Potato server IP or Hostname",
+ defaultValue: "192.168.0.1",
+ optional: true
+ },
+ couchPotatoPORT: {
+ type: Number,
+ label: "Couch Potato server port",
+ defaultValue: 5050,
+ optional: true
+ },
+ couchPotatoSSL: {
+ type: Boolean,
+ label: "Enable Couch Potato SSL",
+ defaultValue: false,
+ optional: true
+ },
+ couchPotatoAPI: {
+ type: String,
+ label: "Couch Potato API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ couchPotatoDIRECTORY: {
+ type: String,
+ label: "Couch Potato sub-directory",
+ defaultValue: "",
+ optional: true
+ },
+ couchPotatoENABLED: {
+ type: Boolean,
+ label: "Enable CouchPotato",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * SICKRAGE
+ */
+ sickRageURL: {
+ type: String,
+ label: "SickRage server IP or Hostname",
+ defaultValue: "192.168.0.1",
+ optional: true
+ },
+ sickRagePORT: {
+ type: Number,
+ label: "SickRage server port",
+ defaultValue: 8081,
+ optional: true
+ },
+ sickRageSSL: {
+ type: Boolean,
+ label: "Enable SickRage SSL",
+ defaultValue: false,
+ optional: true
+ },
+ sickRageAPI: {
+ type: String,
+ label: "SickRage API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ sickRageDIRECTORY: {
+ type: String,
+ label: "SickRage sub-directory",
+ defaultValue: "",
+ optional: true
+ },
+ sickRageENABLED: {
+ type: Boolean,
+ label: "Enable SickRage",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * SONARR
+ */
+ sonarrURL: {
+ type: String,
+ label: "Sonarr server IP or Hostname",
+ defaultValue: "192.168.0.1",
+ optional: true
+ },
+ sonarrPORT: {
+ type: Number,
+ label: "Sonarr server port",
+ defaultValue: 8989,
+ optional: true
+ },
+ sonarrSSL: {
+ type: Boolean,
+ label: "Enable Sonarr SSL",
+ defaultValue: false,
+ optional: true
+ },
+ sonarrAPI: {
+ type: String,
+ label: "Sonarr API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ sonarrDIRECTORY: {
+ type: String,
+ label: "Sonarr sub-directory",
+ defaultValue: "",
+ optional: true
+ },
+ sonarrQUALITYPROFILEID: {
+ type: Number,
+ label: "Download quality profile",
+ defaultValue: 1,
+ optional: true
+ },
+ sonarrROOTFOLDERPATH: {
+ type: String,
+ label: "Root save directory for TV shows",
+ defaultValue: "/path/to/root/tv/folder",
+ optional: true
+ },
+ sonarrSEASONFOLDERS: {
+ type: Boolean,
+ label: "Enable season folders",
+ defaultValue: true,
+ optional: true
+ },
+ sonarrENABLED: {
+ type: Boolean,
+ label: "Enable Sonarr",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * Radarr
+ */
+ radarrURL: {
+ type: String,
+ label: "Radarr server IP or Hostname",
+ defaultValue: "192.168.0.1",
+ optional: true
+ },
+ radarrPORT: {
+ type: Number,
+ label: "Radarr server port",
+ defaultValue: 8989,
+ optional: true
+ },
+ radarrSSL: {
+ type: Boolean,
+ label: "Enable Radarr SSL",
+ defaultValue: false,
+ optional: true
+ },
+ radarrAPI: {
+ type: String,
+ label: "Radarr API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ radarrDIRECTORY: {
+ type: String,
+ label: "Radarr sub-directory",
+ defaultValue: "",
+ optional: true
+ },
+ radarrQUALITYPROFILEID: {
+ type: Number,
+ label: "Download quality profile",
+ defaultValue: 1,
+ optional: true
+ },
+ radarrROOTFOLDERPATH: {
+ type: String,
+ label: "Root save directory for movies",
+ defaultValue: "/path/to/root/movie/folder",
+ optional: true
+ },
+ radarrENABLED: {
+ type: Boolean,
+ label: "Enable Radarr",
+ defaultValue: false,
+ optional: true
+ },
+
+ // Notifications Settings
+ customNotificationTEXT: {
+ type: String,
+ label: "Custom Notification Message",
+ defaultValue: " requested by ",
+ optional: true
+ },
+ customNotificationTITLE: {
+ type: String,
+ label: "Custom Notification Title",
+ defaultValue: "Plex Requests ",
+ optional: true
+ },
+ notificationErrorTEXT: {
+ type: String,
+ defaultValue: " Issues: ()"
+ },
+ notificationErrorTitle: {
+ type: String,
+ defaultValue: "Plex Requests Issue"
+ },
+
+ /**
+ * IFTTT
+ */
+
+ iftttENABLED: {
+ type: Boolean,
+ label: "Enable IFTTT Maker",
+ defaultValue: false,
+ optional: true
+ },
+ iftttMAKERAPI: {
+ type: String,
+ label: "IFTTT API key",
+ defaultValue: "abc123",
+ optional: true
+ },
+ iftttMAKERCHANNEL: {
+ type: String,
+ label: "IFTTT Channel Name",
+ defaultValue: "plex_requests",
+ optional: true
+ },
+ iftttMAKERVALUE1: {
+ type: String,
+ label: "IFTTT Value 1",
+ optional: true
+ },
+ iftttMAKERVALUE2: {
+ type: String,
+ label: "IFTTT Value 2",
+ optional: true
+ },
+ iftttMAKERVALUE3: {
+ type: String,
+ label: "IFTTT Value 3",
+ optional: true
+ },
+ /**
+ * PUSHBULLET
+ */
+ pushbulletAPI: {
+ type: String,
+ label: "Pushbullet API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ pushbulletChannel: {
+ type: String,
+ label: "Pushbullet Channel Tag",
+ defaultValue: "",
+ optional: true
+ },
+ pushbulletENABLED: {
+ type: Boolean,
+ label: "Enable Pushbullet notifications",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * PUSHOVER
+ */
+ pushoverAPI: {
+ type: String,
+ label: "Pushover API key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ pushoverUSER: {
+ type: String,
+ label: "Pushover user key",
+ defaultValue: "abcd1234",
+ optional: true
+ },
+ pushoverENABLED: {
+ type: Boolean,
+ label: "Enable Pushover notifications",
+ defaultValue: false,
+ optional: true
+ },
+
+ /**
+ * SLACK
+ */
+ slackAPI: {
+ type: String,
+ label: "Slack webhook url",
+ defaultValue: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
+ optional: true
+ },
+ slackUsername: {
+ type: String,
+ label: "Slack Username",
+ defaultValue: "",
+ optional: true
+ },
+ slackChannel: {
+ type: String,
+ label: "Slack Channel",
+ defaultValue: "",
+ optional: true
+ },
+ slackENABLED: {
+ type: Boolean,
+ label: "Enable Slack notifications",
+ defaultValue: false,
+ optional: true
+ },
+ updateDB: {
+ type: Boolean,
+ label: "Has UpdateDB Run",
+ defaultValue: false,
+ optional: true
+ }
+});
+
+// Permissions Collection Schema
+
+var permissions = new SimpleSchema ({
+ permUSER: {
+ type: String,
+ label: "Username"
+ },
+ permAPPROVAL: {
+ type: Boolean,
+ label: "No Approval",
+ defaultValue: false,
+ optional: true
+ },
+ permLIMIT: {
+ type: Boolean,
+ label: "No Limit",
+ defaultValue: false,
+ optional: true
+ },
+ permBANNED: {
+ type: Boolean,
+ label: "Banned",
+ defaultValue: false,
+ optional: true
+ }
+});
+
+// Set Collection Schemas
+
+TV.attachSchema(tv);
+Movies.attachSchema(movies);
+Settings.attachSchema(settings);
Permissions.attachSchema(permissions);
\ No newline at end of file
diff --git a/lib/exports/couchpotatoExports.js b/lib/exports/couchpotatoExports.js
new file mode 100644
index 00000000..6de60dbe
--- /dev/null
+++ b/lib/exports/couchpotatoExports.js
@@ -0,0 +1,24 @@
+function Server() {
+ this.url = "http://192.168.0.1";
+ this.port = 5050;
+ this.api = "abcdef012345";
+ this.directory = "";
+}
+
+CouchPotato = new Server();
+
+CouchPotato.appAvailable = function() {
+ return Meteor.call("appAvailable", {});
+};
+
+CouchPotato.mediaGet = function(media) {
+ return Meteor.call("mediaGet", media, {});
+};
+
+CouchPotato.movieAdd = function(media) {
+ return Meteor.call("movieAdd", media, {});
+};
+
+CouchPotato.movieDelete = function(media) {
+ return Meteor.call("movieDelete", media, {});
+};
diff --git a/lib/exports/radarrExports.js b/lib/exports/radarrExports.js
new file mode 100644
index 00000000..d69c65af
--- /dev/null
+++ b/lib/exports/radarrExports.js
@@ -0,0 +1,32 @@
+function Server() {
+ this.url = "http://192.168.0.1";
+ this.port = 8989;
+ this.api = "abcdef012345";
+ this.directory = "";
+}
+
+Radarr = new Server();
+
+Radarr.radarrSystemStatus = function() {
+ return Meteor.call("radarrSystemStatus", {});
+};
+
+Radarr.radarrProfilesGet = function() {
+ return Meteor.call("radarrProfilesGet", {});
+};
+
+Radarr.radarrMovieStats = function(id) {
+ return Meteor.call("radarrMovieStats", id, {});
+};
+
+Radarr.radarrMovieGet = function(id) {
+ return Meteor.call("radarrMovieGet", id, {});
+};
+
+// Radarr.seriesDelete = function(tmdbId) {
+// return Meteor.call("radarrMovieDelete", tmdbId, {});
+// };
+
+Radarr.radarrMovieAdd = function(id, title, qualityProfileId, rootFolderPath) {
+ return Meteor.call("radarrMovieAdd", id, title, qualityProfileId, rootFolderPath, {});
+};
diff --git a/lib/exports/sickrageExports.js b/lib/exports/sickrageExports.js
new file mode 100644
index 00000000..79b8395b
--- /dev/null
+++ b/lib/exports/sickrageExports.js
@@ -0,0 +1,28 @@
+function Server() {
+ this.url = "http://192.168.0.1";
+ this.port = 8081;
+ this.api = "abcdef012345";
+ this.directory = "";
+}
+
+SickRage = new Server();
+
+SickRage.available = function() {
+ return Meteor.call("available", {});
+};
+
+SickRage.checkShow = function(tvdbid) {
+ return Meteor.call("checkShow", tvdbid, {});
+};
+
+SickRage.addShow = function(tvdbid, episodes) {
+ return Meteor.call("addShow", tvdbid, episodes, {});
+};
+
+SickRage.deleteShow = function(tvdbid) {
+ return Meteor.call("deleteShow", tvdbid, {});
+};
+
+SickRage.statsShow = function(tvdbid) {
+ return Meteor.call("statsShow", tvdbid, {});
+};
diff --git a/lib/sonarr.js b/lib/exports/sonarrExports.js
similarity index 100%
rename from lib/sonarr.js
rename to lib/exports/sonarrExports.js
diff --git a/server/methods/admin/adminMethods.js b/server/methods/admin/adminMethods.js
index c515e3ff..5d0883be 100644
--- a/server/methods/admin/adminMethods.js
+++ b/server/methods/admin/adminMethods.js
@@ -1,63 +1,64 @@
Meteor.methods({
setIFTTTVARS: function(settings, request) {
var tags = {
- title: "",
- type: "",
- n_type: "",
- user: "",
- issues: "",
- year: "",
- link: ""
+ title: '',
+ type: '',
+ n_type: '',
+ user: '',
+ issues: '',
+ year: '',
+ link: ''
};
if (request === 'test') {
- var req = {
- title: "A Test Movie",
- media_type: "Movie",
- notification_type: "request",
- user: "test_user",
- year: "2020",
- link: "https://plex.tv"
+ var req;
+ req = {
+ title: 'A Test Movie',
+ media_type: 'Movie',
+ notification_type: 'request',
+ user: 'test_user',
+ year: '2020',
+ link: 'https://plex.tv'
};
- logger.info("Request type is test");
+ logger.info('Request type is test');
} else {
- var req = request;
- };
+ req = request;
+ }
var r = {};
if (settings.iftttMAKERVALUE1) {
var v_1 = settings.iftttMAKERVALUE1.replace(tags.title, req.title);
- var v_1 = v_1.replace(tags.type, req.media_type);
- var v_1 = v_1.replace(tags.n_type, req.notification_type);
- var v_1 = v_1.replace(tags.user, req.user);
- var v_1 = v_1.replace(tags.issues, req.issues);
- var v_1 = v_1.replace(tags.year, req.year);
- var v_1 = v_1.replace(tags.link, req.link);
- r["value1"] = v_1;
+ v_1 = v_1.replace(tags.type, req.media_type);
+ v_1 = v_1.replace(tags.n_type, req.notification_type);
+ v_1 = v_1.replace(tags.user, req.user);
+ v_1 = v_1.replace(tags.issues, req.issues);
+ v_1 = v_1.replace(tags.year, req.year);
+ v_1 = v_1.replace(tags.link, req.link);
+ r['value1'] = v_1;
}
if (settings.iftttMAKERVALUE2) {
var v_2 = settings.iftttMAKERVALUE2.replace(tags.title, req.title);
- var v_2 = v_2.replace(tags.type, req.media_type);
- var v_1 = v_1.replace(tags.n_type, req.notification_type);
- var v_2 = v_2.replace(tags.user, req.user);
- var v_2 = v_2.replace(tags.issues, req.issues);
- var v_2 = v_2.replace(tags.year, req.year);
- var v_2 = v_2.replace(tags.link, req.link);
- r["value2"] = v_2;
+ v_2 = v_2.replace(tags.type, req.media_type);
+ v_2 = v_2.replace(tags.n_type, req.notification_type);
+ v_2 = v_2.replace(tags.user, req.user);
+ v_2 = v_2.replace(tags.issues, req.issues);
+ v_2 = v_2.replace(tags.year, req.year);
+ v_2 = v_2.replace(tags.link, req.link);
+ r['value2'] = v_2;
}
if (settings.iftttMAKERVALUE3) {
var v_3 = settings.iftttMAKERVALUE3.replace(tags.title, req.title);
- var v_3 = v_3.replace(tags.type, req.media_type);
- var v_1 = v_1.replace(tags.n_type, req.notification_type);
- var v_3 = v_3.replace(tags.user, req.user);
- var v_3 = v_3.replace(tags.issues, req.issues);
- var v_3 = v_3.replace(tags.year, req.year);
- var v_3 = v_3.replace(tags.link, req.link);
- r["value3"] = v_3;
+ v_3 = v_3.replace(tags.type, req.media_type);
+ v_3 = v_3.replace(tags.n_type, req.notification_type);
+ v_3 = v_3.replace(tags.user, req.user);
+ v_3 = v_3.replace(tags.issues, req.issues);
+ v_3 = v_3.replace(tags.year, req.year);
+ v_3 = v_3.replace(tags.link, req.link);
+ r['value3'] = v_3;
}
return r;
@@ -65,116 +66,134 @@ Meteor.methods({
},
setTestVARS: function (t, b, request) {
-
+ var req;
var tags = {
- title: "",
- type: "",
- user: "",
- issues: "",
- release: "",
- link: ""
+ title: '',
+ type: '',
+ user: '',
+ issues: '',
+ release: '',
+ link: ''
};
if (request === 'test') {
- var req = {
- title: "A Test Movie",
- type: "request",
- user: "test_user",
- release: "2020",
- link: "https://plex.tv"
- };
+ req = {
+ title: 'A Test Movie',
+ type: 'request',
+ user: 'test_user',
+ release: '2020',
+ link: 'https://plex.tv'
+ };
- } else {var req = request;}
+ } else {
+ req = request;
+ }
var message_title = t.replace(tags.title, req.title);
- var message_title = message_title.replace(tags.type, req.media_type);
- var message_title = message_title.replace(tags.user, req.user);
- var message_title = message_title.replace(tags.issues, req.issues);
- var message_title = message_title.replace(tags.release, req.release);
- var message_title = message_title.replace(tags.link, req.link);
+ message_title = message_title.replace(tags.type, req.media_type);
+ message_title = message_title.replace(tags.user, req.user);
+ message_title = message_title.replace(tags.issues, req.issues);
+ message_title = message_title.replace(tags.release, req.release);
+ message_title = message_title.replace(tags.link, req.link);
var message_body = b.replace(tags.title, req.title);
- var message_body = message_body.replace(tags.type, req.media_type);
- var message_body = message_body.replace(tags.user, req.user);
- var message_body = message_body.replace(tags.issues, req.issues);
- var message_body = message_body.replace(tags.release, req.release);
- var message_body = message_body.replace(tags.link, req.link);
+ message_body = message_body.replace(tags.type, req.media_type);
+ message_body = message_body.replace(tags.user, req.user);
+ message_body = message_body.replace(tags.issues, req.issues);
+ message_body = message_body.replace(tags.release, req.release);
+ message_body = message_body.replace(tags.link, req.link);
- var r = {title: message_title, body: message_body}
- return r
- },
- testCouchPotato: function () {
- return CouchPotato.appAvailable();
- },
- testSickRage: function () {
- return SickRage.available();
- },
- testSonarr: function () {
- return Sonarr.systemStatus();
- },
- sonarrProfiles: function () {
- return Sonarr.profilesGet();
- },
- testIFTTT: function () {
- var settings = Settings.find().fetch()[0];
- console.log("Testing IFTTT Maker...");
- try {
- Meteor.call("sendIFTTT", settings, request='test');
- logger.info("IFTTT Maker tested successfully");
- } catch (error) {
- throw new Meteor.Error(401, error);
- }
- return true;
- },
- testPushbulllet: function () {
- var settings = Settings.find().fetch()[0];
- try {
- var message = Meteor.call("setTestVARS", settings.customNotificationTITLE, settings.customNotificationTEXT, request = 'test');
- Meteor.call("sendPushbulletNotification", settings, message.title, message.body);
- logger.info("Pushbullet tested successfully");
- } catch (error) {
- throw new Meteor.Error(401, error);
- }
- logger.info("Pushbullet tested successfully");
- return true;
- },
- testPushover: function () {
- var settings = Settings.find().fetch()[0];
- try {
- Meteor.call("sendPushoverNotification", settings, 'Pushover Requests', 'Test notification');
- logger.info("Pushover tested successfully");
- } catch (error) {
- throw new Meteor.Error(401, error);
- }
- logger.info("Pushover tested successfully");
- return true;
- },
- testSlack: function () {
- var settings = Settings.find().fetch()[0];
- try {
- Meteor.call("sendSlackNotification", settings, 'Plex Requests Test notification');
- } catch (error) {
- throw new Meteor.Error(401, error);
- }
- logger.info("Slack tested successfully");
+
+ return {title: message_title, body: message_body}
+ },
+
+ testCouchPotato: function () {
+ return CouchPotato.appAvailable();
+ },
+
+ testSickRage: function () {
+ return SickRage.available();
+ },
+
+ testSonarr: function () {
+ return Sonarr.systemStatus();
+ },
+
+ testRadarr: function () {
+ return Radarr.radarrSystemStatus();
+ },
+
+ SonarrProfiles: function () {
+ return Sonarr.profilesGet();
+ },
+
+ RadarrProfiles: function () {
+ return Radarr.radarrProfilesGet();
+ },
+
+ testIFTTT: function () {
+ var settings = Settings.find().fetch()[0];
+ console.log('Testing IFTTT Maker...');
+ try {
+ Meteor.call('sendIFTTT', settings, request='test');
+ logger.info('IFTTT Maker tested successfully');
+ } catch (error) {
+ throw new Meteor.Error('401', error);
+ }
+ return true;
+ },
+
+ testPushbulllet: function () {
+ var settings = Settings.find().fetch()[0];
+ try {
+ var message = Meteor.call('setTestVARS', settings.customNotificationTITLE, settings.customNotificationTEXT, request = 'test');
+ Meteor.call('sendPushbulletNotification', settings, message.title, message.body);
+ logger.info('Pushbullet tested successfully');
+ } catch (error) {
+ throw new Meteor.Error('401', error);
+ }
+ logger.info('Pushbullet tested successfully');
return true;
- },
-
- updateSeasonCount: function() {
- try {
+ },
+
+ testPushover: function () {
+ var settings = Settings.find().fetch()[0];
+ try {
+ Meteor.call('sendPushoverNotification', settings, 'Pushover Requests', 'Test notification');
+ logger.info('Pushover tested successfully');
+ } catch (error) {
+ throw new Meteor.Error('401', error);
+ }
+ logger.info('Pushover tested successfully');
+ return true;
+ },
+ testSlack: function () {
+ var settings = Settings.find().fetch()[0];
+ try {
+ Meteor.call('sendSlackNotification', settings, 'Plex Requests Test notification');
+ } catch (error) {
+ throw new Meteor.Error('401', error);
+ }
+ logger.info('Slack tested successfully');
+ return true;
+ },
+/*
+Unused at the moment, commenting out until implemented
+ */
+ updateSeasonCount: function() {
+ try {
var results = TV.find({seasons: -1}).fetch();
- for(i=0;i " + e.message);
+ return [];
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ var allProfiles;
+ try {
+ allProfiles = HTTP.get(Radarr.url + ":" + Radarr.port + Radarr.directory + "/api/profile", {headers: {"X-Api-Key":Radarr.api}, timeout: 15000} );
+ } catch (e) {
+ console.log("Radarr Profiles Get -> " + e.message);
+ return [];
+ }
+
+ return _.map(allProfiles.data, function (profile) {
+ return {
+ id: profile.id,
+ name: profile.name
+ };
+ });
+ },
+
+ radarrMovieAdd: function(tmdbId, title, qualityProfileId, rootFolderPath) {
+ try {
+ check(Radarr.url, String);
+ check(Radarr.port, Number);
+ check(Radarr.api, String);
+
+ check(title, String);
+ check(tmdbId, Number);
+ check(qualityProfileId, Number);
+ check(rootFolderPath, String);
+
+ } catch (e) {
+ console.log("Radarr Movie Post -> " + e.message);
+ return false;
+ }
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ var options = {"searchForMovie": 'true'};
+ try {
+ var response = HTTP.post(Radarr.url + ":" + Radarr.port + Radarr.directory + "/api/movie", {
+ headers: {"X-Api-Key":Radarr.api},
+ data: {
+ "title": title,
+ "tmdbId": tmdbId,
+ "qualityProfileId": qualityProfileId,
+ "rootFolderPath": rootFolderPath,
+ "titleSlug": title,
+ "monitored": 'true',
+ "images": [],
+ "addOptions": options
+ },
+ timeout: 15000
+ }
+ );
+
+ } catch (e) {
+ console.log("Radarr Movie Post -> " + e.message);
+ return false;
+ }
+ logger.log('debug', 'Radarr add response: \n' + JSON.stringify(response.data));
+ return response.data
+ },
+
+ radarrSystemStatus: function() {
+ try {
+ check(Radarr.url, String);
+ check(Radarr.port, Number);
+ check(Radarr.api, String);
+ } catch (e) {
+ console.log("Radarr Status -> " + e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.get(Radarr.url + ":" + Radarr.port + Radarr.directory + "/api/system/status", {headers: {"X-Api-Key":Radarr.api}, timeout: 15000} );
+ } catch (e) {
+ console.log("Radarr Status -> " + e.message);
+ return false;
+ }
+
+
+ return !!(response.data);
+ },
+
+ radarrMovieGet: function(tmdbId) {
+ /*
+ Returns JSON object of movie data if found
+ else:
+ false if not
+ */
+ try {
+ check(Radarr.url, String);
+ check(Radarr.port, Number);
+ check(Radarr.api, String);
+ check(tmdbId, Number);
+ } catch (e) {
+ console.log("Radarr Movie Get -> " + e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var allMovies = HTTP.get(Radarr.url + ":" + Radarr.port + Radarr.directory + "/api/movie", {headers: {"X-Api-Key":Radarr.api}, timeout: 15000} );
+ } catch (e) {
+ console.log("Radarr Movie Get -> " + e.message);
+ return false;
+ }
+
+ var parsed = JSON.parse(allMovies.content);
+ var data;
+ _.each(parsed, function (movie) {
+ if (movie.tmdbId === tmdbId) {
+ logger.log('debug', 'Movie found: \n' + movie.title);
+ data = movie;
+ }
+ });
+
+ if (data) {
+ logger.log('debug', 'Returned data');
+ return data;
+ } else {
+ logger.log('debug', 'Returned false');
+ return false
+ }
+ }
+
+});
+
diff --git a/server/methods/helpers/tv/sickrageMethods.js b/server/methods/helpers/tv/sickrageMethods.js
new file mode 100644
index 00000000..ae0e0911
--- /dev/null
+++ b/server/methods/helpers/tv/sickrageMethods.js
@@ -0,0 +1,165 @@
+Meteor.methods({
+ addShow: function(tvdbid, episodes){
+ try {
+ check(SickRage.url, String);
+ check(SickRage.port, Number);
+ check(SickRage.api, String);
+ check(SickRage.directory, String);
+ check(tvdbid, Number);
+ check(episodes, Number);
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ var episodeStatus = (episodes === 1) ? "&status=wanted" : "";
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.call("GET",
+ SickRage.url + ":" + SickRage.port + SickRage.directory + "/api/" + SickRage.api + "?cmd=show.addnew&tvdbid=" + tvdbid + episodeStatus,
+ {timeout: 2000} );
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ var status;
+
+ if (response.data) {
+ status = (response.data.result == "success");
+ } else {
+ status = false;
+ }
+
+ return status;
+ },
+
+ available: function(){
+ try {
+ check(SickRage.url, String);
+ check(SickRage.port, Number);
+ check(SickRage.api, String);
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.call("GET", SickRage.url + ":" + SickRage.port + SickRage.directory + "/api/" + SickRage.api + "/?cmd=sb.ping", {timeout: 2000} );
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ return (response.data)
+ },
+
+ checkShow: function(tvdbid){
+ try {
+ check(SickRage.url, String);
+ check(SickRage.port, Number);
+ check(SickRage.api, String);
+ check(tvdbid, Number);
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.call("GET", SickRage.url + ":" + SickRage.port + SickRage.directory + "/api/" + SickRage.api + "?cmd=show&tvdbid=" + tvdbid, {timeout: 2000} );
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ var status;
+
+ if (response.data) {
+ status = (response.data.result == "success");
+ } else {
+ status = false;
+ }
+
+ return status;
+ },
+
+ deleteShow: function(tvdbid){
+ try {
+ check(SickRage.url, String);
+ check(SickRage.port, Number);
+ check(SickRage.api, String);
+ check(tvdbid, Number);
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.call("GET", SickRage.url + ":" + SickRage.port + SickRage.directory + "/api/" + SickRage.api + "?cmd=show.delete&tvdbid=" + tvdbid, {timeout: 2000} );
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ var status;
+
+ if (response.data) {
+ status = (response.data.result == "success");
+ } else {
+ status = false;
+ }
+
+ return status;
+ },
+
+ statsShow: function(tvdbid){
+ try {
+ check(SickRage.url, String);
+ check(SickRage.port, Number);
+ check(SickRage.api, String);
+ check(tvdbid, Number);
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ //Workaround to allow self-signed SSL certs, however can be dangerous and should not be used in production, looking into better way
+ //But it's possible there's nothing much I can do
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+
+ try {
+ var response = HTTP.call("GET", SickRage.url + ":" + SickRage.port + SickRage.directory + "/api/" + SickRage.api + "?cmd=show.stats&tvdbid=" + tvdbid, {timeout: 2000} );
+ } catch (e) {
+ console.log(e.message);
+ return false;
+ }
+
+ var status;
+
+ if (response.data.data.total) {
+ var total = response.data.data.total - response.data.data.unaired;
+ var downloaded = response.data.data.downloaded.total;
+ status = {"downloaded" : downloaded, "total" : total}
+ } else {
+ status = {"downloaded" : 0, "total" : 0}
+ }
+
+ return status;
+ }
+});
diff --git a/server/methods/helpers/tv/sonarr.js b/server/methods/helpers/tv/sonarrMethods.js
similarity index 99%
rename from server/methods/helpers/tv/sonarr.js
rename to server/methods/helpers/tv/sonarrMethods.js
index 57f03ba6..5def446f 100644
--- a/server/methods/helpers/tv/sonarr.js
+++ b/server/methods/helpers/tv/sonarrMethods.js
@@ -159,7 +159,7 @@ Meteor.methods({
return false;
}
- return response.data ? true : false;
+ return !!response.data
},
seriesStats: function(tvdb) {
try {
diff --git a/server/methods/helpers/tv/tvmaze.js b/server/methods/helpers/tv/tvmazeMethods.js
similarity index 100%
rename from server/methods/helpers/tv/tvmaze.js
rename to server/methods/helpers/tv/tvmazeMethods.js
diff --git a/server/methods/notifications/iftttMaker.js b/server/methods/notifications/iftttMaker.js
index 64a39584..16ce1daa 100644
--- a/server/methods/notifications/iftttMaker.js
+++ b/server/methods/notifications/iftttMaker.js
@@ -1,11 +1,11 @@
Meteor.methods({
- "sendIFTTT": function(settings, request) {
+ 'sendIFTTT': function(settings, request) {
//////// Function Constants
var access_token = settings.iftttMAKERAPI;
var channel_tag = settings.iftttMAKERCHANNEL;
- var values = Meteor.call("setIFTTTVARS", settings, request);
+ var values = Meteor.call('setIFTTTVARS', settings, request);
var ifttt_url = 'https://maker.ifttt.com/trigger/' + channel_tag + '/with/key/' + access_token;
console.log(ifttt_url);
@@ -13,9 +13,9 @@ Meteor.methods({
console.log(values);
var data = {
data: {
- "value1": values.value1,
- "value2": values.value2,
- "value3": values.value3
+ 'value1': values.value1,
+ 'value2': values.value2,
+ 'value3': values.value3
}
};
//////// Create JSON object of http.post Parameters
@@ -31,7 +31,7 @@ Meteor.methods({
catch (error) {
var err = error.response.data.error.message;
- logger.error("IFTTT Maker error: " + err);
+ logger.error('IFTTT Maker error: ' + err);
throw err;
}
}
diff --git a/server/methods/requests/approveAll.js b/server/methods/requests/approveAll.js
index 3064b0f7..ef4c0b1e 100644
--- a/server/methods/requests/approveAll.js
+++ b/server/methods/requests/approveAll.js
@@ -1,10 +1,10 @@
Meteor.methods({
approveAll: function () {
- var movies = Movies.find().fetch();
+ var movies = Movies.find({approval_status: 0}).fetch();
var tv = TV.find().fetch();
movies.forEach(function (movie) {
- Meteor.call("approveRequest", movie);
+ Meteor.call("approveRequest", movie);
});
tv.forEach(function (show) {
diff --git a/server/methods/requests/approveRequest.js b/server/methods/requests/approveRequest.js
index 190fbe4b..5c523978 100644
--- a/server/methods/requests/approveRequest.js
+++ b/server/methods/requests/approveRequest.js
@@ -1,130 +1,172 @@
+// TODO: Clean up the approveRequest method. Approving the request should be a single action and client agnostic
+// TODO: Define what should be returned by the "movie info" methods of each client. Should be uniform across clients
+
Meteor.methods({
"approveRequest": function(request) {
- check(request, Object);
- var settings = Settings.find().fetch()[0];
+ check(request, Object);
+ var settings = Settings.find().fetch()[0];
+ var status = null;
- // If not logged in return without doing anything
- if (!Meteor.user()) {
- return false;
- }
+ // If not logged in return without doing anything
+ if (!Meteor.user()) {
+ return false;
+ }
- if (request.imdb) {
- // First confirm it doesn't exist already
- try {
- if (settings.couchPotatoENABLED) {
- var checkCP = CouchPotato.mediaGet(request.imdb);
- var status = checkCP.status == "done";
- if (checkCP.status !== "false" && checkCP !== false) {
+ if (request.imdb) {
+ // First confirm it doesn't exist already
+ try {
+ if (settings.couchPotatoENABLED) {
+ var checkCP = CouchPotato.mediaGet(request.imdb);
+ status = checkCP.status == "done";
+ if (checkCP.status !== "false" && checkCP !== false) {
+ try {
+ Movies.update(request._id, {$set: {approval_status: 1, downloaded: status}});
+ return true;
+ } catch (error) {
+ logger.error(error.message);
+ return false;
+ }
+ }
+ }
+ } catch (error) {
+ logger.error('Error checking CouchPotato', error.message);
+ return false;
+ }
+
+ try {
+ if (settings.radarrENABLED) {
+ var checkRadarr = Radarr.radarrMovieGet(request.id);
+ if (checkRadarr) {
+
+ status = Radarr.radarrMovieGet(request.id);
try {
Movies.update(request._id, {$set: {approval_status: 1, downloaded: status}});
return true;
} catch (error) {
+
logger.error(error.message);
return false;
}
}
}
- } catch (error) {
- logger.error("Error checking Couch Potato:", error.message);
- return false;
- }
- // Doesn't exist so try to add
- if (settings.couchPotatoENABLED) {
- try {
- if (CouchPotato.movieAdd(request.imdb)) {
- Movies.update(request._id, {$set: {approval_status: 1}});
- return true;
- } else {
- return false;
- }
- } catch (error) {
- logger.error("Error adding to Couch Potato:", error.message);
- return false;
- }
- } else {
+ } catch (error) {
+ logger.error('Error checking Radarr: ', error.message);
+ return false;
+ }
+
+ // Doesn't exist so try to add
+ if (settings.couchPotatoENABLED) {
+ try {
+ if (CouchPotato.movieAdd(request.imdb)) {
+ Movies.update(request._id, {$set: {approval_status: 1, downloaded: false}});
+ return true;
+ } else {
+ return false;
+ }
+ } catch (error) {
+ logger.error("Error adding to Couch Potato:", error.message);
+ return false;
+ }
+
+ } else if (settings.radarrENABLED) {
+ var radarrQualityProfileId = settings.radarrQUALITYPROFILEID;
+ var RadarrRootFolderPath = settings.radarrROOTFOLDERPATH;
+ try {
+ if (Radarr.radarrMovieAdd(request.id, request.title, radarrQualityProfileId, RadarrRootFolderPath)) {
+ Movies.update(request._id, {$set: {approval_status: 1, downloaded: false}});
+ return true;
+ } else {
+ return false;
+ }
+ } catch (error) {
+ logger.error("Error adding to Radarr: ", error.message);
+ return false;
+ }
+ } else {
Movies.update(request._id, {$set: {approval_status: 1}});
return true;
}
- } else {
- if (settings.sickRageENABLED) {
- // First confirm it doesn't exist already
- try {
- if (settings.sickRageENABLED) {
- var checkSickRage = SickRage.checkShow(request.tvdb);
- if (checkSickRage) {
- var status = SickRage.statsShow(request.tvdb);
- try {
- TV.update(request._id, {$set: {approval_status: 1, status: status}});
- return true;
- } catch (error) {
- logger.error(error.message);
- return false;
- }
- }
- }
- } catch (error) {
- logger.error("Error checking SickRage:", error.message);
- return false;
- }
+ } else {
+ if (settings.sickRageENABLED) {
+ // First confirm it doesn't exist already
+ try {
+ if (settings.sickRageENABLED) {
+ var checkSickRage = SickRage.checkShow(request.tvdb);
+ if (checkSickRage) {
+ status = SickRage.statsShow(request.tvdb);
+ try {
+ TV.update(request._id, {$set: {approval_status: 1, status: status}});
+ return true;
+ } catch (error) {
+ logger.error(error.message);
+ return false;
+ }
+ }
+ }
+ } catch (error) {
+ logger.error("Error checking SickRage:", error.message);
+ return false;
+ }
- // Doesn't exist so try to add
- try {
- var episodes = (request.episodes === true) ? 1 : 0;
- if (SickRage.addShow(request.tvdb, episodes)) {
- TV.update(request._id, {$set: {approval_status: 1}});
- return true;
- } else {
- logger.error("Error adding to SickRage");
- return false;
- }
- } catch (e) {
- logger.error("Error adding to SickRage:", error.message);
- return false;
- }
- } else if (settings.sonarrENABLED) {
- // First confirm it doesn't exist already
- try {
- if (settings.sonarrENABLED) {
- var checkSonarr = Sonarr.seriesGet(request.tvdb);
-
- if (checkSonarr) {
- var status = Sonarr.seriesStats(request.tvdb);
- try {
- TV.update(request._id, {$set: {approval_status: 1, status: status}});
- return true;
- } catch (error) {
- logger.error(error.message);
- return false;
- }
- }
- }
- } catch (error) {
- logger.error("Error checking Sonarr:", error.message);
- return false;
- }
+ // Doesn't exist so try to add
+ try {
+ var episodes = (request.episodes === true) ? 1 : 0;
+ if (SickRage.addShow(request.tvdb, episodes)) {
+ TV.update(request._id, {$set: {approval_status: 1}});
+ return true;
+ } else {
+ logger.error("Error adding to SickRage");
+ return false;
+ }
+ } catch (error) {
+ logger.error("Error adding to SickRage:", error.message);
+ return false;
+ }
+ } else if (settings.sonarrENABLED) {
+ // First confirm it doesn't exist already
+ try {
+ if (settings.sonarrENABLED) {
+ var checkSonarr = Sonarr.seriesGet(request.tvdb);
+
+ if (checkSonarr) {
+ status = Sonarr.seriesStats(request.tvdb);
+ try {
+ TV.update(request._id, {$set: {approval_status: 1, status: status}});
+ return true;
+ } catch (error) {
+ logger.error(error.message);
+ return false;
+ }
+ }
+ }
+ } catch (error) {
+ logger.error("Error checking Sonarr:", error.message);
+ return false;
+ }
+
+ var qualityProfileId = settings.sonarrQUALITYPROFILEID;
+ var seasonFolder = settings.sonarrSEASONFOLDERS;
+ var rootFolderPath = settings.sonarrROOTFOLDERPATH;
+ try {
+ if (Sonarr.seriesPost(request.tvdb, request.title, qualityProfileId, seasonFolder, rootFolderPath, request.episodes)) {
+ TV.update(request._id, {$set: {approval_status: 1}});
+ return true;
+ } else {
+ return false;
+ }
+ } catch (error) {
+ logger.error("Error adding to Sonarr:", error.message);
+ return false;
+ }
+ } else {
+ TV.update(request._id, {$set: {approval_status: 1}});
+ return true;
+ }
+ }
+ },
- var qualityProfileId = settings.sonarrQUALITYPROFILEID;
- var seasonFolder = settings.sonarrSEASONFOLDERS;
- var rootFolderPath = settings.sonarrROOTFOLDERPATH;
- try {
- if (Sonarr.seriesPost(request.tvdb,request.title, qualityProfileId, seasonFolder, rootFolderPath, request.episodes)) {
- TV.update(request._id, {$set: {approval_status: 1}});
- return true;
- } else {
- return false;
- }
- } catch (error) {
- logger.error("Error adding to Sonarr:", error.message);
- return false;
- }
- } else {
- TV.update(request._id, {$set: {approval_status: 1}});
- return true;
- }
- }
- },
"denyRequest": function(docID, reason) {
// If not logged in return without doing anything
if (!Meteor.user()) {
@@ -160,4 +202,4 @@ Meteor.methods({
}
}
}
-});
+});
\ No newline at end of file
diff --git a/server/methods/search/requestMovie.js b/server/methods/search/requestMovie.js
index 901f5958..94719378 100644
--- a/server/methods/search/requestMovie.js
+++ b/server/methods/search/requestMovie.js
@@ -1,3 +1,7 @@
+// TODO: Clean up the requestMovie method, much of the logic is duplicated throughout and can be simplified
+// TODO: Define what exactly gets returned by each clients "add movie" method for uniform, predictable returns
+// #td-done: Fix issue with not validating if movie exists in radarr
+
Meteor.methods({
"requestMovie": function(request) {
check(request, Object);
@@ -6,12 +10,32 @@ Meteor.methods({
request["notification_type"] = "request";
request["media_type"] = "Movie";
-
// Check user request limit
var date = Date.now() - 6.048e8;
var weeklyLimit = Settings.find({}).fetch()[0].movieWeeklyLimit;
var userRequestTotal = Movies.find({user:request.user, createdAt: {"$gte": date} }).fetch().length;
+ // One function to rule them all!!
+ // Or just to simplify adding movies to the DB
+ function insertMovie(request, imdbid, dlStatus, approvalStatus, poster) {
+ try {
+ Movies.insert({
+ title: request.title,
+ id: request.id,
+ imdb: imdbid,
+ released: request.release_date,
+ user: request.user,
+ downloaded: dlStatus,
+ approval_status: approvalStatus,
+ poster_path: poster
+ });
+ } catch (error) {
+ logger.error(error.message);
+ return false;
+ }
+ return true;
+ }
+
if (weeklyLimit !== 0
&& (userRequestTotal >= weeklyLimit)
&& !(Meteor.user())
@@ -22,7 +46,7 @@ Meteor.methods({
}
// Movie Request only requires IMDB_ID
- //Get IMDB ID
+ // Get IMDB ID
try {
var imdb = TMDBSearch.externalIds(request.id, "movie");
if (imdb.indexOf("tt") === -1) {
@@ -35,32 +59,20 @@ Meteor.methods({
}
// Check if it already exists in CouchPotato
+ // If it exists, insert into our collection
if (settings.couchPotatoENABLED) {
try {
var checkCP = CouchPotato.mediaGet(imdb);
var status = checkCP.status == "done";
if (checkCP.status !== "false" && checkCP !== false) {
- try {
- Movies.insert({
- title: request.title,
- id: request.id,
- imdb: imdb,
- released: request.release_date,
- user: request.user,
- downloaded: status,
- approval_status: 1,
- poster_path: poster
- });
-
- if (status) {
- return 'exists';
- } else {
- return true;
- }
+ insertMovie(request, imdb, checkCP.status, 1, poster);
+ // Using these values to set client states
+ // TODO: Look into alternate method for this
- } catch (error) {
- logger.error(error.message);
- return false;
+ if (status) {
+ return "exists";
+ } else {
+ return false
}
}
} catch (error) {
@@ -69,54 +81,106 @@ Meteor.methods({
}
}
- //If approval needed and user does not have override permission
+ // Check if it exists in Radarr
+ // Same deal here, check and bail on fail else continue on
+ if (settings.radarrENABLED) {
+ try {
+ // MovieGet returns false if not found or the data from radarr as a JSON object if it exists
+ // So here, just check if it's false and if so we can continue on
+ var checkRadarr = Radarr.radarrMovieGet(request.id);
+ logger.log('debug', "Radarr Movie info: \n" + JSON.stringify(checkRadarr));
+ if (checkRadarr !== false) {
+ logger.log('info', "Movie already present in Radarr");
+ insertMovie(request, imdb, checkRadarr.downloaded, 1, poster);
+ // Using these values to set client states
+ // TODO: Look into alternate method for this
+ return "exists"
+ }
+ } catch (error) {
+ logger.error("Error checking Radarr:", error.message);
+ return false;
+ }
+ }
+
+ /*
+ | Making it here means the media did not exist in either client so we proceed to handling the request
+ | based on the users permissions.
+ */
+
+ // If approval needed and user does not have override permission
if (settings.movieApproval
+
//Check if user has override permission
&& (!settings.plexAuthenticationENABLED || !Permissions.find({permUSER: request.user}).fetch()[0].permAPPROVAL)) {
// Approval required
- // Add to DB but not CP
+ // Add to DB but do NOT send to client
try {
- Movies.insert({
- title: request.title,
- id: request.id,
- imdb: imdb,
- released: request.release_date,
- user: request.user,
- downloaded: false,
- approval_status: 0,
- poster_path: poster
- });
- } catch (error) {
+
+ var result = insertMovie(request, imdb, false, 0, poster);
+
+ } catch (error) {
+
logger.error(error.message);
return false;
+
+ }
+
+ if (result) {
+ Meteor.call("sendNotifications", request);
+ return true;
}
+ else {
+ logger.error('Error sending notification');
+ return false;
+ }
+
+ } else {
+ // No approval required
- Meteor.call("sendNotifications", request);
- return true;
- } else {
- // No approval required
+ if (settings.couchPotatoENABLED) {
- if (settings.couchPotatoENABLED) {
+ // Were sending the request to CP here
+ try {
+ var add = CouchPotato.movieAdd(imdb);
+ } catch (error) {
+ logger.error("Error adding to Couch Potato:", error.message);
+ return false;
+ }
+
+ // If the request was successful, insert the movie into our collection
+ try {
+ if (add) {
+ result = insertMovie(request, imdb, false, 1, poster);
+ }
+ } catch (error) {
+
+ logger.error(error.message);
+ return false;
+
+ }
+ // If we added to our collection successfully, were ready to tell the world!
+ if (result) {
+ Meteor.call("sendNotifications", request);
+ return true;
+ }
+ else {
+ logger.error('Error sending notification');
+ return false;
+ }
+
+ // Radarr's turn now
+ } else if (settings.radarrENABLED) {
+ // So, standard practice here, send the request to client then insert then notify.
try {
- var add = CouchPotato.movieAdd(imdb);
+ add = Radarr.radarrMovieAdd(request.id, request.title, settings.radarrQUALITYPROFILEID, settings.radarrROOTFOLDERPATH);
} catch (error) {
- logger.error("Error adding to Couch Potato:", error.message);
+ logger.error("Error adding to Radarr:", error.message);
return false;
}
-
if (add) {
try {
- Movies.insert({
- title: request.title,
- id: request.id,
- imdb: imdb,
- released: request.release_date,
- user: request.user,
- downloaded: false,
- approval_status: 1,
- poster_path: poster
- });
+ insertMovie(request, imdb, false, 1, poster);
} catch (error) {
logger.error(error.message);
return false;
@@ -126,25 +190,7 @@ Meteor.methods({
} else {
return false;
}
- } else {
- try {
- Movies.insert({
- title: request.title,
- id: request.id,
- imdb: imdb,
- released: request.release_date,
- user: request.user,
- downloaded: false,
- approval_status: 1,
- poster_path: poster
- });
- Meteor.call("sendNotifications", request);
- return true;
- } catch (error) {
- logger.error(error.message);
- return false;
- }
}
}
}
- });
+ });
\ No newline at end of file
diff --git a/server/startup/logging.js b/server/startup/logging.js
index b820f3d2..243771fb 100644
--- a/server/startup/logging.js
+++ b/server/startup/logging.js
@@ -1,31 +1,31 @@
Meteor.startup(function () {
//creating a global server logger
- logger = Meteor.npmRequire('winston');
- var FS = Npm.require('fs');
- var Path = Npm.require('path');
- var meteor_root = FS.realpathSync( process.cwd() + '/../' );
- var application_root = FS.realpathSync( meteor_root + '/../' );
+ logger = Meteor.npmRequire('winston');
+ var FS = Npm.require('fs');
+ var Path = Npm.require('path');
+ var meteor_root = FS.realpathSync( process.cwd() + '/../' );
+ var application_root = FS.realpathSync( meteor_root + '/../' );
- // if running on dev mode
- if( Path.basename(FS.realpathSync( meteor_root + '/../../../' ) ) == '.meteor' ){
+ // if running on dev mode
+ if( Path.basename(FS.realpathSync( meteor_root + '/../../../' ) ) == '.meteor' ){
application_root = FS.realpathSync( meteor_root + '/../../../../' );
- }
+ }
- logger.add(logger.transports.File, {
- filename: Path.join(application_root + '/logs.log'),
- handleExceptions: true,
- humanReadableUnhandledException: true,
- exitOnError: false,
- maxsize: 10000000,
- maxFiles: 3
- });
+ logger.add(logger.transports.File, {
+ filename: Path.join(application_root + '/logs.log'),
+ handleExceptions: true,
+ humanReadableUnhandledException: true,
+ exitOnError: false,
+ maxsize: 10000000,
+ maxFiles: 3
+ });
- logger.remove(logger.transports.Console);
+ logger.remove(logger.transports.Console);
- logger.add(logger.transports.Console, {
- handleExceptions: true,
- humanReadableUnhandledException: true,
- exitOnError: false
- });
+ logger.add(logger.transports.Console, {
+ handleExceptions: true,
+ humanReadableUnhandledException: true,
+ exitOnError: false
+ });
});
diff --git a/server/startup/settings.js b/server/startup/settings.js
index 8d0140c7..a0089083 100644
--- a/server/startup/settings.js
+++ b/server/startup/settings.js
@@ -36,6 +36,13 @@ Meteor.startup(function () {
Sonarr.api = settings.sonarrAPI;
Sonarr.directory = settings.sonarrDIRECTORY || "";
+ //set Radarr on start-up
+ Radarr.url = (settings.radarrSSL) ? "https://" + settings.radarrURL : "http://" + settings.radarrURL;
+ Radarr.port = settings.radarrPORT;
+ Radarr.api = settings.radarrAPI;
+ Radarr.directory = settings.radarrDIRECTORY || "";
+
+
Meteor.call("updateSeasons");
Meteor.call("updateApproved");
diff --git a/version.txt b/version.txt
index 545fd574..39893559 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.15.7
+1.20.0