download_tv 2.6.2 → 2.6.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29c9837fef84c38a41063a8526525e12ce56c82bd8c8467289401dd8ae5453ba
4
- data.tar.gz: c448ce24115b3cb19dcc128c56a47cdee61d072994dafcfe5ab3d53b5d799109
3
+ metadata.gz: '09d470071b18c6859d55874249141ae57bfc68b538fc8a5e5ffb3ba27dfb9d89'
4
+ data.tar.gz: '08fa4240f9f2ab5fe00fbe5509932b9a05d4c5e7254da38aaa249ecee3c60dce'
5
5
  SHA512:
6
- metadata.gz: a00092c93cc8076bf41d2a43a198f16be217ef251f74586387f92303e2db9baf0db8008f09271a7f086788578368dec2a881429136caf0d9c71d4fc2ff00be22
7
- data.tar.gz: b79f9e1625c27bd2c3f2c6c33b8092dcd0c1fb8c29a4e0f950619d0484d20d7fa175398e5d9e67cc6e8e7c268f137715e3c7e04e1c5c1e323c45d436a084eb4c
6
+ metadata.gz: 9a0f0390cf1f4d74f65a41e4704bca3d618043b6e72ad0a02716e5121276966016d60e9323f8392d77cb4bf07c1abb6289372d95214f575b9a7da3d620b5f993
7
+ data.tar.gz: 9271b796d80b9d0519699ca5f9acc0d26b88f190798474ca2128077324781df7f4205fffc4345f7d225b00635071177ca118d26ae0aacff2fc02e5174c3496e3
data/CHANGELOG.md ADDED
@@ -0,0 +1,214 @@
1
+ # download_tv CHANGELOG
2
+
3
+ ## 2.6.6 (2022-01-21)
4
+
5
+ * Improvements
6
+ * The `--dry-run` option now prevents from persisting any configuration, including pending shows, not just the last execution date.
7
+ * Performance improvements when running with the `-t` flag.
8
+
9
+ ## 2.6.5 (2021-06-10)
10
+
11
+ * Fixes
12
+ * Bump HTTP read timeout to avoid errors on new grabber.
13
+
14
+ ## 2.6.4 (2021-06-07)
15
+
16
+ * Grabbers
17
+ * Torrentz: added Torrentz2 grabber.
18
+
19
+ ## 2.6.3 (2021-05-24)
20
+
21
+ * Fixes
22
+ * Fix download full season feature (`-s/--season`), inadvertently broken in 2.6.2.
23
+
24
+ ## 2.6.2 (2021-05-20)
25
+
26
+ * Fixes
27
+ * Avoid duplicate downloads when using `-t` and `-o` together.
28
+
29
+ * Improvements
30
+ * Add `-s` shorthand to the `--season` flag.
31
+
32
+ ## 2.6.1 (2020-09-22)
33
+
34
+ * Features
35
+ * Add `-q/--queue` to manually add an episode to the pending list.
36
+
37
+ * Improvements
38
+ * Gracefully exits after option parsing errors.
39
+
40
+ * Grabbers
41
+ * EZTV: now sorts torrents by number of seeders.
42
+ * ThePirateBay: disable grabber.
43
+
44
+ ## 2.5.5 (2019-04-06)
45
+
46
+ * Features
47
+ * Allow user to configure include/exclude filters of the results.
48
+
49
+ * Improvements
50
+ * The `-t/--tomorrow` flag now also performs a normal run if needed.
51
+
52
+ ## 2.5.4 (2019-01-19)
53
+
54
+ * Features
55
+ * Add `--season` to try and sequentially download all episodes of the given show, for the given season.
56
+ * Add `-t/--tomorrow` to download the shows airing in the current day.
57
+
58
+ ## 2.5.3 (2018-12-14)
59
+
60
+ * Fixes
61
+ * Fix bug preventing clearing pending shows from working properly.
62
+
63
+ ## 2.5.2 (2018-12-10)
64
+
65
+ * Fixes
66
+ * Changing the configuration no longer resets the list of pending downloads.
67
+
68
+ ## 2.5.1 (2018-12-03)
69
+
70
+ * Fixes
71
+ * Fix pending shows handling.
72
+
73
+ ## 2.5.0 (2018-12-02)
74
+
75
+ * Fixes
76
+ * Fix not detecting successful MyEpisodes login.
77
+ * Fix not detecting non-backwards compatible version changes.
78
+ * Fix names not being sanitised when downloading through `-d/--download`
79
+ * Fix names not being sanitised when downloading through `-f/--file`
80
+
81
+ * Features
82
+ * Persist list of episodes not found in the configuration.
83
+ * Add `-p/--pending` to show the list of pending downloads.
84
+ * Add `--clear-pending` to empty the list of pending downloads.
85
+
86
+ * Grabbers
87
+ * KAT: disable grabber.
88
+
89
+ ## 2.4.7 (2018-10-05)
90
+
91
+ * Grabbers
92
+ * KAT: re-enable grabber, updating rules for new CSS structure.
93
+
94
+ ## 2.4.6 (2018-07-19)
95
+
96
+ * Grabbers
97
+ * KAT: disable grabber.
98
+
99
+ ## 2.4.5 (2018-05-04)
100
+
101
+ * Grabbers
102
+ * TorrentAPI: now sorts by seeders.
103
+
104
+ ## 2.4.4 (2018-03-22)
105
+
106
+ * Grabbers
107
+ * TorrentAPI: fix timeouts.
108
+
109
+ ## 2.4.3 (2018-03-22)
110
+
111
+ * Fixes
112
+ * Fix new trackers' availability not being checked before attempting to use them.
113
+
114
+ ## 2.4.2 (2018-03-14)
115
+
116
+ * Fixes
117
+ * Fix bug where the wrong grabber was being removed when offline.
118
+
119
+ ## 2.4.1 (2018-03-12)
120
+
121
+ * Fixes
122
+ * Fix bug accessing wrong variable when a grabber was offline.
123
+
124
+ ## 2.4.0 (2018-03-04)
125
+
126
+ * Fixes
127
+ * Fix not reporting "Nothing to download" when it was due to ignored shows.
128
+ * Fix downloading from file not handling newlines well.
129
+
130
+ * Improvements
131
+ * Reset grabber order after every download.
132
+
133
+ * Grabbers
134
+ * KAT: fix parsing rules.
135
+ * ThePirateBay: change proxy URL.
136
+
137
+ ## 2.3.0 (2017-09-24)
138
+
139
+ * Improvements
140
+ * Store configuration file as JSON instead of Marshaling the hash.
141
+ * Use custom User-Agent for all connections.
142
+
143
+ * Grabbers
144
+ * ThePirateBay: change proxy URL.
145
+
146
+ ## 2.2.2 (2017-08-06)
147
+
148
+ * Fixes
149
+ * Fix date not being saved in the configuration.
150
+
151
+ ## 2.2.1 (2017-08-03)
152
+
153
+ * Add LICENSE.md to repo
154
+
155
+ * Fixes
156
+ * Fix default grabber not being properly selected.
157
+
158
+ * Improvements
159
+ * Add support for OS X.
160
+
161
+ * Grabbers
162
+ * TorrentAPI: add temporary workaround for CloudFlare errors.
163
+
164
+ ## 2.2.0 (2017-08-01)
165
+
166
+ * Add LICENSE information to Gemfile
167
+ * Move default path to configuration file to `~/.config/download_tv/config`
168
+
169
+ * Improvements
170
+ * Improve detection of ignored shows.
171
+
172
+ ## 2.1.1 (2017-07-31)
173
+
174
+ * Improvements
175
+ * Minor improvements to configuration file handling.
176
+
177
+ ## 2.1.0 (2017-07-21)
178
+
179
+ * Features
180
+ * Add `-g/--grabber` to select which grabber to use for finding links.
181
+ * Add `--show-grabbers` to list available options.
182
+ * Add `-v` to print gem version.
183
+
184
+ * Grabbers
185
+ * KAT: added KickAssTorrents grabber.
186
+
187
+ ## 2.0.6 (2017-07-11)
188
+
189
+ * Improvements
190
+ * Remove colons from the show name for searching.
191
+
192
+ ## 2.0.5 (2017-06-17)
193
+
194
+ * Features
195
+ * Add `--show-config` to print contents of the configuration file in a readable way.
196
+
197
+ * Fixes
198
+ * Fix download from file not properly finding the path.
199
+
200
+ ## 2.0.3 (2017-06-07)
201
+
202
+ * Fixes
203
+ * Fix missing arguments breaking the main entrypoint.
204
+ * Fix ignored shows list not handling multiple comma-separated shows.
205
+ * Minor fixes on configuration file.
206
+
207
+ ## 2.0.0 (2017-06-07)
208
+
209
+ * Features
210
+ * Add new configuration system.
211
+
212
+ ## 1.0.0 (2017-06-07)
213
+
214
+ Initial published version.
data/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # download_tv
2
2
 
