discogs (2958B)
1 #!/usr/bin/env ruby 2 require "net/http" 3 require "openssl" 4 require "json" 5 6 # Add easy access to hash members for JSON stuff 7 class Hash 8 def method_missing(meth, *_args, &_block) 9 raise NoMethodError unless key?(meth.to_s) 10 11 self[meth.to_s] 12 end 13 end 14 15 class Discogs 16 def initialize_http 17 @http = Net::HTTP.new(@base_url.host, @base_url.port) 18 @http.use_ssl = true 19 @http.verify_mode = OpenSSL::SSL::VERIFY_NONE 20 end 21 22 def auth 23 my_user_token = ENV["DISCOGS_API_TOKEN"] 24 25 if my_user_token.nil? 26 raise "No user token set." 27 end 28 29 @token = my_user_token 30 end 31 32 def initialize 33 auth 34 @base_url = URI("https://api.discogs.com") 35 initialize_http 36 end 37 38 def url_call_get(url) 39 request = Net::HTTP::Get.new(url) 40 request["Authorization"] = "Discogs token=#{@token}" 41 begin 42 resp = @http.request(request) 43 rescue Exception => e 44 puts("Connection broke (#{e}), retrying request to #{url}") 45 binding.irb if File.exist?("/tmp/rubydebug") 46 47 sleep(2) 48 initialize_http 49 return url_call_get(url) 50 end 51 52 if resp["X-Discogs-Ratelimit-Remaining"].to_i == 0 53 sleep(60) 54 return url_call_get(url) 55 elsif resp.code_type != Net::HTTPOK 56 puts("Request #{url} returned #{resp}") 57 exit(1) 58 end 59 60 JSON.parse(resp.read_body) 61 end 62 63 def api_call_get(endpoint, params = {}) 64 url = @base_url + endpoint 65 url.query = URI.encode_www_form(params) 66 url_call_get(url) 67 end 68 69 def search(query) 70 return api_call_get("/database/search", {q: query}) 71 end 72 73 end 74 75 # Join the rest of the arguments into a search string 76 query = ARGV.join(" ") 77 78 # Initialise arrays 79 genres, styles = [], [] 80 81 # Search for the query 82 discogs = Discogs::new 83 search = discogs.search("#{query}") 84 85 if search.results.empty? 86 STDERR.puts("discogs: no search results") 87 exit(1) 88 end 89 90 # Add the genres of the first result 91 search["results"].each do |result| 92 if result.include?("genre") && !result["genre"].empty? 93 genres.push(result["genre"].first) 94 # result.genre.each do |g| 95 # if g.include? "," 96 # g.split(",").each { |x| genres.push "#{x}" } 97 # else 98 # genres.push "#{g}" 99 # end 100 # end 101 break 102 end 103 end 104 105 # Add the styles of the first result 106 search["results"].each do |result| 107 if result.include?("style") && !result["style"].empty? 108 styles.push(result["style"].to_a.first) 109 # result.style.to_a.each { |x| styles.push("#{x}") } 110 end 111 112 break 113 end 114 115 # Add the url of the first result 116 # url = "http://discogs.com#{search.results[0].uri}".split(" ") 117 118 # Join everything together into a 2d array 119 # 2 different separators ("~", ",") because bash 120 # result = [genres.join("~"), styles.join("~"), url] 121 result = [genres.join("~"), styles.join("~")] 122 123 # Unless only asking for genre, also add title 124 if !(ARGV.include?("-g") || ARGV.include?("--genre")) 125 result = [search.results.first.title] + result 126 end 127 128 # Send result to stdout 129 puts(result.join("/"))