├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md ├── bin ├── plexreport └── plexreport-setup ├── etc ├── config.yaml.example └── email_body.erb ├── images └── plex.png ├── initial_setup.sh ├── lib ├── locales │ ├── de.yml │ ├── en.yml │ └── fr.yml ├── mailReport.rb ├── omdb.rb ├── plex.rb ├── plexTv.rb ├── themoviedb.rb └── thetvdb.rb └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | etc/config.yaml 2 | cron/ 3 | plexReport.log 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'json', '1.8.2' 4 | gem 'httparty', '0.13.1' 5 | gem 'mail', '2.6.3' 6 | gem 'logger', '1.2.8' 7 | gem 'highline', '1.7.1' 8 | gem 'i18n', '0.7.0' 9 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | highline (1.7.1) 5 | httparty (0.13.1) 6 | json (~> 1.8) 7 | multi_xml (>= 0.5.2) 8 | i18n (0.7.0) 9 | json (1.8.1) 10 | logger (1.2.8) 11 | mail (2.6.3) 12 | mime-types (>= 1.16, < 3) 13 | mime-types (2.4.3) 14 | multi_xml (0.5.5) 15 | 16 | PLATFORMS 17 | ruby 18 | 19 | DEPENDENCIES 20 | highline (= 1.7.1) 21 | httparty (= 0.13.1) 22 | i18n (= 0.7.0) 23 | json (= 1.8.1) 24 | logger (= 1.2.8) 25 | mail (= 2.6.3) 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | plexWeeklyReport 2 | ================ 3 | 4 | Scripts to generate a weekly email of new additions to Plex. 5 | 6 | ## Introduction 7 | This script is meant to send out a summary of all new Plex entries to your server to all of your server's users. 8 | 9 | ## Supported Platforms 10 | * Debian 11 | * Ubuntu 14.04 LTS 12 | * Mac OSX 13 | 14 | ## Supported Email Clients 15 | * Gmail 16 | * Mozilla Thunderbird 17 | 18 | ## Supported Plex Agents 19 | * themoviedb 20 | * Freebase 21 | * thetvdb.org 22 | 23 | ## Prerequisites 24 | 25 | The following are needed to run this script: 26 | 27 | 1. Ruby installed (at least version 1.9.3) and ruby-dev. 28 | 2. For OSX: make sure you have Ruby installed using RVM (This is needed to create a wrapper to weekly run the script through crontab) (see http://railsapps.github.io/installrubyonrails-mac.html. Follow the steps from "Prepare your computer" until "Rails installation options"). 29 | 3. themoviedb set as your Agent for your Movie section on your Plex server. 30 | 3. thetvdb.org set as your Agent for your TV section on your Plex server. 31 | 4. (Optional) A Gmail account to forward the email (Gmail is the only supported provider, so if you use another, YMMV). 32 | 33 | ## Installation (Linux) 34 | 35 | 1. Clone this repo on your server: 36 | 37 | `git clone https://github.com/bstascavage/plexReport.git` 38 | 2. Change to the plexReport directory 39 | 3. Run the initial_setup script: 40 | 41 | `./initial_setup.sh` 42 | 43 | 4. If you want to run your script with different commandline parameters, you'll need to edit the crontab. See here for reference: http://www.adminschoice.com/crontab-quick-reference 44 | 45 | ## Installation (OS X) 46 | Part 1: Install plexReport 47 | 48 | 1. Clone this repo on your server: 49 | 50 | `git clone https://github.com/bstascavage/plexReport.git` 51 | 2. Change to the plexReport directory 52 | 3. Install the blunder gem (http://bundler.io/) 53 | 54 | `gem install bundler` 55 | 4. Install the gem dependecies: 56 | 57 | `bundle install` 58 | 5. Setup the config file in `etc/config.yaml`. See `etc/config.yaml.example` and below for details 59 | 6. Run `bin/plexreport` to execute the script 60 | It should work correctly 61 | 62 | 63 | Part 2: Create Ruby Wrapper 64 | 65 | Now to have the script run once a week through crontab, you have to create an RVM alias by doing the following steps: 66 | (Note: You need an RVM alias because launchd, cron, and other process schedulers operate in discrete bash shell environments. Simply calling ruby from inside your launchd or cron script will not work; that will invoke the non-RVM ruby that OS X shipped with. Instead, you need an RVM alias, which will run your file through RVM's ruby, from inside launchd.) 67 | 68 | 1. Determine your ruby version by entering 69 | 70 | `which ruby` 71 | this should results in: 72 | `/Users/you/.rvm/rubies/ruby-2.2.0/bin/ruby` 73 | ruby-2.2.0 is your ruby version 74 | 75 | 2. Create a wrapper by entering 76 | 77 | `rvm alias create plexReport ruby-2.2.0@plexReport` 78 | Note: Replace ruby-2.2.0 with the version that you have determined in step 1 79 | 80 | 3. Test the wrapper by entering 81 | 82 | `$rvm_path/wrappers/plexReport/ruby /bin/plexReport.rb -t` 83 | Note: Replace with the path leading to your plexReport directory 84 | 85 | It should run and exit properly (be patient it might take a few minutes). 86 | 87 | 4. Next determine the absolute path to your wrapper. Just run 88 | 89 | `echo $rvm_path` 90 | it should result in something like this /users/esw1187/.rvm/ 91 | 92 | Substitute '$rvm_path' in the wrapper call with the absolute rvm path obtaine above and run it again by entering 93 | 94 | `/users/ersw1187/.rvm/wrappers/plexReport/ruby /path_to/plexReport/bin/plexReport.rb` 95 | 96 | 5. Create bash script to run the Rub code by doing the following: 97 | - Create a file on your desktop named 'plexReport.sh' and open it with TextEdit 98 | 99 | - Copy the following two lines in the file 100 | `export LC_ALL=en_US.UTF-8` 101 | `export LANG=en_US.UTF-8` 102 | 103 | - Add the wrapper call you just tested in step 4 to the file that you have just tested. E.g. 104 | `/users/ersw1187/.rvm/wrappers/plexReport/ruby /path_to/plexReport/bin/plexReport` 105 | 106 | 6. Copy plexReport.sh to /user/local/bin directory 107 | 108 | 7. Go to the /usr/local/bin directory and set the correct permissions by entering 109 | `chmod u+x plexReport.sh` 110 | 111 | 8. Add the following line to your crontab (sudo crontab -e) 112 | 113 | `15 11 * * 5 /usr/local/bin/plexReport.sh` 114 | (This will run it every Friday at 11:15. To change the time, see crontab documentation: 115 | http://www.adminschoice.com/crontab-quick-reference 116 | 117 | ## Upgrading 118 | 119 | To upgrade your code, cd to your plexReport directory and run `./update.sh` 120 | 121 | ## Config file 122 | 123 | By default, the config file is located in `/etc/plexReport/config.yaml`. If you need to change any information for the program, or to add more optional config parameters, see below for the config file format: 124 | 125 | ###### email 126 | `title` - Banner title for the email body. Required. 127 | 128 | `language` - The language of the email body. You need to use ISO 639-1 code ('fr', 'en', 'de'). If a content is not available in the specified language, the script will fall back to english. Defaults to 'en'. Optional. 129 | 130 | ###### plex 131 | `server` - IP address of your Plex server. Defaults to 'localhost'. Optional. 132 | 133 | `api_key` - Your Plex API key. Required. 134 | 135 | `sections` - Array of sections to report on. If field is not set, will report on all TV and movie sections. Format is ['section1', 'section2']. Optional. 136 | 137 | ###### mail 138 | `address` - Address of your smtp relay server. (ie smtp.gmail.com). Required. 139 | 140 | `port` - Mail port to use. Default is 25. (Use 587 for gmail.com). Required 141 | 142 | `username` - Email address to send the email from. Required. 143 | 144 | `password` - Password for hte email set above. Required. 145 | 146 | `from` - Display name of the sender. Required. 147 | 148 | `subject` - Subject of the email. Note that the script will automatically add a date to the end of the subject. Required. 149 | 150 | `recipients_email` - Email addresses of any additional recipients, outside of your Plex friends. Optional. 151 | 152 | `recipients` - Plex usernames of any Plex friends to be notified. To be used with the -n option. Optional 153 | 154 | ## Command-line Options 155 | 156 | Once installed, you can run the script by simply running `plexreport`. If you need to reinstall or reconfigure the program, run `plexreport-setup`. All commandline options can be seen by running `plexReport --help` 157 | 158 | ##### Options: 159 | `-n, --no-plex-email` - Do not send emails to Plex friends. Can be used with the `recipients_email` and `recipients` config file option to customize email recipients. 160 | 161 | `-l, --add-library-names` - Adding the Library name in front of the movie/tv show. To be used with custom Libraries 162 | 163 | `-t, --test-email` - Send email only to the Plex owner (ie yourself). For testing purposes 164 | 165 | `-d, --detailed-email` - Send more details in the email, such as movie ratings, actors, etc 166 | 167 | ## Images 168 | 169 | New Episodes: 170 | ![alt tag](http://i.imgur.com/hWzHl2x.png) 171 | 172 | 173 | New Seasons: 174 | ![alt tag](http://i.imgur.com/sBy62Ty.png) 175 | 176 | 177 | New Movies: 178 | ![alt tag](http://i.imgur.com/E3Q85uU.png) 179 | 180 | New Movies (detailed view): 181 | ![alt tag](http://i.imgur.com/9BHiQHW.png) 182 | -------------------------------------------------------------------------------- /bin/plexreport: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'rubygems' 3 | require 'bundler/setup' 4 | require 'time' 5 | require 'date' 6 | require 'yaml' 7 | require 'erb' 8 | require 'logger' 9 | require 'optparse' 10 | require 'pp' 11 | require 'i18n' 12 | require 'i18n/backend/fallbacks' 13 | 14 | require_relative '/var/lib/plexReport/plex' 15 | require_relative '/var/lib/plexReport/themoviedb' 16 | require_relative '/var/lib/plexReport/thetvdb' 17 | require_relative '/var/lib/plexReport/omdb' 18 | require_relative '/var/lib/plexReport/mailReport' 19 | 20 | # Class for parsing the Plex server for new movies and TV Shows 21 | # 22 | # Author: Brian Stascavage 23 | # Email: brian@stascavage.com 24 | # 25 | class PlexReport 26 | $options = { 27 | :emails => true, 28 | :library_names => false, 29 | :test_email => false, 30 | :detail_email => false, 31 | :full => false, 32 | :debug => false 33 | } 34 | 35 | OptionParser.new do |opts| 36 | opts.banner = "PlexReport: A script for sending out regular Plex summaries\nUsage: plexReport.rb [$options]" 37 | 38 | opts.on("-a", "--all-media", "Scans full library. Takes a long time; only for servers that have large updates") do |opt| 39 | $options[:full] = true 40 | end 41 | 42 | opts.on("-d", "--detailed-email", "Send more details in the email, such as movie ratings, actors, etc") do |opt| 43 | $options[:detail_email] = true 44 | end 45 | 46 | opts.on("-l", "--add-library-names", "Adding the Library name in front of the movie/tv show. To be used with custom Libraries") do |opt| 47 | $options[:library_names] = true 48 | end 49 | 50 | opts.on("-n", "--no-plex-email", "Do not send emails to Plex friends") do |opt| 51 | $options[:emails] = false 52 | end 53 | 54 | opts.on("-t", "--test-email", "Send email only to the Plex owner (ie yourself). For testing purposes") do |opt| 55 | $options[:test_email] = true 56 | end 57 | 58 | opts.on("-v", "--verbose", "Enable verbose debug logging") do |opt| 59 | $options[:verbose] = true 60 | end 61 | end.parse! 62 | 63 | def initialize 64 | begin 65 | $config = YAML.load_file('/etc/plexReport/config.yaml') 66 | rescue Errno::ENOENT => e 67 | abort('Configuration file not found. Exiting...') 68 | end 69 | 70 | begin 71 | $logger = Logger.new('/var/log/plexReport.log') 72 | 73 | if $options[:verbose] 74 | $logger.level = Logger::DEBUG 75 | else 76 | $logger.level = Logger::INFO 77 | end 78 | rescue 79 | abort('Log file not found. Exiting...') 80 | end 81 | 82 | $logger.info("Starting up PlexReport") 83 | end 84 | 85 | 86 | # Method for parsing the Plex library for every movie 87 | def getMovies 88 | moviedb = TheMovieDB.new($config) 89 | omdb = OMDB.new 90 | plex = Plex.new($config) 91 | movies = Array.new 92 | 93 | library = plex.get('/library/sections') 94 | 95 | library['MediaContainer']['Directory'].each do | element | 96 | if element['type'] == 'movie' 97 | # Checks to see if a section filter was applied 98 | # If so, checks to see if this section should be reported 99 | if !$config['plex']['sections'].nil? 100 | if !$config['plex']['sections'].include?(element['title']) 101 | break 102 | end 103 | end 104 | 105 | library = plex.get("/library/sections/#{element['key']}/all") 106 | 107 | if library['MediaContainer']['Video'].is_a?(Hash) 108 | begin 109 | movie = self.getMovieInfo(library['MediaContainer']['Video']) 110 | if !movie.nil? 111 | movies.push(movie) 112 | end 113 | rescue 114 | $logger.error("Error loading movie section #{element['librarySectionTitle']}. Is it empty?") 115 | end 116 | else 117 | library['MediaContainer']['Video'].each do | element | 118 | movie = self.getMovieInfo(element) 119 | if !movie.nil? 120 | movies.push(movie) 121 | end 122 | end 123 | end 124 | end 125 | end 126 | return movies.sort_by { |hsh| hsh[:title] } 127 | end 128 | 129 | 130 | # For a given movie, pulls it's metadata from the search agent 131 | # Parameters: 132 | # movie: Plex movie object, from '/library/sections/ movie['id'], 170 | :title => (localized_movie['title'].nil? ? movie['title'] : localized_movie['title'] ), 171 | :image => "https://image.tmdb.org/t/p/w154#{poster_path}", 172 | :date => omdb_result['Year'], 173 | :tagline => (localized_movie['tagline'].nil? ? movie['tagline'] : localized_movie['tagline']), 174 | :synopsis => (localized_movie['overview'].nil? ? movie['overview'] : localized_movie['overview']), 175 | :runtime => (localized_movie['runtime'].nil? ? movie['runtime'] : localized_movie['runtime']), 176 | :imdb => "http://www.imdb.com/title/#{movie['imdb_id']}", 177 | :imdb_rating => omdb_result['imdbRating'], 178 | :imdb_votes => omdb_result['imdbVotes'], 179 | :director => omdb_result['Director'], 180 | :actors => omdb_result['Actors'], 181 | :genre => omdb_result['Genre'], 182 | :released => omdb_result['Released'], 183 | :rating => omdb_result['Rated'] 184 | } 185 | rescue 186 | end 187 | end 188 | end 189 | end 190 | end 191 | 192 | 193 | # Method for getting new TV shows from the Plx server 194 | def getTVEpisodes 195 | plex = Plex.new($config) 196 | tv_episodes = Hash.new 197 | tv_episodes[:new] = [] 198 | tv_episodes[:seasons] = [] 199 | 200 | library = plex.get('/library/sections') 201 | library['MediaContainer']['Directory'].each do | element | 202 | if element['type'] == 'show' 203 | # Checks to see if a section filter was applied 204 | # If so, checks to see if this section should be reported 205 | if !$config['plex']['sections'].nil? 206 | if !$config['plex']['sections'].include?(element['title']) 207 | break 208 | end 209 | end 210 | 211 | library = plex.get("/library/sections/#{element['key']}/all") 212 | 213 | begin 214 | library['MediaContainer']['Directory'].each do | element | 215 | tv_episodes = self.getTVInfo(element, tv_episodes) 216 | end 217 | rescue 218 | $logger.error("Something wrong with section #{element['librarySectionTitle']}. Is it empty?") 219 | end 220 | end 221 | end 222 | 223 | tv_episodes[:new].sort_by! { |hsh| hsh[:series_name] } 224 | 225 | begin 226 | tv_episodes[:seasons].sort_by! { |hsh| hsh[:series_name] } 227 | rescue 228 | $logger.error("Error in sorting TV seasons") 229 | end 230 | return tv_episodes 231 | end 232 | 233 | 234 | # For a given TV show, determine if thre are new episodes and/or seasons, and adds them approprately 235 | # Parameters: 236 | # tv_show: Plex TV show object from 'library/sections//all' 237 | # tv_episodes: Array of Hashes of all episodes and seasons 238 | def getTVInfo(tv_show, tv_episodes) 239 | thetvdb = TheTVDB.new 240 | plex = Plex.new($config) 241 | language = $config['email']['language'].nil? ? "en" : $config['email']['language'] 242 | 243 | begin 244 | $logger.debug(plex.get("/library/metadata/#{tv_show['ratingKey']}")) 245 | last_updated = plex.get("/library/metadata/#{tv_show['ratingKey']}")['MediaContainer']['Directory']['updatedAt'].to_i 246 | if (Time.now.to_i - last_updated < 604800) 247 | 248 | # This is some contrivulted logic to strip off the moviedb.org id 249 | # from the Plex mediadata. I wish Plex made this information 250 | # easier to get 251 | if plex.get("/library/metadata/#{tv_show['ratingKey']}")['MediaContainer']['Directory']['guid'].include?("thetvdb:") 252 | show_id = plex.get("/library/metadata/#{tv_show['ratingKey']}")['MediaContainer']['Directory']['guid'].gsub(/com.plexapp.agents.thetvdb:\/\//, '').gsub(/\?lang.*/, '') 253 | else 254 | $logger.error("TV Show #{tv_show['title']} using incompatiable agent") 255 | return tv_episodes 256 | end 257 | 258 | begin 259 | show = thetvdb.get("series/#{show_id}/all/#{language}.xml")['Data'] 260 | episodes = show['Episode'].sort_by { |hsh| hsh[:FirstAired] }.reverse! 261 | rescue 262 | $logger.error("Connection to thetvdb.com failed while retrieving info for #{tv_show['title']}") 263 | return tv_episodes 264 | end 265 | 266 | episodes.each do | episode | 267 | airdate = nil 268 | begin 269 | airdate_date = Date.parse(episode['FirstAired']) 270 | rescue 271 | end 272 | 273 | if !airdate_date.nil? 274 | if ((Date.parse(Time.now.to_s) - airdate_date).round < 8 && 275 | (Date.parse(Time.now.to_s) - airdate_date).round > 0) 276 | #if !tv_episodes[:new].any? {|h| h[:id] == show_id} 277 | series = plex.get("/library/metadata/#{tv_show['ratingKey']}/allLeaves")['MediaContainer']['Video'] 278 | series.each do | plex_episode | 279 | if (episode['EpisodeNumber'] == plex_episode['index'] && episode['SeasonNumber'] == plex_episode['parentIndex']) 280 | $logger.info("Reporting #{show['Series']['SeriesName']} Season #{episode['SeasonNumber']} Episode #{episode['EpisodeNumber']}") 281 | tv_episodes[:new].push({ 282 | :id => show_id, 283 | :series_name => show['Series']['SeriesName'], 284 | :image => "http://thetvdb.com/banners/#{show['Series']['poster']}", 285 | :network => show['Series']['Network'], 286 | :imdb => "http://www.imdb.com/title/#{show['Series']['IMDB_ID']}", 287 | :title => episode['EpisodeName'], 288 | :episode_number => "S#{episode['SeasonNumber']} E#{episode['EpisodeNumber']}", 289 | :synopsis => episode['Overview'], 290 | :airdate => episode['FirstAired'] 291 | }) 292 | end 293 | end 294 | #end 295 | elsif ((Date.parse(Time.now.to_s) - Date.parse(Time.at(last_updated).to_s)).round < 7) 296 | season_mapping = Hash.new 297 | dvd_season_mapping = Hash.new 298 | show['Episode'].each do | episode_count | 299 | season_mapping[episode_count['SeasonNumber']] = episode_count['EpisodeNumber'] 300 | end 301 | show['Episode'].each do | episode_count | 302 | if !episode_count['DVD_episodenumber'].nil? 303 | dvd_season_mapping[episode_count['SeasonNumber']] = episode_count['DVD_episodenumber'].to_i 304 | end 305 | end 306 | 307 | seasons = plex.get("/library/metadata/#{tv_show['ratingKey']}/children")['MediaContainer'] 308 | if seasons['Directory'].size > 1 309 | seasons = seasons['Directory'] 310 | end 311 | 312 | seasons.each do | season | 313 | if season.is_a?(Array) 314 | season = seasons 315 | end 316 | if (Time.now.to_i - season['addedAt'].to_i < 604800) 317 | if (season_mapping[season['index']].to_i == season['leafCount'].to_i || 318 | dvd_season_mapping[season['index']].to_i == season['leafCount'].to_i ) 319 | if tv_episodes[:seasons].detect { |f| f[:id].to_i == show_id.to_i } 320 | tv_episodes[:seasons].each do |x| 321 | if x[:id] == show_id 322 | if !x[:season].include? season['index'] 323 | $logger.info("Reporting #{show['Series']['SeriesName']} Season #{[season['index']]}") 324 | x[:season].push(season['index']) 325 | end 326 | end 327 | end 328 | else 329 | $logger.info("Reporting #{show['Series']['SeriesName']} Season #{[season['index']]}") 330 | tv_episodes[:seasons].push({ 331 | :id => show_id, 332 | :series_name => show['Series']['SeriesName'], 333 | :image => "http://thetvdb.com/banners/#{show['Series']['poster']}", 334 | :season => [season['index']], 335 | :network => show['Series']['Network'], 336 | :imdb => "http://www.imdb.com/title/#{show['Series']['IMDB_ID']}", 337 | :synopsis => show['Series']['Overview'] 338 | }) 339 | end 340 | end 341 | end 342 | end 343 | end 344 | end 345 | end 346 | end 347 | rescue Exception => e 348 | $logger.error("Something failed. If you are seeing this, please turn on debugging and open an issue.") 349 | $logger.debug(tv_show) 350 | $logger.debug(e) 351 | end 352 | return tv_episodes 353 | end 354 | end 355 | 356 | # Main method that starts the report 357 | def main 358 | startTime = Time.now 359 | report = PlexReport.new 360 | 361 | I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) 362 | I18n.load_path = Dir['/var/lib/plexReport/locales/*.yml'] 363 | I18n.backend.load_translations 364 | I18n.locale = $config['email']['language'].nil? ? 'en' : $config['email']['language'] 365 | 366 | movies = report.getMovies 367 | new_episodes = report.getTVEpisodes 368 | 369 | new_seasons = new_episodes[:seasons] 370 | new_episodes = new_episodes[:new] 371 | 372 | YAML.load_file('/etc/plexReport/config.yaml') 373 | template = ERB.new File.new("/etc/plexReport/email_body.erb").read, nil, "%" 374 | mail = MailReport.new($config, $options) 375 | 376 | if (movies.empty? && new_seasons.empty? && new_episodes.empty?) 377 | $logger.info('No new media to report!') 378 | exit 379 | end 380 | 381 | mail.sendMail(template.result(binding)) 382 | 383 | $logger.info("Script complete. Ran in #{Time.now - startTime} seconds") 384 | end 385 | main() 386 | -------------------------------------------------------------------------------- /bin/plexreport-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | require 'highline/import' 6 | 7 | require_relative '/var/lib/plexReport/plexTv' 8 | 9 | # Class to setup PlexReport 10 | # 11 | # Author: Brian Stascavage 12 | # Email: brian@stascavage.com 13 | # 14 | class Setup 15 | include HTTParty 16 | 17 | def initialize 18 | begin 19 | $config = Hash.new 20 | # $config = YAML.load_file(File.join(File.expand_path(File.dirname(__FILE__)), '../etc/config.yaml') ) 21 | rescue Errno::ENOENT => e 22 | abort('Configuration file not found. Exiting...') 23 | end 24 | 25 | $config = { 'email' => 26 | { 'title' => '' }, 27 | 'plex' => 28 | { 'server' => '', 29 | 'api_key' => '' }, 30 | 'mail' => 31 | { 'address' => '', 32 | 'port' => '', 33 | 'username' => '', 34 | 'password' => '', 35 | 'from' => '', 36 | 'subject' => '' } 37 | } 38 | $plex = PlexTv.new($config) 39 | end 40 | 41 | def setPlexApiKey 42 | username = ask("Enter your Plex username:") { |q| q.echo = true } 43 | password = ask("Enter your Plex Password. NOTE: This will not be saved anywhere") { |q| q.echo = "*" } 44 | 45 | auth = {:username => username, :password => password} 46 | devices = $plex.get("/devices.xml", auth, true) 47 | 48 | devices['MediaContainer']['Device'].each do | device, index | 49 | if device['provides'] == 'server' 50 | puts "Your API key is: #{device['token']}" 51 | $config['plex']['api_key'] = device['token'] 52 | return true 53 | end 54 | 55 | if devices['MediaContainer']['Device'].size - 1 == index 56 | puts "Cannot find Plex Server. Exiting" 57 | abort 58 | end 59 | end 60 | end 61 | 62 | def setServer 63 | $config['plex']['server'] = ask("Enter your Plex server IP (default: localhost)") { |q| q.echo = true } 64 | if $config['plex']['server'].empty? 65 | $config['plex']['server'] = 'localhost' 66 | end 67 | end 68 | 69 | def setEmail 70 | $config['mail']['address'] = ask("Enter your SMTP server (default: smtp.gmail.com)") { |q| q.echo = true } 71 | if $config['mail']['address'].empty? 72 | $config['mail']['address'] = 'smtp.gmail.com' 73 | end 74 | 75 | $config['mail']['port'] = ask("Enter your SMTP port (default: 587)") { |q| q.echo = true } 76 | if $config['mail']['port'].empty? 77 | $config['mail']['port'] = 587 78 | end 79 | 80 | $config['mail']['username'] = ask("Enter your SMTP username/email address (For Gmail, use email address)") { |q| q.echo = true } 81 | $config['mail']['password'] = ask("Enter your email password (This will only be saved in etc/config.yaml)") { |q| q.echo = "*" } 82 | 83 | $config['mail']['from'] = ask("Display name of the sender (default: Plex Server)") { |q| q.echo = true } 84 | if $config['mail']['from'].empty? 85 | $config['mail']['from'] = 'Plex Server' 86 | end 87 | 88 | $config['mail']['subject'] = ask("Email subject (default: Plex Server Summary)") { |q| q.echo = true } 89 | if $config['mail']['subject'].empty? 90 | $config['mail']['subject'] = 'Plex Server Summary' 91 | end 92 | 93 | $config['email']['title'] = ask("Display title in the Email body (default: Plex Server Summary)") { |q| q.echo = true } 94 | if $config['email']['title'].empty? 95 | $config['email']['title'] = 'Plex Server Summary' 96 | end 97 | end 98 | 99 | def start 100 | self.setServer 101 | self.setPlexApiKey 102 | self.setEmail 103 | 104 | File.open('/etc/plexReport/config.yaml', 'w') {|f| f.write $config.to_yaml } 105 | puts "Writing information to /etc/plexReport/config.yaml" 106 | end 107 | end 108 | 109 | setup_agent = Setup.new 110 | setup_agent.start 111 | -------------------------------------------------------------------------------- /etc/config.yaml.example: -------------------------------------------------------------------------------- 1 | --- 2 | email: 3 | title: 'Default Email Header' 4 | langauge: 'en' 5 | plex: 6 | server: 7 | api_key: 8 | mail: 9 | address: 10 | port: 25 11 | username: 12 | password: 13 | from: 14 | subject: 15 | recipients_email: ['TEST1@EMAIL.COM', 'TEST2@EMAIL.COM'] 16 | recipients: ['PLEX_USER'] 17 | -------------------------------------------------------------------------------- /etc/email_body.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 333 | 450 |
334 |
335 | 336 | 350 |
337 |
338 | 339 | 348 |
340 | 341 | 343 | 346 | 347 |
342 |

