Module: Cinema

Defined in:
lib/cinema.rb,
lib/cinema/version.rb

Constant Summary collapse

APP_ID =
"69f18bbaff859f035d934888f846b7ae3653e223a2b0f15629bcc9b836d3996b"
APP_SECRET =
"077edf5024fca4102295263e802631f52f8cebd404f612194279f059bc5d9b8d"
VERSION =
"2.2.0"

Class Method Summary collapse

Class Method Details

.ask_and_playObject



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/cinema.rb', line 39

def ask_and_play
  watchlist = get_watchlist
  sorting_options = get_sorting_options(watchlist.first)
  sort_getter = select("Order movie list by", sorting_options, &:first).last

  imdb_id = select("Select movie", watchlist.sort_by{|x| sort_getter.(x)}){ |x|
    "#{sort_getter.(x)}: #{x["movie"]["title"]}"
  }["movie"]["ids"]["imdb"]

  torrent = select("Select quality", torrents(imdb_id)){|x| x["quality"] }["url"]
  downloader = select("Select downloader", ["peerflix", "qbittorrent", "wget", "echo"])
  run_torrent(downloader, torrent)
end

.capture_stderrObject



176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/cinema.rb', line 176

def capture_stderr
  backup_stderr = STDERR.dup
  begin
    Tempfile.open("captured_stderr") do |f|
      STDERR.reopen(f)
      yield
      f.rewind
      f.read
    end
  ensure
    STDERR.reopen backup_stderr
  end
end

.configObject



155
156
157
158
159
160
# File 'lib/cinema.rb', line 155

def config
  unless File.exist? config_file
    initial_authorize_and_save_config
  end
  YAML.load_file config_file
end

.config_fileObject



162
163
164
# File 'lib/cinema.rb', line 162

def config_file
  "#{ENV['HOME']}/.config/cinema.yml"
end

.get_sorting_options(sample) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/cinema.rb', line 14

def get_sorting_options(sample)
  sample.reduce([]) do |result, (k,v)|
    if v.is_a? Hash
      child_sorting_options = get_sorting_options(v).map do |name, accessor|
        ["#{k} #{name}", ->(x){ accessor.(x[k]) }]
      end
      result.concat child_sorting_options
    else
      result << [k.to_s, ->(x){ x[k] }]
    end
  end
end

.get_watchlistObject



68
69
70
71
72
73
# File 'lib/cinema.rb', line 68

def get_watchlist
  with_unreliable_api do
    puts "Requesting watchlist..."
    trakt_request(:get, "sync/watchlist/movies")
  end
end

.initial_authorizeObject



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/cinema.rb', line 103

def initial_authorize
  loop do
    capture_stderr do
      Launchy.open("https://trakt.tv/oauth/authorize?client_id=#{APP_ID}&redirect_uri=#{redirect_uri}&response_type=code")
    end
    print "Please authorize the app and enter PIN: "
    pin = gets.chomp
    if pin.size == 8
      return pin_to_token(pin)
    end
  end
end

.initial_authorize_and_save_configObject



120
121
122
# File 'lib/cinema.rb', line 120

def initial_authorize_and_save_config
  write_config(*initial_authorize)
end

.pin_to_token(pin) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/cinema.rb', line 91

def pin_to_token(pin)
  response =
    RestClient.post('https://trakt.tv/oauth/token', {
                      code: pin,
                      client_id: APP_ID,
                      client_secret: APP_SECRET,
                      redirect_uri: redirect_uri,
                      grant_type: 'authorization_code'
                    }).body
  JSON.parse(response).values_at('access_token', 'refresh_token')
end

.redirect_uriObject



87
88
89
# File 'lib/cinema.rb', line 87

def redirect_uri
  'urn:ietf:wg:oauth:2.0:oob'
end

.refresh_access_tokenObject



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/cinema.rb', line 124

def refresh_access_token
  response =
    RestClient.post('https://trakt.tv/oauth/token', {
                      refresh_token: config[:refresh_token],
                      client_id: APP_ID,
                      client_secret: APP_SECRET,
                      redirect_uri: redirect_uri,
                      grant_type: 'refresh_token'
                    }).body
  write_config *JSON.parse(response).values_at('access_token', 'refresh_token')
end

.run_torrent(downloader, torrent) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/cinema.rb', line 27

def run_torrent(downloader, torrent)
  case downloader
  when 'peerflix'
    player = select("Select player", ["mplayer","vlc"])
    system downloader, torrent, "--#{player}"
  when 'qbittorrent'
    system "sh", "-c", "#{downloader} #{torrent} &"
  else
    system downloader, torrent
  end
end

.select(title, items, &title_proc) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/cinema.rb', line 53

def select(title, items, &title_proc)
  menu_items = items.each_with_index.map do |x,i|
    [i.to_s, (title_proc ? title_proc.(x) : x)]
  end
  index = capture_stderr do
    success = system 'dialog', '--title', title,
      '--menu', '', '0', '0', '0',
      *menu_items.flatten
    unless success
      exit 0
    end
  end
  items[index.to_i] if index
end

.torrents(imdb_id) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/cinema.rb', line 75

def torrents(imdb_id)
  with_unreliable_api do
    puts "Searching torrents..."
    response = RestClient.get("http://yts.ag/api/v2/list_movies.json?query_term=#{imdb_id}").body
    JSON.parse(response)["data"]["movies"].first["torrents"]
  end
end

.trakt_request(method, path, payload = nil) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/cinema.rb', line 136

def trakt_request(method, path, payload=nil)
  params = {
    method: method,
    url: "https://api-v2launch.trakt.tv/#{path}",
    payload: payload,
    headers: {
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{config[:access_token]}",
      "trakt-api-version" => "2",
      "trakt-api-key" => APP_ID,
    }
  }
  JSON.parse RestClient::Request.execute(params).body
rescue RestClient::Unauthorized
  puts 'Unauthorized. Trying to refresh token.'
  refresh_access_token
  retry
end

.with_unreliable_api(delay = 3) ⇒ Object



166
167
168
169
170
171
172
173
174
# File 'lib/cinema.rb', line 166

def with_unreliable_api(delay=3)
  begin
    yield
  rescue
    puts "Request failed. Retrying in #{delay} seconds..."
    sleep delay
    retry
  end
end

.write_config(access_token, refresh_token) ⇒ Object



116
117
118
# File 'lib/cinema.rb', line 116

def write_config(access_token, refresh_token)
  File.write config_file, {access_token: access_token, refresh_token: refresh_token}.to_yaml
end

.yifyObject



83
84
85
# File 'lib/cinema.rb', line 83

def yify
  @yify ||= Yify::Client.new
end