├── .gitignore ├── .rspec ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib ├── marvel │ ├── api.rb │ ├── api │ │ ├── character.rb │ │ ├── comic.rb │ │ ├── creator.rb │ │ ├── event.rb │ │ ├── old │ │ │ ├── account.rb │ │ │ ├── app.rb │ │ │ ├── apps.rb │ │ │ ├── password.rb │ │ │ ├── rate_limits.rb │ │ │ └── regions.rb │ │ ├── series.rb │ │ └── story.rb │ ├── conn.rb │ ├── conn │ │ └── cache.rb │ ├── model.rb │ ├── properties.rb │ ├── properties │ │ └── null_logger.rb │ └── version.rb └── marvel_api.rb ├── marvel.gemspec └── spec └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 1.9.3 4 | script: 5 | - bundle install 6 | - CODECLIMATE_REPO_TOKEN=9e979646269338662e0e529e8d8f0ca1a50ba26ca18c1f18caaa29344b76badf bundle exec rspec 7 | addons: 8 | code_climate: 9 | repo_token: 9e979646269338662e0e529e8d8f0ca1a50ba26ca18c1f18caaa29344b76badf 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in marvel.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Ritesh Choudhary 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marvel-API Gem 2 | 3 | Ruby Client for Marvel API's just add gem in your project for using the Marvel API. 4 | 5 | Marvel Ruby Client Provide apis for following resources: 6 | 7 | Character 8 | Comic 9 | Creator 10 | Event 11 | Series 12 | Story 13 | 14 | ## Installation 15 | 16 | Add this line to your application's Gemfile: 17 | 18 | gem 'marvel-api' 19 | 20 | And then execute: 21 | 22 | $ bundle 23 | 24 | Or install it yourself as: 25 | 26 | $ gem install marvel-api 27 | 28 | ## Usage 29 | 30 | ### Require the gem 31 | 32 | require 'marvel_api' 33 | # => true 34 | 35 | ### Configuration 36 | 37 | Marvel::API.configure do |c| 38 | c.public_key = "" # Mandatory 39 | c.private_key = "" # Mandatory 40 | end 41 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /lib/marvel/api.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/properties' 2 | 3 | module Marvel 4 | class API 5 | require 'marvel/api/character' 6 | require 'marvel/api/comic' 7 | require 'marvel/api/creator' 8 | require 'marvel/api/event' 9 | require 'marvel/api/series' 10 | require 'marvel/api/story' 11 | 12 | 13 | extend Marvel::Properties::ConfigMethods 14 | extend Marvel::API::Character 15 | extend Marvel::API::Comic 16 | extend Marvel::API::Creator 17 | extend Marvel::API::Event 18 | extend Marvel::API::Series 19 | extend Marvel::API::Story 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/marvel/api/character.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Character 8 | @@etags = {} 9 | RESOURCE_TYPE = "CHARACTER" 10 | API_BASE_PATH = "/v1/public/characters" 11 | 12 | def getCharacters(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getCharacter(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getComicsOfCharacter(id, params = {}) 23 | resource = "comics" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getCreatorsOfCharacter(id, params = {}) 29 | resource = "creators" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getEventsOfCharacter(id, params = {}) 35 | resource = "events" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getSeriesOfCharacter(id, params = {}) 41 | resource = "series" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getStoriesOfCharacter(id, params = {}) 47 | resource = "stories" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/api/comic.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Comic 8 | @@etags = {} 9 | RESOURCE_TYPE = "COMIC" 10 | API_BASE_PATH = "/v1/public/comics" 11 | 12 | def getComics(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getComic(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getCharactersOfComic(id, params = {}) 23 | resource = "characters" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getCreatorsOfComic(id, params = {}) 29 | resource = "creators" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getEventsOfComic(id, params = {}) 35 | resource = "events" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getSeriesOfComic(id, params = {}) 41 | resource = "series" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getStoriesOfComic(id, params = {}) 47 | resource = "stories" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/api/creator.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Creator 8 | @@etags = {} 9 | RESOURCE_TYPE = "CREATOR" 10 | API_BASE_PATH = "/v1/public/creators" 11 | 12 | def getCreators(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getCreator(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getCharactersOfCreator(id, params = {}) 23 | resource = "characters" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getComicsOfCreator(id, params = {}) 29 | resource = "comics" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getEventsOfCreator(id, params = {}) 35 | resource = "events" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getSeriesOfCreator(id, params = {}) 41 | resource = "series" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getStoriesOfCreator(id, params = {}) 47 | resource = "stories" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/api/event.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Event 8 | @@etags = {} 9 | RESOURCE_TYPE = "EVENT" 10 | API_BASE_PATH = "/v1/public/events" 11 | 12 | def getEvents(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getEvent(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getCharactersOfEvent(id, params = {}) 23 | resource = "characters" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getComicsOfEvent(id, params = {}) 29 | resource = "comics" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getCreatorsOfEvent(id, params = {}) 35 | resource = "creators" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getSeriesOfEvent(id, params = {}) 41 | resource = "series" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getStoriesOfEvent(id, params = {}) 47 | resource = "stories" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/api/old/account.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | require 'heroku/model/account' 4 | 5 | module Heroku 6 | class API 7 | module Account 8 | @@etag = nil 9 | RESOURCE_TYPE = "ACCOUNT" 10 | 11 | def account 12 | Heroku::Properties.logger.info("[Account] Fetching.") 13 | 14 | @@etag, res = 15 | Heroku::Conn::Get( 16 | '/account', 17 | etag: @@etag, 18 | r_type: RESOURCE_TYPE 19 | ) 20 | 21 | Heroku::Model::Account.new(res.merge("parent" => self)) 22 | end 23 | 24 | def update_account(account) 25 | Heroku::Properties.logger.info("[Account] Updating #{account.id}") 26 | 27 | @@etag, res = 28 | Heroku::Conn::Patch( 29 | "/account", 30 | r_type: RESOURCE_TYPE, 31 | body: account.patchable.to_json 32 | ) 33 | 34 | Heroku::Model::Account.new(res.merge("parent" => self)) 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/marvel/api/old/app.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | require 'heroku/model/app' 4 | 5 | module Heroku 6 | class API 7 | module App 8 | @@etags = {} 9 | RESOURCE_TYPE = "APP" 10 | 11 | def app(name_or_id) 12 | Heroku::Properties.logger.info("[App] Fetching #{name_or_id}") 13 | 14 | etag, res = 15 | Heroku::Conn::Get( 16 | "/apps/#{name_or_id}", 17 | etag: @@etags[name_or_id], 18 | r_type: RESOURCE_TYPE 19 | ) 20 | 21 | @@etags[res['id']] = etag 22 | @@etags[res['name']] = etag 23 | Heroku::Model::App.new(res.merge("parent" => self)) 24 | end 25 | 26 | def new(params = {}) 27 | Heroku::Properties.logger.info("[App] New with parameters: #{params.inspect}") 28 | 29 | _, res = 30 | Heroku::Conn::Post( 31 | '/apps', 32 | r_type: RESOURCE_TYPE, 33 | body: params.to_json 34 | ) 35 | 36 | Heroku::Model::App.new(res.merge("parent" => self)) 37 | end 38 | 39 | def update_app(app) 40 | Heroku::Properties.logger.info("[App] Updating #{app.id}") 41 | 42 | etag, res = 43 | Heroku::Conn::Patch( 44 | app.end_point, 45 | r_type: RESOURCE_TYPE, 46 | body: app.patchable.to_json 47 | ) 48 | 49 | @@etags[res['id']] = etag 50 | @@etags[res['name']] = etag 51 | Heroku::Model::App.new(res.merge("parent" => self)) 52 | end 53 | 54 | def delete_app(app) 55 | Heroku::Properties.logger.info("[App] Deleting #{app.id}") 56 | Heroku::Conn::Delete(app.end_point, r_type: RESOURCE_TYPE) 57 | true 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/marvel/api/old/apps.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | require 'heroku/model/app_list' 4 | require 'heroku/model/app' 5 | 6 | module Heroku 7 | class API 8 | module Apps 9 | @@etag = nil 10 | RESOURCE_TYPE = "APPS" 11 | 12 | def apps 13 | Heroku::Model::AppList.new( ->(parent){ 14 | Heroku::Properties.logger.info("[Apps] Fetching") 15 | 16 | @@etag, res = 17 | Heroku::Conn::Get( 18 | "/apps", 19 | etag: @@etag, 20 | r_type: RESOURCE_TYPE 21 | ) 22 | 23 | res.map do |params| 24 | Heroku::Model::App.new(params.merge("parent" => parent)) 25 | end 26 | }) 27 | end 28 | 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/marvel/api/old/password.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | 4 | module Heroku 5 | class API 6 | module Password 7 | def update_password(new_password, current_password) 8 | Heroku::Properties.logger.info("[Password] Updating") 9 | 10 | Heroku::Conn::Put("/account/password", body: { 11 | password: new_password, 12 | current_password: current_password 13 | }.to_json) 14 | true 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/marvel/api/old/rate_limits.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | 4 | module Heroku 5 | class API 6 | module RateLimits 7 | @@etag = nil 8 | RESOURCE_TYPE = "RATE_LIMITS" 9 | 10 | def rate_limits 11 | Heroku::Properties.logger.info("[Rate Limits] Fetching") 12 | 13 | @@etag, res = 14 | Heroku::Conn::Get( 15 | "/account/rate-limits", 16 | etag: @@etag, 17 | r_type: RESOURCE_TYPE 18 | ) 19 | 20 | res["remaining"].to_i 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/marvel/api/old/regions.rb: -------------------------------------------------------------------------------- 1 | require 'heroku/conn' 2 | require 'heroku/properties' 3 | 4 | module Heroku 5 | class API 6 | module Regions 7 | def regions 8 | Heroku::Properties.logger.info("[Regions] Fetching") 9 | Heroku::Conn::Get("/regions").last 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/marvel/api/series.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Series 8 | @@etags = {} 9 | RESOURCE_TYPE = "SERIES" 10 | API_BASE_PATH = "/v1/public/series" 11 | 12 | def getSeries(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getSeries(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getCharactersOfSeries(id, params = {}) 23 | resource = "characters" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getComicsOfSeries(id, params = {}) 29 | resource = "comics" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getCreatorsOfSeries(id, params = {}) 35 | resource = "creators" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getEventsOfSeries(id, params = {}) 41 | resource = "events" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getStoriesOfSeries(id, params = {}) 47 | resource = "stories" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/api/story.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/conn' 2 | require 'marvel/properties' 3 | 4 | 5 | module Marvel 6 | class API 7 | module Story 8 | @@etags = {} 9 | RESOURCE_TYPE = "STORIE" 10 | API_BASE_PATH = "/v1/public/storie" 11 | 12 | def getStorie(params = {}) 13 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}] Fetching #{params}") 14 | baseRequest("#{API_BASE_PATH}", params) 15 | end 16 | 17 | def getStory(id, params = {}) 18 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] Fetching #{params}") 19 | baseRequest("#{API_BASE_PATH}/#{id}", params) 20 | end 21 | 22 | def getCharactersOfStory(id, params = {}) 23 | resource = "characters" 24 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 25 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 26 | end 27 | 28 | def getComicsOfStory(id, params = {}) 29 | resource = "comics" 30 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 31 | baseRequest("/#{API_BASE_PATH}/#{id}/#{resource}", params) 32 | end 33 | 34 | def getCreatorsOfStory(id, params = {}) 35 | resource = "creators" 36 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 37 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 38 | end 39 | 40 | def getEventsOfStory(id, params = {}) 41 | resource = "events" 42 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 43 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 44 | end 45 | 46 | def getSeriesOfStory(id, params = {}) 47 | resource = "series" 48 | Marvel::Properties.logger.info("[#{RESOURCE_TYPE}:#{id}] with #{resource} Fetching #{params}") 49 | baseRequest("#{API_BASE_PATH}/#{id}/#{resource}", params) 50 | end 51 | 52 | 53 | private 54 | def baseRequest(path, params = {}) 55 | etag, res = 56 | Marvel::Conn::Get( 57 | "#{path}#{Marvel::Conn.authorization_params}", 58 | etag: @@etags["path"], 59 | r_type: RESOURCE_TYPE 60 | ) 61 | responce_handlar(res) 62 | @@etags[res['id']] = etag 63 | @@etags[res['name']] = etag 64 | ##Heroku::Model::App.new(res.merge("parent" => self)) 65 | end 66 | 67 | def responce_handlar(responce_obj) 68 | characters_count = responce_obj['data']['total'] 69 | characters_info = responce_obj['data']['results'].collect{|res| {name:res['name'], thumbnail:res['thumbnail']} } 70 | puts "characters count : " + characters_count.to_s 71 | puts characters_info 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/marvel/conn.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'net/http' 3 | require 'digest/md5' 4 | require 'marvel/properties' 5 | 6 | module Marvel 7 | class Conn 8 | require 'marvel/conn/cache' 9 | 10 | APIRequest = Struct.new(:method, :end_point) 11 | 12 | @https = Net::HTTP.new('gateway.marvel.com', 80).tap do |https| 13 | https.use_ssl = false 14 | end 15 | 16 | def self.cache 17 | @cache ||= Marvel::Conn::Cache.new 18 | end 19 | 20 | def self.method_missing(method, end_point, opts = {}) 21 | _Request = Net::HTTP.const_get(method.capitalize) 22 | 23 | req = _Request.new(end_point, headers(opts)) 24 | req.body = opts[:body] 25 | api_req = APIRequest[method, end_point] 26 | 27 | Marvel::Properties.logger.debug("[Conn] Attempting #{method.upcase} #{end_point} ...") 28 | 29 | check_response(api_req, opts[:r_type], @https.request(req)) 30 | end 31 | 32 | private 33 | 34 | def self.check_response(api_req, r_type, res) 35 | Marvel::Properties.logger.debug("[Conn] Received #{res.code} for #{r_type} at #{api_req.end_point}") 36 | 37 | case res 38 | when Net::HTTPOK, 39 | Net::HTTPCreated 40 | cache.put( 41 | r_type, res["ETag"], 42 | parse_body(res) 43 | ) 44 | when Net::HTTPPartialContent 45 | cache.put( 46 | r_type, res["ETag"], 47 | gather_partial_content(api_req, res) 48 | ) 49 | when Net::HTTPNotModified then cache.fetch(r_type, res["ETag"]) 50 | when Net::HTTPSuccess then [res["ETag"], parse_body(res)] 51 | else raise_exception(res) 52 | end 53 | end 54 | 55 | def gather_partial_content(api_req, res) 56 | Marvel::Properties.logger.info("[Conn] Gathering Partial Content.") 57 | 58 | list_head = parse_body(res) 59 | etag, list_tail = 60 | self.send( 61 | api_req.method, 62 | api_req.end_point, 63 | range: res["Next-Range"] 64 | ) 65 | 66 | list_tail.unshift(*list_head) 67 | end 68 | 69 | def self.raise_exception(res) 70 | Marvel::Properties.logger.error("[Conn response] #{res.body.inspect}") 71 | Marvel::Properties.logger.error("[Conn] Uh oh, something went wrong with request #{res["Request-Id"]}.") 72 | raise res.class::EXCEPTION_TYPE.new(status(res.code), nil) 73 | end 74 | 75 | def self.status(code) 76 | Hash[Net::HTTPResponse::CODE_TO_OBJ.map { |k, v| [k, v.to_s] }] 77 | .merge({ "429" => "Net::HTTPTooManyRequests" }) 78 | .fetch(code, "Net::HTTPUnknownError") 79 | end 80 | 81 | def self.headers(opts = {}) 82 | { 83 | "Accept" => 'application/json', 84 | "Content-Type" => 'application/json;charset=utf-8', 85 | "User-Agent" => Marvel::Properties::USER_AGENT 86 | }.merge({}.tap do |header| 87 | header["If-None-Match"] = opts[:etag] if opts[:etag] 88 | header["Range"] = opts[:range] if opts[:range] 89 | end) 90 | end 91 | 92 | def self.authorization_params 93 | ts = Time.now.to_i 94 | hash = Digest::MD5.hexdigest("#{ts}#{Marvel::Properties.private_key}#{Marvel::Properties.public_key}") 95 | "?ts=#{ts}&apikey=#{Marvel::Properties.public_key}&hash=#{hash}" 96 | end 97 | 98 | def self.parse_body(res) 99 | JSON.parse(decompress(res)) 100 | end 101 | 102 | def self.decompress(res) 103 | case res["content-encoding"] 104 | when 'gzip' 105 | Zlib::GzipReader.new( 106 | StringIO.new(res.body), 107 | encoding: "ASCII-8BIT" 108 | ).read 109 | when 'deflate' 110 | Zlib::Inflate.inflate(res.body) 111 | else 112 | res.body 113 | end 114 | end 115 | end 116 | end 117 | -------------------------------------------------------------------------------- /lib/marvel/conn/cache.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/properties' 2 | 3 | class Marvel::Conn::Cache 4 | CachePair = Struct.new(:response, :etag) 5 | 6 | def initialize() 7 | @response_cache = {} 8 | @etag_pointers = {} 9 | end 10 | 11 | def put(r_type, new_etag, json) 12 | pair = pair(r_type) 13 | key = key(json) 14 | old_etag, _ = pair.response[key] 15 | record = [new_etag, json] 16 | 17 | Marvel::Properties.logger.debug("[#{r_type} Cache] Caching #{key} #{new_etag}") 18 | Marvel::Properties.logger.debug("[#{r_type} Cache] Dissociating tag: #{old_etag}") 19 | 20 | pair.etag.delete(old_etag) 21 | pair.response[key] = record 22 | pair.etag[new_etag] = record 23 | record 24 | end 25 | 26 | def fetch(r_type, etag) 27 | Marvel::Properties.logger.info("[#{r_type} Cache] Fetching #{etag}") 28 | pair(r_type).etag[etag] 29 | end 30 | 31 | private 32 | 33 | def pair(r_type) 34 | CachePair[ 35 | @response_cache[r_type] ||= {}, 36 | @etag_pointers[r_type] ||= {} 37 | ] 38 | end 39 | 40 | def key(json_response) 41 | case json_response 42 | when Array then "list" 43 | when Hash then json_response['id'] 44 | else nil 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/marvel/model.rb: -------------------------------------------------------------------------------- 1 | module Heroku 2 | module Model 3 | require 'heroku/model/model_helper' 4 | require 'heroku/model/array_proxy' 5 | require 'heroku/model/account' 6 | require 'heroku/model/app_list' 7 | require 'heroku/model/app' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/marvel/properties.rb: -------------------------------------------------------------------------------- 1 | require 'marvel/version' 2 | 3 | module Marvel 4 | class Properties 5 | require 'marvel/properties/null_logger' 6 | 7 | USER_AGENT = "Marvel API Gem #{Marvel::VERSION}" 8 | @@public_key = nil 9 | @@private_key = nil 10 | @@logger = nil 11 | 12 | def self.public_key 13 | @@public_key 14 | end 15 | 16 | def self.private_key 17 | @@private_key 18 | end 19 | 20 | def self.public_key=(key) 21 | raise ArgumentError, "Need an API Public Key" if key.nil? 22 | @@public_key = key 23 | key 24 | end 25 | 26 | def self.private_key=(key) 27 | raise ArgumentError, "Need an API Private_key Key" if key.nil? 28 | @@private_key = key 29 | key 30 | end 31 | 32 | def self.logger 33 | @@logger || NullLogger.new 34 | end 35 | 36 | def self.logger=(logger) 37 | @@logger = logger 38 | end 39 | 40 | module ConfigMethods 41 | def configure # yield 42 | yield Marvel::Properties 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/marvel/properties/null_logger.rb: -------------------------------------------------------------------------------- 1 | module Marvel 2 | class Properties 3 | class NullLogger 4 | 5 | def info( msg) 6 | puts msg 7 | end 8 | def warn( msg) 9 | puts msg 10 | end 11 | def debug( msg) 12 | puts msg 13 | end 14 | def error( msg) 15 | puts msg 16 | end 17 | def unknown(msg) 18 | puts msg 19 | end 20 | 21 | def tagged(tag) # yields 22 | yield 23 | end 24 | 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/marvel/version.rb: -------------------------------------------------------------------------------- 1 | module Marvel 2 | VERSION = "0.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /lib/marvel_api.rb: -------------------------------------------------------------------------------- 1 | module Marvel 2 | #Crowdbotics 3 | require 'marvel/properties' 4 | require 'marvel/conn' 5 | #require 'marvel/model' 6 | require 'marvel/api' 7 | end 8 | -------------------------------------------------------------------------------- /marvel.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'marvel/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "marvel-api" 8 | spec.version = Marvel::VERSION 9 | spec.authors = ["Ritesh Choudhary", "Mukesh Patel"] 10 | spec.email = ["ritesh.strive@gmail.com", "mukesh.strive@gmail.com"] 11 | spec.description = %q{Ruby Client for Marvel API's just add gem in your project for using the Marvel API.} 12 | spec.summary = %q{Ruby client for the Marvel API.} 13 | spec.homepage = "" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_development_dependency "bundler", "~> 1.3" 22 | #spec.add_development_dependency "rake", "~> 10.3" 23 | spec.add_development_dependency "rspec", "~> 3" 24 | end 25 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | Bundler.setup 2 | 3 | require 'marvel_api' 4 | 5 | RSpec.configure do |config| 6 | config.run_all_when_everything_filtered = true 7 | config.filter_run :focus 8 | 9 | # Run specs in random order to surface order dependencies. If you find an 10 | # order dependency and want to debug it, you can fix the order by providing 11 | # the seed, which is printed after each run. 12 | # --seed 1234 13 | config.order = 'random' 14 | end 15 | --------------------------------------------------------------------------------