344 | 345 |
349 |
448 |
351 | 352 | 363 | 364 | 365 | <% new_episodes.each do |episode| %> 366 |
353 | 354 | 361 | 362 |
355 |

<%= $config['email']['title'] %>

356 |

<%= I18n.l Time.now.to_date, format: :long %>

357 |
358 | <% if new_episodes != [] %> 359 |

<%= I18n.t :new_episodes %>:

360 |
371 | 382 |
367 | 369 | 370 |
368 |
372 | 373 | 380 | 381 |
374 |
<%= episode[:series_name] %>
375 |

<%= episode[:episode_number] %> - <%= episode[:title] %>

376 |

<%= episode[:synopsis] %>

377 |

<%= I18n.t :network %>: <%= episode[:network] %>

378 |

<%= I18n.t :air_date %>: <%= episode[:airdate] %>

379 |
383 | <% end %> 384 | <% end %> 385 | 386 |
387 | <% if new_seasons != [] %> 388 |

<%= I18n.t :new_seasons %>:

389 | <% new_seasons.each do |season| %> 390 |
395 | 405 |
391 | 393 | 394 |
392 |
396 | 397 | 403 | 404 |
398 |
<%= season[:series_name] %>
399 |

<%= I18n.t :seasons, count: season[:season].length %><%= season[:season].min %>-<%= season[:season].max %>