3
- ![Build Status](https://github.com/guille/download_tv/actions/workflows/ruby.yml/badge.svg)
3
+ [![Ruby](https://github.com/guille/download_tv/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/guille/download_tv/actions/workflows/ruby.yml)
4
4
  [![Gem Version](https://badge.fury.io/rb/download_tv.svg)](https://badge.fury.io/rb/download_tv)
5
5
  [![Code Climate](https://codeclimate.com/github/guille/download_tv.svg)](https://codeclimate.com/github/guille/download_tv)
6
6
 
7
- download_tv is a tool that allows the user to find magnet links for TV show episodes. It accepts shows as arguments, from a file or it can integrate with your MyEpisodes account.
7
+ **download_tv** is a tool that allows the user to find magnet links for TV show episodes. It accepts shows as arguments, from a file or it can integrate with your MyEpisodes account.
8
8
 
9
- ### Installation
9
+ ## Installation
10
10
 
11
11
  `gem install download_tv`
12
12
 
13
- ### Usage
13
+ ## Usage
14
14
 
15
- Once installed, you can launch the binary *tv*
15
+ Once installed, you can launch the binary `tv`
16
16
 
17
17
  ```
18
18
  Usage: tv [options]
@@ -38,50 +38,58 @@ Specific options:
38
38
 
39
39
  ### MyEpisodes integration
40
40
 
41
- By default, download_tv connects to your MyEpisodes.com account and fetches the list of episodes that have aired since the program was run for the last time. It then tries to find magnet links to download each of these shows, using the link grabbers available. You can see the grabbers with the --show-grabbers option. These magnet links will be executed with whatever program you have configured to handle the magnet:// files.
41
+ By default, **download_tv** connects to your [MyEpisodes.com](https://www.myepisodes.com/) account and fetches the list of episodes that have aired since the program was run for the last time. It then tries to find magnet links to download each of these shows, using the link grabbers available. You can see the grabbers with the `--show-grabbers` option. These magnet links will be executed with whatever program you have configured to handle magnet:// files.
42
42
 
43
- The -o flag can be used in order to re-download the episodes from previous days. The --dry-run option is useful to prevent download_tv from updating the date (for example, when running the application shortly after an episode airs).
43
+ The `-o` flag can be used in order to re-download the episodes from previous days. The `--dry-run` option is useful to prevent **download_tv** from updating the date (for example, when running the application shortly after an episode airs).
44
44
 
45
- Starting in version 2.5.4, download_tv includes the --tomorrow flag. By default, an execution of download_tv will download shows airing from the last execution of the program up to a day prior to the current day. Use this flag to include shows airing today in this search. This can be useful depending on your timezone or on the airtime of the shows you follow.
45
+ The application also includes the `-t/--tomorrow` flag. By default, an execution of **download_tv** will download shows airing from the last execution of the program up to a day prior to the current day. This flag can be used to include in the search the episodes airing in the same day. This can be useful depending on your timezone or on the airtime of the shows you follow.
46
46
 
47
47
  **Note**: Due to API limitations, the gem won't find shows aired more than 14 days prior to the execution of the script.
48
48
 
49
- The options -c and --show-config allow the user to change or view the current configuration values, respectively. These options include your myepisodes username, whether to save cookies or ask for password on each run and the list of ignored shows among other things. The configuration files are (mostly) backwards compatible. The gem will force you to change your configuration after an update if there are breaking changes in it.
49
+ The options `-c` and `--show-config` allow the user to change or view the current configuration values, respectively. These options include your MyEpisodes username, whether to save cookies or ask for password on each run and the list of ignored shows among other things. The gem (mostly) follows semver to track configuration file changes. It will automatically trigger a configuration update when it detects an older non-compatible version.
50
50
 
51
- The `auto` flag toggles whether all the results for each show are prompted to the user for him to choose or if the application should try to choose the download link automatically (see Section Filters).
51
+ The `--auto` flag toggles whether all the results for each show are prompted to the user for him to choose or if the application should try to choose the download link automatically (see Section Filters). By default, all grabbers try to sort by number of seeders.
52
52
 
53
53
  ### Single torrent download
54
54
 
55
- In order to download a single episode, use the -d flag, quoting the string when it contains spaces: *tv -d "Breaking Bad S04E01"*
55
+ In order to download a single episode, use the `-d` flag, quoting the string when it contains spaces:
56
+
57
+ ```
58
+ tv -d "Breaking Bad S04E01"
59
+ ```
56
60
 
57
61
  Although it uses some settings and grabbers specific for TV shows, this option can also be used as a quick way to find and download any torrent.
58
62
 
59
- It can be used with the --season flag to try to find and download a whole season of the given show: *tv -d "Breaking Bad" --season 4*. It will start searching from episode 1 and continue until it can't find any torrent for the episode.
63
+ It can be optionally used in conjunction with the `--season` flag to try to find and download a whole season of the given show: `tv -d "Breaking Bad" --season 4`. It will start searching from episode 1 and continue upwards until it can't find any torrent for an episode.
60
64
 
61
65
  ### Multi torrent download
62
66
 
63
- The -f flag can be used to read the list of episodes to download from a file. Each line of the file is interpreted as a episode to download: *tv -f /path/to/listofeps*
67
+ The `-f` flag can be used to read the list of episodes to download from a file. Each line of the file is interpreted as a episode to download.
64
68
 
65
69
  ### Available link grabbers
66
70
 
67
- With -g and --show-grabbers, the user can see what grabbers are available and choose one of these as their preferred option. By default, the application searches for torrents in TorrentAPI, ThePirateBay, EZTV and KAT, in that order, skipping to the next when one of them is down/doesn't have a torrent for said episode.
71
+ With `-g` and `--show-grabbers`, the user can see what grabbers are available and choose one of these as their preferred option. By default, the application searches for torrents using TorrentAPI. When a grabber doesn't have a torrent for said episode, is offline, or causes any error to appear, it skips to the next grabber until exhausting the list.
68
72
 
69
73
  I usually publish a patch update to the gem when I detect one of them isn't working, disabling it or fixing it altogether. If a specific grabber is giving you problems, check whether you're running the latest version of the gem before opening an issue here.
70
74
 
71
75
  ### Pending shows
72
76
 
73
- download_tv version 2.5.0 persists the list of shows it can't find on a given execution (when connecting to MyEpisodes, not for single show or file downloads) and it will try to find them again on following executions. This list can be viewed by passing the -p flag to the tv binary. The list can be cleared with the --clear-pending option.
77
+ **download_tv** persists the list of shows it can't find on a given execution (when connecting to MyEpisodes, not for single show or file downloads) and it will try to find them again on following executions. This list can be viewed by passing the -p flag to the tv binary. The list can be cleared with the --clear-pending option.
74
78
 
75
- Version 2.6.0 adds functionality to queue an episode by running `tv --queue "show name"`. The --queue parameter cannot be used in conjunction with any other parameters. On the plus side, it doesn't need the show name to be quoted or the spaces escaped.
79
+ It also has the functionality to queue an episode by running `tv --queue "show name"`. The --queue parameter cannot be used in conjunction with any other parameters.
76
80
 
77
81
  ### Filters
78
82
 
79
- download_tv version 2.5.5 adds the possibility of setting include/exclude filters for the automatic download of shows.
83
+ **download_tv** allows setting include/exclude filters for the automatic download of shows.
84
+
85
+ Upon installation, the default filters exclude 2060p, 1080p or 720p, and include PROPER or REPACK releases when available. The user can specify in their configuration (`tv -c`) a list of words to include or exclude from their results that will override these defaults.
86
+
87
+ Keep in mind that this is not a hard filter. The application will sequentially apply as many user-defined filters as possible **while still returning at least one result**.
80
88
 
81
- Up until that version, the filters by default were excluding 1080p or 720p, as well as including PROPER or REPACK releases when available. From that version onwards, the user can specify in their configuration (`tv -c`) a list of words to include or exclude from their results.
89
+ ## Shell completion
82
90
 
83
- Please keep in mind that this is not a hard filter. The application will apply as many user-defined filters as possible **while still returning at least one result**.
91
+ The provided binary will print completion files to STDOUT by passing the options `--*-completion-bash` and `--*-completion-zsh` (you might have to escape the asterisk). Use your shell's manual to find out how to load these files to get completions.
84
92
 
85
- ### License
93
+ ## License
86
94
 
87
95
  This project is released under the terms of the MIT license. See [LICENSE.md](https://github.com/guille/download_tv/blob/master/LICENSE.md) file for details.
data/bin/tv CHANGED
@@ -47,7 +47,7 @@ opt_parser = OptionParser.new do |opts|
47
47
  options[:cmd] = 'showconfig'
48
48
  end
49
49
 
50
- opts.on('--dry-run', "Don't write to the date file") do |n|
50
+ opts.on('--dry-run', "Don't update the persisted configuration") do |n|
51
51
  options[:dry] = n
52
52
  end
53
53
 
@@ -115,7 +115,7 @@ begin
115
115
  dl = DownloadTV::Downloader.new(config)
116
116
  dl.run(options[:dry], options[:offset].abs, include_tomorrow: true)
117
117
  when 'config'
118
- DownloadTV::Configuration.new(config, true)
118
+ DownloadTV::Configuration.new(config).change_configuration
119
119
  when 'showconfig'
120
120
  DownloadTV::Configuration.new(config).print_config
121
121
  when 'showpending'
@@ -6,15 +6,14 @@ module DownloadTV
6
6
  class Configuration
7
7
  attr_reader :content, :config_path
8
8
 
9
- def initialize(content = {}, force_change = false)
10
- FileUtils.mkdir_p(File.join(ENV['HOME'], '.config', 'download_tv'))
9
+ def initialize(content = {})
11
10
  @config_path = content[:path] || default_config_path
11
+ FileUtils.mkdir_p(File.expand_path('..', @config_path))
12
12
 
13
13
  if File.exist? @config_path
14
14
  load_config
15
15
  @content.merge!(content) unless content.empty?
16
16
  @content[:ignored]&.map!(&:downcase)
17
- change_configuration if force_change
18
17
  else
19
18
  @content = content
20
19
  change_configuration
@@ -33,11 +32,8 @@ module DownloadTV
33
32
  end
34
33
 
35
34
  def prompt_for_myep_user
36
- if @content[:myepisodes_user]
37
- print "Enter your MyEpisodes username (#{@content[:myepisodes_user]}) : "
38
- else
39
- print 'Enter your MyEpisodes username: '
40
- end
35
+ existing = "(#{@content[:myepisodes_user]}) " if @content[:myepisodes_user]
36
+ print "Enter your MyEpisodes username #{existing}: "
41
37
  input = $stdin.gets.chomp
42
38
  @content[:myepisodes_user] = input if input
43
39
  end
@@ -48,39 +44,27 @@ module DownloadTV
48
44
  end
49
45
 
50
46
  def prompt_for_ignored
51
- if @content[:ignored]
52
- puts "Enter a comma-separated list of shows to ignore: (#{@content[:ignored]})"
53
- else
54
- puts 'Enter a comma-separated list of shows to ignore: '
55
- end
47
+ existing = "(#{@content[:ignored]})" if @content[:ignored]
48
+ puts "Enter a comma-separated list of shows to ignore: #{existing}"
56
49
 
57
- @content[:ignored] = $stdin.gets
58
- .chomp
59
- .split(',')
60
- .map(&:strip)
61
- .map(&:downcase)
50
+ @content[:ignored] = read_and_split_list :downcase
62
51
  end
63
52
 
64
53
  def prompt_for_filters
65
54
  puts "Current filters: (#{@content[:filters]})" if @content[:filters]
66
-
67
55
  @content[:filters] = {}
68
56
 
69
57
  puts 'Enter a comma-separated list of terms to include: '
70
-
71
- @content[:filters][:includes] = $stdin.gets
72
- .chomp
73
- .split(',')
74
- .map(&:strip)
75
- .map(&:upcase)
58
+ @content[:filters][:includes] = read_and_split_list :upcase
76
59
 
77
60
  puts 'Enter a comma-separated list of terms to exclude: '
61
+ @content[:filters][:excludes] = read_and_split_list :upcase
62
+ end
78
63
 
79
- @content[:filters][:excludes] = $stdin.gets
80
- .chomp
81
- .split(',')
82
- .map(&:strip)
83
- .map(&:upcase)
64
+ def read_and_split_list(case_method)
65
+ $stdin.gets.chomp.split(',')
66
+ .map(&:strip)
67
+ .map(&case_method)
84
68
  end
85
69
 
86
70
  def default_filters
@@ -90,11 +74,11 @@ module DownloadTV
90
74
  }
91
75
  end
92
76
 
77
+ ##
78
+ # Update the +content+ attribute with the defaults, if needed.
79
+ # Maintains the previous values, in case it's an update from an existing file.
93
80
  def set_default_values
94
- # When modifying existing config, keeps previous values
95
- # When creating new one, sets defaults
96
81
  @content[:auto] ||= true
97
- @content[:subs] ||= true
98
82
  @content[:grabber] ||= 'TorrentAPI'
99
83
  @content[:date] ||= Date.today - 1
100
84
  @content[:filters] ||= default_filters
@@ -117,7 +101,6 @@ module DownloadTV
117
101
  rescue JSON::ParserError
118
102
  @content = {}
119
103
  change_configuration
120
- retry
121
104
  end
122
105
 
123
106
  def default_config_path
@@ -125,9 +108,7 @@ module DownloadTV
125
108
  end
126
109
 
127
110
  ##
128
- # Returns true if a major or minor update has been detected
129
- # Returns false if a patch has been detected
130
- # Returns nil if it's the same version
111
+ # Returns true if a major or minor update has been detected, something falsy otherwise
131
112
  def breaking_changes?(version)
132
113
  DownloadTV::VERSION.split('.')
133
114
  .zip(version.split('.'))
@@ -16,6 +16,7 @@ module DownloadTV
16
16
  # Tries to download episodes in order for a given season,
17
17
  # until it can't find any
18
18
  def download_entire_season(show, season)
19
+ t = Torrent.new(@config.content[:grabber])
19
20
  season.insert(0, '0') if season.size == 1
20
21
  episode = "#{show} s#{season}e01"
21
22
  loop do
@@ -65,17 +66,16 @@ module DownloadTV
65
66
  # the last run of the program
66
67
  # It connects to MyEpisodes in order to find which shows
67
68
  # to track and which new episodes aired.
68
- # The param +dont_update_last_run+ prevents changing the configuration's date value
69
+ # The param +dry_run+ prevents changing the persisted configuration
69
70
  # The param +offset+ can be used to move the date back that many days in the check
70
71
  # The param +include_tomorrow+ will add the current day to the list of dates to search
71
- def run(dont_update_last_run, offset = 0, include_tomorrow: false)
72
+ def run(dry_run = false, offset = 0, include_tomorrow: false)
72
73
  pending = @config.content[:pending].clone
73
74
  @config.content[:pending].clear
74
75
  pending ||= []
75
76
  date = date_to_check_from(offset)
76
77
 
77
- pending.concat shows_to_download(date) if date < Date.today
78
- pending.concat today_shows_to_download if include_tomorrow && date < Date.today.next
78
+ pending.concat shows_to_download(date, include_tomorrow) if date < (include_tomorrow ? Date.today.next : Date.today)
79
79
 
80
80
  if pending.empty?
81
81
  puts 'Nothing to download'
@@ -84,55 +84,52 @@ module DownloadTV
84
84
  puts 'Completed. Exiting...'
85
85
  end
86
86
 
87
- unless dont_update_last_run
87
+ unless dry_run
88
88
  @config.content[:date] = if include_tomorrow
89
89
  Date.today.next
90
90
  else
91
91
  [Date.today, @config.content[:date]].max
92
92
  end
93
+ @config.serialize
93
94
  end
94
- @config.serialize
95
95
  rescue InvalidLoginError
96
96
  warn 'Wrong username/password combination'
97
97
  end
98
98
 
99
+ def find_links(torrent, shows, queue)
100
+ Thread.new do
101
+ shows.each { |show| queue << get_link(torrent, show, save_pending: true) }
102
+ queue.close
103
+ end
104
+ end
105
+
106
+ def download_from_queue(queue)
107
+ Thread.new do
108
+ until queue.closed?
109
+ magnet = queue.pop
110
+ download(magnet) if magnet # Doesn't download if no torrents are found
111
+ end
112
+ end
113
+ end
114
+
99
115
  def find_and_download(shows)
100
116
  t = Torrent.new
101
117
  queue = Queue.new
102
118
 
103
- # Adds a link (or empty string to the queue)
104
- link_t = Thread.new do
105
- shows.each { |show| queue << get_link(t, show, save_pending: true) }
106
- end
119
+ link_t = find_links(t, shows, queue)
107
120
 
108
121
  # Downloads the links as they are added
109
- download_t = Thread.new do
110
- shows.size.times do
111
- magnet = queue.pop
112
- next if magnet == '' # Doesn't download if no torrents are found
113
-
114
- download(magnet)
115
- end
116
- end
122
+ download_t = download_from_queue(queue)
117
123
 
118
124
  link_t.join
119
125
  download_t.join
120
126
  end
121
127
 
122
- def shows_to_download(date)
123
- myepisodes = MyEpisodes.new(@config.content[:myepisodes_user],
124
- @config.content[:cookie])
125
- myepisodes.load_cookie
126
- shows = myepisodes.get_shows_since(date)
127
- shows = reject_ignored(shows)
128
- fix_names(shows)
129
- end
130
-
131
- def today_shows_to_download
128
+ def shows_to_download(date, include_tomorrow)
132
129
  myepisodes = MyEpisodes.new(@config.content[:myepisodes_user],
133
130
  @config.content[:cookie])
134
131
  myepisodes.load_cookie
135
- shows = myepisodes.today_shows
132
+ shows = myepisodes.get_shows_since(date, include_tomorrow: include_tomorrow)
136
133
  shows = reject_ignored(shows)
137
134
  fix_names(shows)
138
135
  end
@@ -142,18 +139,17 @@ module DownloadTV
142
139
  # When :auto is true it will try to find the best match
143
140
  # based on a set of filters.
144
141
  # When it's false it will prompt the user to select the preferred result
145
- # Returns either a magnet link or an emptry string
142
+ # Returns either a magnet link or nil
146
143
  def get_link(torrent, show, save_pending: false)
147
144
  links = torrent.get_links(show)
148
145
 
149
146
  if links.empty?
150
147
  @config.content[:pending] << show if save_pending
151
- return ''
148
+ return
152
149
  end
153
150
 
154
151
  if @config.content[:auto]
155
- links = filter_shows(links)
156
- links.first[1]
152
+ filter_shows(links).first[1]
157
153
  else
158
154
  prompt_links(links)
159
155
  get_link_from_user(links)
@@ -168,7 +164,7 @@ module DownloadTV
168
164
  i = $stdin.gets.chomp.to_i
169
165
  end
170
166
 
171
- i == -1 ? '' : links[i][1]
167
+ i == -1 ? nil : links[i][1]
172
168
  end
173
169
 
174
170
  def prompt_links(links)
@@ -203,8 +199,8 @@ module DownloadTV
203
199
  # Runs until no filters are left to be applied or applying
204
200
  # a filter would leave no results
205
201
  def filter_shows(links)
206
- f = Filterer.new(@config.content[:filters])
207
- f.filter(links)
202
+ @filterer ||= Filterer.new(@config.content[:filters])
203
+ @filterer.filter(links)
208
204
  end
209
205
 
210
206
  ##
@@ -224,7 +220,7 @@ module DownloadTV
224
220
  when /darwin/
225
221
  'open'
226
222
  else
227
- warn "You're using an unsupported platform."
223
+ warn "You're using an unsupported platform (#{RbConfig::CONFIG['host_os']})."
228
224
  exit 1
229
225
  end
230
226
  end
@@ -9,31 +9,17 @@ module DownloadTV
9
9
  end
10
10
 
11
11
  def get_links(show)
12
- # Format the url
13
- search = format(@url, show)
14
-
15
- raw_data = @agent.get(search)
16
- raw_links = raw_data.search('a.magnet')
12
+ raw_data = @agent.get(format(@url, show))
17
13
  raw_seeders = raw_data.search('td.forum_thread_post_end').map { |e| e.children[0].text.to_i }
18
- raw_links = raw_links.sort_by.with_index { |_, index| raw_seeders[index] }.reverse
19
-
20
- # Torrent name in raw_links[i].attribute 'title'
21
- # 'Suits S04E01 HDTV x264-LOL Torrent: Magnet Link'
14
+ raw_links = raw_data.search('a.magnet').sort_by.with_index { |_, index| raw_seeders[index] }.reverse
22
15
 
23
16
  # EZTV shows 50 latest releases if it can't find the torrent
24
17
  raise NoTorrentsError if raw_links.size == 50
25
18
 
26
- names = raw_links.collect do |i|
27
- i.attribute('title')
28
- .text
29
- .chomp(' Magnet Link')
19
+ raw_links.collect do |i|
20
+ [i.attribute('title').text.chomp(' Magnet Link'),
21
+ i.attribute('href').text]
30
22
  end
31
- links = raw_links.collect do |i|
32
- i.attribute('href')
33
- .text
34
- end
35
-
36
- names.zip(links)
37
23
  end
38
24
  end
39
25
  end
@@ -5,30 +5,29 @@ module DownloadTV
5
5
  # TorrentAPI.org grabber
6
6
  # Interfaces with http://torrentapi.org/apidocs_v2.txt
7
7
  class TorrentAPI < LinkGrabber
8
- attr_accessor :token
9
- attr_reader :wait
8
+ TOKEN_EXPIRED_ERROR = 4
9
+ TOO_MANY_REQUESTS_ERROR = 5 # 1req/2s
10
10
 
11
11
  def initialize
12
12
  super('https://torrentapi.org/pubapi_v2.php?'\
13
13
  'mode=search&search_string=%s&token=%s&'\
14
14
  'app_id=DownloadTV&sort=seeders')
15
- @wait = 0.1
15
+ @wait = 0.5
16
+ @token = nil
16
17
  end
17
18
 
18
19
  ##
19
20
  # Specific implementation for TorrentAPI (requires token)
20
21
  def online?
21
- @agent.read_timeout = 2
22
22
  renew_token
23
23
  true
24
24
  rescue Mechanize::ResponseCodeError => e
25
25
  if e.response_code == '429'
26
26
  sleep(@wait)
27
27
  retry
28
- else
29
- false
30
28
  end
31
- rescue Net::HTTP::Persistent::Error => e
29
+ false
30
+ rescue Net::HTTP::Persistent::Error
32
31
  false
33
32
  end
34
33
 
@@ -52,19 +51,19 @@ module DownloadTV
52
51
  end
53
52
 
54
53
  def get_links(show)
55
- @token ||= renew_token
54
+ renew_token if @token.nil?
56
55
 
57
56
  search = format(@url, show, @token)
58
57
 
59
58
  obj = request_and_parse(search)
60
59
 
61
- if obj['error_code'] == 4 # Token expired
60
+ if obj['error_code'] == TOKEN_EXPIRED_ERROR
62
61
  renew_token
63
62
  search = format(@url, show, @token)
64
63
  obj = request_and_parse(search)
65
64
  end
66
65
 
67
- while obj['error_code'] == 5 # Violate 1req/2s limit
66
+ while obj['error_code'] == TOO_MANY_REQUESTS_ERROR
68
67
  sleep(@wait)
69
68
  obj = request_and_parse(search)
70
69
  end
@@ -79,9 +78,6 @@ module DownloadTV
79
78
  if e.response_code == '429'
80
79
  sleep(@wait)
81
80
  retry
82
- else
83
- warn 'An unexpected error has occurred. Try updating the gem.'
84
- exit 1
85
81
  end
86
82
  end
87
83
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DownloadTV
4
+ ##
5
+ # EZTV.ag grabber
6
+ class Torrentz < LinkGrabber
7
+ def initialize
8
+ super('https://torrentzeu.org/kick.php?q=%s')
9
+ end
10
+
11
+ def get_links(show)
12
+ raw_data = @agent.get(format(@url, show))
13
+ results = raw_data.search('tbody tr')
14
+
15
+ # require 'byebug'; byebug
16
+
17
+ raise NoTorrentsError if results.empty?
18
+
19
+ data = results.sort_by { |e| e.search('td[data-title="Last Updated"]')[1].text.to_i }.reverse
20
+
21
+ data.collect do |i|
22
+ [i.children[1].text.strip,
23
+ i.children[11].children[1].attribute('href').text]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -8,12 +8,13 @@ module DownloadTV
8
8
 
9
9
  def initialize(url)
10
10
  @url = url
11
- @agent = Mechanize.new
12
- @agent.user_agent = DownloadTV::USER_AGENT
11
+ @agent = Mechanize.new do |a|
12
+ a.user_agent = DownloadTV::USER_AGENT
13
+ a.read_timeout = 10
14
+ end
13
15
  end
14
16
 
15
17
  def online?
16
- @agent.read_timeout = 2
17
18
  url = if @url.include? '%s'
18
19
  format(@url, 'test')
19
20
  else
@@ -64,16 +64,11 @@ module DownloadTV
64
64
  @agent
65
65
  end
66
66
 
67
- def get_shows_since(last)
67
+ def get_shows_since(last, include_tomorrow: false)
68
68
  page = @agent.get 'https://www.myepisodes.com/ajax/service.php?mode=view_privatelist'
69
69
  shows = page.parser.css('tr.past')
70
70
  shows = filter_newer_shows(shows, last)
71
- build_show_strings(shows)
72
- end
73
-
74
- def today_shows
75
- page = @agent.get 'https://www.myepisodes.com/ajax/service.php?mode=view_privatelist'
76
- shows = page.parser.css('tr.today')
71
+ shows.concat(page.parser.css('tr.today')) if include_tomorrow
77
72
  build_show_strings(shows)
78
73
  end
79
74
 
@@ -81,7 +76,8 @@ module DownloadTV
81
76
  def filter_newer_shows(shows, date)
82
77
  shows.select do |i|
83
78
  airdate = i.css('td.date')[0].text
84
- Date.parse(airdate) >= date
79
+ viewed_checkbox = i.css('td.status input').last
80
+ Date.parse(airdate) >= date && viewed_checkbox&.attribute('checked').nil?
85
81
  end
86
82
  end
87
83
 
@@ -7,8 +7,7 @@ module DownloadTV
7
7
  attr_reader :g_instances, :tries
8
8
 
9
9
  def grabbers
10
- # %w[TorrentAPI ThePirateBay Eztv KAT]
11
- %w[TorrentAPI Eztv]
10
+ %w[TorrentAPI Torrentz Eztv]
12
11
  end
13
12
 
14
13
  def initialize(default_grabber = nil)
@@ -39,31 +38,23 @@ module DownloadTV
39
38
  end
40
39
 
41
40
  def change_grabbers
42
- # Rotates the instantiated grabbers
41
+ @tries -= 1
43
42
  @g_instances.rotate!
44
43
  check_grabber_online
45
44
  end
46
45
 
47
46
  def get_links(show)
48
- links = @g_instances.first.get_links(show)
49
-
50
- reset_grabbers_order
51
- reset_tries
52
-
53
- links
47
+ @g_instances.first.get_links(show)
54
48
  rescue NoTorrentsError
55
- # Use next grabber
56
49
  if @tries.positive?
57
- @tries -= 1
58
50
  change_grabbers
59
51
  retry
60
-
61
- else
62
- reset_grabbers_order
63
- reset_tries
64
- puts "No torrents found for #{show}"
65
- []
66
52
  end
53
+ # We're out of grabbers to try
54
+ puts "No torrents found for #{show}"
55
+ []
56
+ ensure
57
+ reset_grabbers_order
67
58
  end
68
59
 
69
60
  def reset_tries
@@ -72,6 +63,7 @@ module DownloadTV
72
63
 
73
64
  def reset_grabbers_order
74
65
  @g_instances.rotate!(@tries + 1)
66
+ reset_tries
75
67
  end
76
68
  end
77
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DownloadTV
4
- VERSION = '2.6.2'
4
+ VERSION = '2.6.6'
5
5
  end
data/lib/download_tv.rb CHANGED
@@ -14,7 +14,6 @@ require 'download_tv/torrent'
14
14
  require 'download_tv/filterer'
15
15
  require 'download_tv/myepisodes'
16
16
  require 'download_tv/linkgrabber'
17
- require 'download_tv/subtitles'
18
17
 
19
18
  module DownloadTV
20
19
  USER_AGENT = "DownloadTV #{DownloadTV::VERSION}"
data/test/config_test.rb CHANGED
@@ -105,7 +105,6 @@ describe DownloadTV::Configuration do
105
105
  _(c.content[:cookie]).must_equal true
106
106
  _(c.content[:ignored]).must_equal ['anything']
107
107
  _(c.content[:auto]).must_equal true
108
- _(c.content[:subs]).must_equal true
109
108
  _(c.content[:pending]).must_equal []
110
109
  _(c.content[:grabber]).must_equal 'TorrentAPI'
111
110
  _(c.content[:date]).must_equal(Date.today - 1)
@@ -151,7 +150,6 @@ describe DownloadTV::Configuration do
151
150
  _(content[:myepisodes_user]).must_equal 'anything'
152
151
  _(content[:ignored]).must_equal ['anything']
153
152
  _(content[:auto]).must_equal true
154
- _(content[:subs]).must_equal true
155
153
  _(content[:pending]).must_equal []
156
154
  _(content[:grabber]).must_equal 'TorrentAPI'
157
155
  _(content[:date]).must_equal Date.today - 1
@@ -44,17 +44,17 @@ describe DownloadTV::Downloader do
44
44
  end
45
45
  end
46
46
 
47
- describe 'the check_date method' do
48
- it 'exits the script when up to date' do
47
+ describe 'the date_to_check_from method' do
48
+ it 'returns the config date when offset is not given' do
49
49
  dl = DownloadTV::Downloader.new(date: Date.today, path: config_path)
50
- _(dl.check_date(0)).must_be_nil
50
+ _(dl.date_to_check_from(0)).must_equal Date.today
51
51
  end
52
52
 
53
53
  it 'uses the offset to adjust the date' do
54
54
  # Would exit with offset 0
55
55
  dl = DownloadTV::Downloader.new(date: Date.today, path: config_path)
56
56
 
57
- date = dl.check_date(1)
57
+ date = dl.date_to_check_from(1)
58
58
 
59
59
  _(date).must_equal(Date.today - 1)
60
60
  _(dl.config.content[:date]).must_equal Date.today
@@ -89,18 +89,18 @@ describe DownloadTV::Downloader do
89
89
  end
90
90
 
91
91
  describe 'the get_link method' do
92
- it "returns an empty string when it can't find links" do
92
+ it "returns nil when it can't find links" do
93
93
  t = Minitest::Mock.new
94
94
  show = 'Example Show S01E01'
95
95
 
96
96
  t.expect(:get_links, [], [show])
97
97
  dl = DownloadTV::Downloader.new(auto: true, path: config_path, pending: ['show 11'])
98
- _(dl.get_link(t, show, true)).must_equal ''
98
+ _(dl.get_link(t, show, save_pending: true)).must_be_nil
99
99
  _(dl.config.content[:pending]).must_equal ['show 11', show]
100
100
 
101
101
  t.expect(:get_links, [], [show])
102
102
  dl = DownloadTV::Downloader.new(auto: false, path: config_path, pending: [])
103
- _(dl.get_link(t, show, true)).must_equal ''
103
+ _(dl.get_link(t, show, save_pending: true)).must_be_nil
104
104
  _(dl.config.content[:pending]).must_include show
105
105
 
106
106
  t.verify
@@ -20,7 +20,7 @@ describe DownloadTV::LinkGrabber do
20
20
  end
21
21
 
22
22
  it 'will return an array with names and links of results when a torrent can be found' do
23
- result = grabber.get_links('The Boys S01E01')
23
+ result = grabber.get_links('The Boys S02E01')
24
24
  _(result).must_be_instance_of Array
25
25
  _(result).wont_be :empty?
26
26
  result.each do |r|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: download_tv
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.2
4
+ version: 2.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - guille
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-20 00:00:00.000000000 Z
11
+ date: 2022-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -119,6 +119,7 @@ files:
119
119
  - ".github/workflows/ruby.yml"
120
120
  - ".gitignore"
121
121
  - ".travis.yml"
122
+ - CHANGELOG.md
122
123
  - Gemfile
123
124
  - LICENSE.md
124
125
  - README.md
@@ -129,14 +130,13 @@ files:
129
130
  - lib/download_tv/configuration.rb
130
131
  - lib/download_tv/downloader.rb
131
132
  - lib/download_tv/filterer.rb
132
- - lib/download_tv/grabbers/addic7ed.rb
133
133
  - lib/download_tv/grabbers/eztv.rb
134
134
  - lib/download_tv/grabbers/kat.rb
135
135
  - lib/download_tv/grabbers/torrentapi.rb
136
+ - lib/download_tv/grabbers/torrentz2.rb
136
137
  - lib/download_tv/grabbers/tpb.rb
137
138
  - lib/download_tv/linkgrabber.rb
138
139
  - lib/download_tv/myepisodes.rb
139
- - lib/download_tv/subtitles.rb
140
140
  - lib/download_tv/torrent.rb
141
141
  - lib/download_tv/version.rb
142
142
  - test/config_test.rb
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  - !ruby/object:Gem::Version
164
164
  version: '0'
165
165
  requirements: []
166
- rubygems_version: 3.2.17
166
+ rubygems_version: 3.2.30
167
167
  signing_key:
168
168
  specification_version: 4
169
169
  summary: DownloadTV is a tool that allows the user to find magnet links for tv show
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DownloadTV
4
- ##
5
- # Addic7ed prototype (WIP)
6
- class Addic7ed < LinkGrabber
7
- def initialize
8
- super('http://www.addic7ed.com/search.php?search=%s'\
9
- '&Submit=Search')
10
- end
11
-
12
- def get_subs(show)
13
- url = get_url(show)
14
- download_file(url)
15
- end
16
-
17
- def get_url(show)
18
- # Change spaces for the separator
19
- s = show.gsub(' ', @sep)
20
-
21
- # Format the url
22
- search = Format(@url, s)
23
-
24
- agent = Mechanize.new
25
- res = agent.get(search)
26
-
27
- # No redirection means no subtitle found
28
- raise NoSubtitlesError if res.uri.to_s == search
29
-
30
- ##########
31
- # DO OPENSUBTITLES FIRST (see subtitles.rb)
32
- #####
33
-
34
- # We now have an URL like:
35
- # http://www.addic7ed.com/serie/Mr._Robot/2/3/eps2.1k3rnel-pan1c.ksd
36
-
37
- # To find the real links:
38
- # see comments at the end of file
39
- end
40
-
41
- def download_file(url)
42
- # Url must be like 'http://www.addic7ed.com/updated/1/115337/0'
43
-
44
- # ADDIC7ED PROVIDES RSS
45
-
46
- agent = Mechanize.new
47
- page = agent.get(url, [], @url)
48
- puts page.save('Hi')
49
- end
50
- end
51
- end
52
- # subtitles = {}
53
- # html.css('.tabel95 .newsDate').each do |td|
54
- # if downloads = td.text.match(/\s(\d*)\sDownloads/i)
55
- # done = false
56
- # td.parent.parent.xpath('./tr/td/a[@class='buttonDownload']/@href').each do |link|
57
- # if md = link.value.match(/updated/i)
58
- # subtitles[downloads[1].to_i] = link.value
59
- # done = true
60
- # elsif link.value.match(/original/i) && done == false
61
- # subtitles[downloads[1].to_i] = link.value
62
- # done = true
63
- # end
64
- # end
65
- # end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DownloadTV
4
- ##
5
- # Manages the subtitles (WIP)
6
- class Subtitles
7
- def initialize
8
- @a = Addic7ed.new
9
- end
10
-
11
- def get_subs(show)
12
- @a.get_subs(show)
13
- rescue NoSubtitlesError
14
- puts "No subtitles found for #{show}"
15
- end
16
- end
17
- end