400 |

<%= season[:synopsis] %>

401 |

<%= I18n.t :network %>: <%= season[:network] %>

402 |
406 | <% end %> 407 | <% end %> 408 | 409 |
410 | <% if movies != [] %> 411 |

<%= I18n.t :new_movies %>:

412 | 413 | <% movies.each do |movie| %> 414 |
419 | 436 |
415 | 417 | 418 |
416 |
420 | 421 | 434 | 435 |
422 |
<%= movie[:title] %> (<%= movie[:date] %>)
423 |

<%= movie[:tagline] %>

424 | <% if $options[:detail_email] %> 425 |

<%= I18n.t :genre %>: <%= movie[:genre] %>
<%= I18n.t :director %>: <%= movie[:director] %>

<%= I18n.t :cast %>: <%= movie[:actors] %>

426 | <% end %> 427 |

<%= movie[:synopsis] %>

428 | <% if $options[:detail_email] %> 429 |

<%= I18n.t :runtime %>: <%= movie[:runtime] %> <%= I18n.t :minutes %>
<%= I18n.t :release_date %>: <%= movie[:released] %>

<%= I18n.t :rating %>: <%= movie[:rating] %>

<%= I18n.t :imdb_rating %>: <%= movie[:imdb_rating] %>/10 <%= I18n.t :from %> <%= movie[:imdb_votes] %> <%= I18n.t :users %>

430 | <% else %> 431 |

<%= I18n.t :runtime %>: <%= movie[:runtime] %> <%= I18n.t :minutes %>

432 | <% end %> 433 |
447 |
437 | <% end %> 438 | <% end %> 439 | 440 | 445 | 446 |
441 |
442 |

<%= I18n.t :thanks_sentence %>

443 |
444 |
449 |
451 | 455 | 456 | 457 | -------------------------------------------------------------------------------- /images/plex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bstascavage/plexReport/8d668b36dacf270ce98c1d58fc8a2fc205011e51/images/plex.png -------------------------------------------------------------------------------- /initial_setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Bash script that copies plexreport files to various directories 3 | # and walks the user through the initial setup 4 | # 5 | 6 | PLEX_REPORT_LIB='/var/lib/plexReport' 7 | PLEX_REPORT_CONF='/etc/plexReport' 8 | 9 | /bin/echo "Creating plexreport library at /var/lib/plexReport" 10 | /bin/mkdir -p $PLEX_REPORT_LIB 11 | /bin/echo "Creating plexreport conf directory at /etc/plexReport" 12 | /bin/mkdir -p $PLEX_REPORT_CONF 13 | 14 | /bin/echo "Moving plexreport and plexreport-setup to /usr/local/sbin" 15 | /bin/cp -r bin/* /usr/local/sbin 16 | /bin/echo "Moving plexreport libraries to /var/lib/plexreport" 17 | /bin/cp -r lib/* $PLEX_REPORT_LIB 18 | /bin/echo "Moving email_body.erb to /etc/plexreport" 19 | /bin/cp -r etc/* $PLEX_REPORT_CONF 20 | 21 | /bin/echo "Creating /etc/plexreport/config.yaml" 22 | /usr/bin/touch /etc/plexReport/config.yaml 23 | /bin/echo "Creating /var/log/plexReport.log" 24 | /usr/bin/touch /var/log/plexReport.log 25 | 26 | /bin/echo "Installing ruby gem dependency" 27 | GEM_BINARY=$(which gem) 28 | $GEM_BINARY install bundler 29 | /usr/local/bin/bundle install 30 | 31 | /bin/echo "Running /usr/local/sbin/plexreport-setup" 32 | /usr/local/sbin/plexreport-setup 33 | 34 | /bin/echo "What day do you want to run the script on? (Put 0 for Sunday, 1 for Monday, etc...)" 35 | read CRON_DAY 36 | /bin/echo "What hour should the script run? (00-23)" 37 | read CRON_HOUR 38 | /bin/echo "What minute in that hour should the script run? (00-59)" 39 | read CRON_MINUTE 40 | 41 | /bin/echo "Adding /usr/local/sbin/plexreport to crontab" 42 | /usr/bin/crontab -l > mycron 43 | /bin/echo "$CRON_MINUTE $CRON_HOUR * * $CRON_DAY /usr/local/sbin/plexreport" >> mycron 44 | /usr/bin/crontab mycron 45 | /bin/rm mycron 46 | 47 | /bin/echo "Setup complete!" 48 | -------------------------------------------------------------------------------- /lib/locales/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | air_date: "Sendedatum" 3 | cast: "Cast" 4 | credits_sentence: "Alle medialen Inhalte, Zusammenfassungen und Metadaten wurden von themoviedb.org und thetvdb.com bereitgestellt" 5 | date: 6 | abbr_day_names: 7 | - So 8 | - Mo 9 | - Di 10 | - Mi 11 | - Do 12 | - Fr 13 | - Sa 14 | abbr_month_names: 15 | - 16 | - Jan 17 | - Feb 18 | - Mär 19 | - Apr 20 | - Mai 21 | - Jun 22 | - Jul 23 | - Aug 24 | - Sep 25 | - Okt 26 | - Nov 27 | - Dez 28 | day_names: 29 | - Sonntag 30 | - Montag 31 | - Dienstag 32 | - Mittwoch 33 | - Donnerstag 34 | - Freitag 35 | - Samstag 36 | formats: 37 | default: "%d.%m.%Y" 38 | long: "%e. %B %Y" 39 | short: "%e. %b" 40 | month_names: 41 | - 42 | - Januar 43 | - Februar 44 | - März 45 | - April 46 | - Mai 47 | - Juni 48 | - Juli 49 | - August 50 | - September 51 | - Oktober 52 | - November 53 | - Dezember 54 | order: 55 | - :day 56 | - :month 57 | - :year 58 | director: "Regie" 59 | from: "für" 60 | genre: "Genre" 61 | help_page_sentence: "Ein Problem? Diese Seite gefällt Ihnen? Sie möchten helfen? Dann schauen Sie doch einmal auf meiner github-Seite vorbei!" 62 | imdb_rating: "IMDB-Rating" 63 | minutes: "Minuten" 64 | network: "Sender" 65 | new_episodes: "Neue Episoden" 66 | new_movies: "Neue Filme" 67 | new_seasons: "Neue Staffeln" 68 | rating: "Note" 69 | release_date: "Erscheinungsdatum" 70 | runtime: "Dauer" 71 | seasons: { 72 | one: "Staffel", 73 | other: "Staffeln" 74 | } 75 | thanks_sentence: "Das ist alles, Leute - vielen Dank für's Lesen!" 76 | users: "Benutzer" 77 | -------------------------------------------------------------------------------- /lib/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | air_date: "Air date" 3 | cast: "Cast" 4 | credits_sentence: "All art, summaries, and metadata is provided by themoviedb.org and thetvdb.com" 5 | date: 6 | abbr_day_names: 7 | - Sun 8 | - Mon 9 | - Tue 10 | - Wed 11 | - Thu 12 | - Fri 13 | - Sat 14 | abbr_month_names: 15 | - 16 | - Jan 17 | - Feb 18 | - Mar 19 | - Apr 20 | - May 21 | - Jun 22 | - Jul 23 | - Aug 24 | - Sep 25 | - Oct 26 | - Nov 27 | - Dec 28 | day_names: 29 | - Sunday 30 | - Monday 31 | - Tuesday 32 | - Wednesday 33 | - Thursday 34 | - Friday 35 | - Saturday 36 | formats: 37 | default: "%m-%d-%Y" 38 | long: "%B %d, %Y" 39 | short: "%b %d" 40 | month_names: 41 | - 42 | - January 43 | - February 44 | - March 45 | - April 46 | - May 47 | - June 48 | - July 49 | - August 50 | - September 51 | - October 52 | - November 53 | - December 54 | order: 55 | - :month 56 | - :day 57 | - :year 58 | director: "Director" 59 | from: "from" 60 | genre: "Genre" 61 | help_page_sentence: "Have an issue? Like what you see? Want to help? Then please check out my github page" 62 | imdb_rating: "IMDB Rating" 63 | minutes: "minutes" 64 | network: "Network" 65 | new_episodes: "New Episodes" 66 | new_movies: "New Movies" 67 | new_seasons: "New TV Seasons" 68 | rating: "Rating" 69 | release_date: "Release Date" 70 | runtime: "Runtime" 71 | seasons: { 72 | one: "season", 73 | other: "seasons" 74 | } 75 | thanks_sentence: "That's all, folks! Thanks for reading!" 76 | users: "users" 77 | -------------------------------------------------------------------------------- /lib/locales/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | air_date: "Date de diffusion" 3 | cast: "Casting" 4 | credits_sentence: "Les affiches, résumés et méta-données sont fournies par themoviedb.org et par thetvdb.com" 5 | date: 6 | abbr_day_names: 7 | - dim 8 | - lun 9 | - mar 10 | - mer 11 | - jeu 12 | - ven 13 | - sam 14 | abbr_month_names: 15 | - 16 | - jan. 17 | - fév. 18 | - mar. 19 | - avr. 20 | - mai 21 | - juin 22 | - juil. 23 | - août 24 | - sept. 25 | - oct. 26 | - nov. 27 | - déc. 28 | day_names: 29 | - dimanche 30 | - lundi 31 | - mardi 32 | - mercredi 33 | - jeudi 34 | - vendredi 35 | - samedi 36 | formats: 37 | default: "%d/%m/%Y" 38 | short: "%e %b" 39 | long: "%e %B %Y" 40 | month_names: 41 | - 42 | - janvier 43 | - février 44 | - mars 45 | - avril 46 | - mai 47 | - juin 48 | - juillet 49 | - août 50 | - septembre 51 | - octobre 52 | - novembre 53 | - décembre 54 | order: 55 | - :day 56 | - :month 57 | - :year 58 | director: "Réalisateur" 59 | from: "pour" 60 | genre: "Genre" 61 | help_page_sentence: "Vous avez un problème ? Vous aimez ? Vous voulez aider ? Venez visiter la page github du projet" 62 | imdb_rating: "Note IMDB" 63 | minutes: "minutes" 64 | network: "Chaine" 65 | new_episodes: "Nouveaux épisodes" 66 | new_movies: "Nouveaux films" 67 | new_seasons: "Nouvelles saisons" 68 | rating: "Classification" 69 | release_date: "Date de sortie" 70 | runtime: "Durée" 71 | seasons: { 72 | one: "saison", 73 | other: "saisons" 74 | } 75 | thanks_sentence: "C'est tout, pour le moment. Merci pour votre attention." 76 | users: "utilisateurs" 77 | -------------------------------------------------------------------------------- /lib/mailReport.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'mail' 4 | require 'time' 5 | 6 | require_relative '/var/lib/plexReport/plexTv' 7 | 8 | # Class for sending out the email notification. 9 | # 10 | # Author: Brian Stascavage 11 | # Email: brian@stascavage.com 12 | # 13 | class MailReport 14 | def initialize(config, options) 15 | $config = config 16 | $plexEmails = options[:emails] 17 | $testEmail = options[:test_email] 18 | if !$config['mail']['port'].nil? 19 | $port = $config['mail']['port'] 20 | else 21 | $port = 25 22 | end 23 | 24 | if !$config['mail']['subject'].nil? 25 | $subject = $config['mail']['subject'] 26 | else 27 | $subject = "Plex Summary " 28 | end 29 | end 30 | 31 | # Method for pulling the email information from the config and emailing all Plex users 32 | def sendMail(body) 33 | options = { :address => $config['mail']['address'], 34 | :port => $port, 35 | :domain => 'otherdomain.com', 36 | :user_name => $config['mail']['username'], 37 | :password => $config['mail']['password'], 38 | :authentication => 'plain', 39 | :enable_starttls_auto => true } 40 | Mail.defaults do 41 | delivery_method :smtp, options 42 | end 43 | 44 | users = Array.new 45 | 46 | # Logic for pulling the email accounts from Plex.tv and/or the 47 | # config file 48 | plexTv = PlexTv.new($config) 49 | 50 | if !$testEmail 51 | if $plexEmails 52 | plex_users = plexTv.get('/pms/friends/all') 53 | 54 | if plex_users.nil? || plex_users.empty? 55 | $logger.info("No Plex friends found.") 56 | else 57 | plex_users['MediaContainer']['User'].each do | user | 58 | if !user['email'].empty? 59 | users.push(user['email']) 60 | end 61 | end 62 | end 63 | end 64 | if !$config['mail']['recipients'].nil? || !$config['mail']['recipients_email'].nil? 65 | if !$config['mail']['recipients_email'].nil? 66 | $config['mail']['recipients_email'].each do | recipient | 67 | users.push(recipient) 68 | end 69 | end 70 | if !$config['mail']['recipients'].nil? 71 | $config['mail']['recipients'].each do | recipient | 72 | plex_users = plexTv.get('/pms/friends/all') 73 | plex_users['MediaContainer']['User'].each do | user | 74 | if user['username'] == recipient 75 | users.push(user['email']) 76 | end 77 | end 78 | end 79 | end 80 | end 81 | end 82 | 83 | #Get owner's email as well and add it to the list of recpients 84 | users.push(plexTv.get('/users/account')['user']['email'][0]) 85 | 86 | users.each do | user | 87 | mail = Mail.new do 88 | from "#{$config['mail']['from']} <#{$config['mail']['username']}>" 89 | to user 90 | subject $config['mail']['subject'] + " " + (I18n.l Time.now.to_date) 91 | content_type 'text/html; charset=UTF-8' 92 | body body 93 | end 94 | 95 | mail.deliver! 96 | end 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/omdb.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | 6 | # Class that interacts with omdbapi.com. 7 | # 8 | # Author: Brian Stascavage 9 | # Email: brian@stascavage.com 10 | # 11 | class OMDB 12 | include HTTParty 13 | 14 | base_uri 'http://www.omdbapi.com//' 15 | format :json 16 | 17 | def initialize 18 | end 19 | 20 | def get(query, args=nil) 21 | new_query = '?i=' + query + '&plot=short&r=json' 22 | 23 | response = self.class.get(new_query, :verify => false) 24 | 25 | if response.code != 200 26 | if response.nil? 27 | return 'nil' 28 | end 29 | while retry_attempts < 3 do 30 | $logger.error("Could not connect to omdb. Will retry in 30 seconds") 31 | sleep(30) 32 | $retry_attempts += 1 33 | $logger.debug("Retry attempt: #{$retry_attempts}") 34 | if self.get(query).code == 200 35 | break 36 | end 37 | end 38 | if retry_attempts >= 3 39 | $logger.error "Could not connect to omdb. Exiting script." 40 | exit 41 | end 42 | end 43 | return response 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/plex.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | 6 | # Class To interact with a Plex server, for pulling movie and TV info and stuff 7 | # 8 | # Author: Brian Stascavage 9 | # Email: brian@stascavage.com 10 | # 11 | class Plex 12 | include HTTParty 13 | 14 | def initialize(config) 15 | $config = config 16 | $header = { "X-Plex-Token" => "#{$config['plex']['api_key']}" } 17 | 18 | self.class.headers['X-Plen-Token'] = $config['plex']['api_key'] 19 | if !$config['plex']['server'].nil? 20 | self.class.base_uri "http://#{$config['plex']['server']}:32400/" 21 | end 22 | end 23 | 24 | base_uri "http://localhost:32400/" 25 | format :xml 26 | 27 | def get(query, args=nil) 28 | self.class.headers['X-Plex-Token'] = $config['plex']['api_key'] 29 | response = self.class.get(query) 30 | 31 | if response.code != 200 32 | if response.code == 401 33 | $logger.error("Unauthorized access to Plex server") 34 | else 35 | $logger.error("Cannot connect to Plex server") 36 | end 37 | 38 | abort 39 | end 40 | 41 | $logger.debug("Debug info for plexmediaserver connection") 42 | $logger.debug(response.code) 43 | $logger.debug(response.request) 44 | $logger.debug(response) 45 | return response 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/plexTv.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | 6 | # Class To interact with Plex.tv 7 | # 8 | # Author: Brian Stascavage 9 | # Email: brian@stascavage.com 10 | # 11 | class PlexTv 12 | include HTTParty 13 | 14 | base_uri 'http://plex.tv/' 15 | format :xml 16 | 17 | def initialize(config) 18 | if !config.empty? 19 | if !config['plex']['api_key'].empty? 20 | $token = config['plex']['api_key'] 21 | else 22 | if defined? $logger 23 | $logger.error("Missing Plex token") 24 | end 25 | end 26 | end 27 | end 28 | 29 | def get(query, auth=nil, token_check=false) 30 | if !token_check 31 | new_query = query + "?X-Plex-Token=#{$token}" 32 | else 33 | new_query = query 34 | end 35 | 36 | if auth.nil? 37 | response = self.class.get(new_query) 38 | else 39 | response = self.class.get(new_query, :basic_auth => auth) 40 | end 41 | 42 | if response.code != 200 43 | if response.code == 401 44 | puts "Invalid plex.tv credentials" 45 | abort 46 | else 47 | puts "Cannot connect to plex.tv! Change your connection." 48 | abort 49 | end 50 | end 51 | return response 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/themoviedb.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | 6 | # Class that interacts with themoviedb.org. 7 | # Note that themoviedb.org limits API calls to 30 every 10 seconds, 8 | # hence the sleep in this code. 9 | # 10 | # Author: Brian Stascavage 11 | # Email: brian@stascavage.com 12 | # 13 | class TheMovieDB 14 | include HTTParty 15 | 16 | base_uri 'https://api.themoviedb.org/3//' 17 | format :json 18 | 19 | def initialize(config) 20 | $token = '974eddb0f95ce2b912b9b37a63358823' 21 | $retry_attempt = 0 22 | end 23 | 24 | def get(query, args=nil) 25 | if args.nil? 26 | new_query = query + "?api_key=#{$token}" 27 | else 28 | new_query = query + "?api_key=#{$token}&#{args}" 29 | end 30 | 31 | response = self.class.get(new_query, :verify => false) 32 | 33 | if response.code != 200 34 | if response.nil? 35 | return 'nil' 36 | end 37 | while $retry_attempts < 3 do 38 | $logger.error("Could not connect to themoviedb.org. Will retry in 30 seconds") 39 | sleep(30) 40 | $retry_attempts += 1 41 | $logger.debug("Retry attempt: #{$retry_attempts}") 42 | if self.get(query).code == 200 43 | break 44 | end 45 | end 46 | if $retry_attempts >= 3 47 | $logger.error("Could not connect to themoviedb.org. Exiting script") 48 | exit 49 | end 50 | end 51 | 52 | sleep 0.6 53 | $retry_attempt = 0 54 | return response 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/thetvdb.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | require 'rubygems' 3 | require 'json' 4 | require 'httparty' 5 | 6 | # Class that interacts with thetvdb.org. 7 | # 8 | # Author: Brian Stascavage 9 | # Email: brian@stascavage.com 10 | # 11 | class TheTVDB 12 | include HTTParty 13 | 14 | token = '71362BFFDCA2C8CD' 15 | base_uri "http://thetvdb.com/api/#{token}//" 16 | 17 | def initialize 18 | $retry_attempts = 0 19 | end 20 | 21 | def get(query, args=nil) 22 | begin 23 | response = self.class.get(query, :verify => false) 24 | rescue EOFError 25 | $logger.error("thetvdb.org is providing wrong headers. Blah! Retrying.") 26 | while $retry_attempts < 3 do 27 | $logger.error("Could not connect to thetvdb.com. Will retry in 30 seconds") 28 | sleep(30) 29 | $retry_attempts += 1 30 | $logger.debug("Retry attempt: #{$retry_attempts}i for query #{query}") 31 | if self.get(query).code == 200 32 | break 33 | end 34 | end 35 | if $retry_attempts >= 5 36 | $logger.error("Could not connect to thetvdb. Exiting script. If you are constantly seeing this, please turn on debugging and open an issue.") 37 | $logger.debug("Failed to connect to thetvdb for query: #{query}") 38 | exit 39 | end 40 | 41 | $retry_attempts = 0 42 | return nil 43 | end 44 | $logger.debug("Response from thetvdb for query #{query}: Code: #{response.code}.") 45 | 46 | if response.code != 200 47 | if response.nil? 48 | return 'nil' 49 | end 50 | while $retry_attempts < 3 do 51 | $logger.error("Could not connect to thetvdb.com. Will retry in 30 seconds") 52 | sleep(30) 53 | $retry_attempts += 1 54 | $logger.debug("Retry attempt: #{$retry_attempts} for query #{query}") 55 | if self.get(query).code == 200 56 | break 57 | end 58 | end 59 | if $retry_attempts >= 5 60 | $logger.error("Could not connect to thetvdb. Exiting script. If you are constantly seeing this, please turn on debugging and open an issue.") 61 | $logger.debug("Failed to connect to thetvdb for query: #{query}") 62 | exit 63 | end 64 | end 65 | 66 | $retry_attempts = 0 67 | return response 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash script to pull the newest code from Github and copy it to the correct locations 3 | PLEX_REPORT_LIB='/var/lib/plexReport' 4 | PLEX_REPORT_CONF='/etc/plexReport' 5 | 6 | /bin/echo "Grabbing newest code from https://github.com/bstascavage/plexReport" 7 | /usr/bin/git pull 8 | 9 | /bin/echo "Moving plexreport and plexreport-setup to /usr/local/sbin" 10 | /bin/cp -r bin/* /usr/local/sbin 11 | /bin/echo "Moving plexreport libraries to /var/lib/plexReport" 12 | /bin/cp -r lib/* $PLEX_REPORT_LIB 13 | /bin/echo "Moving email_body.erb to /etc/plexReport" 14 | /bin/cp -r etc/* $PLEX_REPORT_CONF 15 | 16 | /bin/echo "Installing ruby gem dependency" 17 | /usr/bin/gem install bundler 18 | /usr/local/bin/bundle install 19 | 20 | /bin/echo "Upgrade complete" 21 | --------------------------------------------------------------------------------