pinboard_api 0.1.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +5 -1
- data/README.md +81 -16
- data/Rakefile +10 -0
- data/lib/core_ext/array.rb +11 -0
- data/lib/core_ext/hash.rb +8 -0
- data/lib/pinboard_api.rb +24 -18
- data/lib/pinboard_api/post.rb +103 -21
- data/lib/pinboard_api/tag.rb +11 -9
- data/lib/pinboard_api/user.rb +1 -1
- data/lib/pinboard_api/version.rb +1 -1
- data/spec/core_ext/array_spec.rb +11 -0
- data/spec/core_ext/hash_spec.rb +18 -0
- data/spec/fixtures/vcr_cassettes/posts/all/custom_count.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/all/custom_tag.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/all/custom_times.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/all/default_values.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/all/not_found.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/dates/custom_tag.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/dates/default_values.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/delete/unsuccessful_class.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/destroy/successful_class.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/destroy/successful_instance.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/destroy/unsuccessful_instance.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/find/found.json +1 -1
- data/spec/fixtures/vcr_cassettes/posts/find/not_found.json +1 -1
- data/spec/fixtures/vcr_cassettes/posts/recent/custom_count.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/recent/custom_tag.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/recent/default_values.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/suggest.json +1 -0
- data/spec/fixtures/vcr_cassettes/posts/update.json +1 -1
- data/spec/fixtures/vcr_cassettes/tags/all.json +1 -1
- data/spec/fixtures/vcr_cassettes/tags/destroy/successful_class.json +1 -0
- data/spec/fixtures/vcr_cassettes/tags/destroy/successful_instance.json +1 -0
- data/spec/fixtures/vcr_cassettes/tags/destroy/unsuccessful_class.json +1 -0
- data/spec/fixtures/vcr_cassettes/tags/destroy/unsuccessful_instance.json +1 -0
- data/spec/fixtures/vcr_cassettes/tags/find/found.json +1 -1
- data/spec/fixtures/vcr_cassettes/tags/find/not_found.json +1 -1
- data/spec/fixtures/vcr_cassettes/tags/rename/successful.json +1 -1
- data/spec/fixtures/vcr_cassettes/tags/rename/unsuccessful.json +1 -1
- data/spec/fixtures/vcr_cassettes/user/secret.json +1 -1
- data/spec/pinboard_api_spec.rb +0 -4
- data/spec/post_spec.rb +358 -29
- data/spec/spec_helper.rb +8 -4
- data/spec/tag_spec.rb +27 -11
- metadata +48 -7
- data/spec/fixtures/vcr_cassettes/tags/delete/successful.json +0 -1
- data/spec/fixtures/vcr_cassettes/tags/delete/unsuccessful.json +0 -1
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # PinboardApi
         | 
| 1 | 
            +
            # PinboardApi [](http://travis-ci.org/phlipper/pinboard_api) [](https://codeclimate.com/github/phlipper/pinboard_api)
         | 
| 2 2 |  | 
| 3 3 | 
             
            ## Description
         | 
| 4 4 |  | 
| @@ -9,8 +9,13 @@ This client aims to cover all of the Pinboard [API v1](https://pinboard.in/api/) | |
| 9 9 |  | 
| 10 10 | 
             
            ## Requirements
         | 
| 11 11 |  | 
| 12 | 
            -
            * This library requires Ruby 1.9.2 or newer.
         | 
| 13 12 | 
             
            * You must have a paid Pinboard account to use the API. It is a great service and you can [signup here](https://pinboard.in/signup/) if you don't already have an account.
         | 
| 13 | 
            +
            * Currently tested on the following Ruby versions:
         | 
| 14 | 
            +
              * 1.9.2
         | 
| 15 | 
            +
              * 1.9.3
         | 
| 16 | 
            +
              * JRuby (1.9 mode)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            _Note:_ Specs are currently passing on Rubinius with `RBXOPT=-X19` on my local machine but there is a failing spec on [Travis CI](http://travis-ci.org/#!/phlipper/pinboard_api). I will update the `README` with official support for Rubinus once everything runs smoothly on Travis.
         | 
| 14 19 |  | 
| 15 20 |  | 
| 16 21 | 
             
            ## Installation
         | 
| @@ -34,6 +39,22 @@ $ gem install pinboard_api | |
| 34 39 | 
             
            ```
         | 
| 35 40 |  | 
| 36 41 |  | 
| 42 | 
            +
            ## Getting Started
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            You will need to set your username and password for the Pinboard service.
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ```ruby
         | 
| 47 | 
            +
            PinboardApi.username = "phlipper"
         | 
| 48 | 
            +
            PinboardApi.password = "[REDACTED]"
         | 
| 49 | 
            +
            ```
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            You may also set the SSL options which will be passed through to [Faraday](https://github.com/technoweenie/faraday#readme):
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            ```ruby
         | 
| 54 | 
            +
            PinboardApi.ssl_options = { ca_file: "/opt/local/share/curl/curl-ca-bundle.crt" }
         | 
| 55 | 
            +
            ```
         | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
| 37 58 | 
             
            ## Usage
         | 
| 38 59 |  | 
| 39 60 | 
             
            The `PinboardApi` namespace implements the 3 primary object types: `Post`, `Tag`, and `User`.
         | 
| @@ -50,24 +71,63 @@ PinboardApi::Post.update | |
| 50 71 | 
             
            ```
         | 
| 51 72 |  | 
| 52 73 | 
             
            * ~~[posts/add](https://pinboard.in/api#posts_add) - add a new bookmark~~
         | 
| 53 | 
            -
            *  | 
| 74 | 
            +
            * [posts/delete](https://pinboard.in/api#posts_delete) - delete an existing bookmark
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            ```ruby
         | 
| 77 | 
            +
            post = PinboardApi::Post.find(url: "https://pinboard.in/u:phlipper").first
         | 
| 78 | 
            +
            post.destroy
         | 
| 79 | 
            +
            # => #<PinboardApi::Post:0x007ffcb5166cf0 @description="Pinboard - antisocial bookmarking", @extended="", @hash="bc857ba651d134be0c9a5267e943c3ce", @url="https://pinboard.in/u:phlipper", @meta=nil, @tags="test", @time="2012-07-11T09:16:14Z">
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            PinboardApi::Post.destroy("https://pinboard.in/u:phlipper")
         | 
| 82 | 
            +
            # => #<PinboardApi::Post:0x007f98d6946d78 @description="Pinboard - antisocial bookmarking", @extended="", @hash="bc857ba651d134be0c9a5267e943c3ce", @url="https://pinboard.in/u:phlipper", @meta=nil, @tags="test", @time="2012-07-11T09:17:36Z">
         | 
| 83 | 
            +
            ```
         | 
| 84 | 
            +
             | 
| 54 85 | 
             
            * [posts/get](https://pinboard.in/api#posts_get) - get bookmark for a single date, or fetch specific items by URL
         | 
| 55 86 |  | 
| 56 87 | 
             
            ```ruby
         | 
| 57 88 | 
             
            PinboardApi::Post.find(tag: "test")
         | 
| 58 | 
            -
            # => [#<PinboardApi::Post:0x007fdce4547388 @description="Test.com – Certification Program Management – Create Online Tests with This Authoring, Management, Training and E-Learning Software", @extended="", @hash="dbb720d788ffaeb0afb7572104072f4a", @ | 
| 89 | 
            +
            # => [#<PinboardApi::Post:0x007fdce4547388 @description="Test.com – Certification Program Management – Create Online Tests with This Authoring, Management, Training and E-Learning Software", @extended="", @hash="dbb720d788ffaeb0afb7572104072f4a", @url="http://test.com/", @tags="test junk", @time="2012-07-07T04:18:28Z">, ...]
         | 
| 59 90 |  | 
| 60 91 | 
             
            PinboardApi::Post.find(hash: "dbb720d788ffaeb0afb7572104072f4a", meta: "yes")
         | 
| 61 | 
            -
            # => [#<PinboardApi::Post:0x007fac2b9d6690 @description="Test.com – Certification Program Management – Create Online Tests with This Authoring, Management, Training and E-Learning Software", @extended="", @hash="dbb720d788ffaeb0afb7572104072f4a", @href="http://test.com/", @meta="73b192512e3e4829806f5eee0a6b456d", @tags="test junk", @time="2012-07-07T04:18:28Z">, ...]
         | 
| 62 | 
            -
             | 
| 63 92 | 
             
            PinboardApi::Post.find(dt: Date.parse("2012-07-07"))
         | 
| 64 | 
            -
            # => [#<PinboardApi::Post:0x007fac2ba0fdf0 @description="Test.com – Certification Program Management – Create Online Tests with This Authoring, Management, Training and E-Learning Software", @extended="", @hash="dbb720d788ffaeb0afb7572104072f4a", @href="http://test.com/", @meta=nil, @tags="test junk", @time="2012-07-07T04:18:28Z">, ...]
         | 
| 65 93 | 
             
            ```
         | 
| 66 94 |  | 
| 67 | 
            -
            *  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 95 | 
            +
            * [posts/dates](https://pinboard.in/api#posts_dates) - list dates on which bookmarks were posted
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            ```ruby
         | 
| 98 | 
            +
            PinboardApi::Post.dates
         | 
| 99 | 
            +
            # => [{"count"=>1, "date"=>#<Date: 2012-07-10 ((2456119j,0s,0n),+0s,2299161j)>}, {"count"=>3, "date"=>#<Date: 2012-07-08 ((2456117j,0s,0n),+0s,2299161j)>}, ...]
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            PinboardApi::Post.dates(tag: "ruby")
         | 
| 102 | 
            +
            ```
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            * [posts/recent](https://pinboard.in/api#posts_recent) - fetch recent bookmarks
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            ```ruby
         | 
| 107 | 
            +
            PinboardApi::Post.recent
         | 
| 108 | 
            +
            # => [#<PinboardApi::Post:0x007ffe150e1fd0 @description="Techniques to Secure Your Website with Ruby on Rails..."> ...]
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            PinboardApi::Post.recent(count: 3)
         | 
| 111 | 
            +
            PinboardApi::Post.recent(tag: "ruby")
         | 
| 112 | 
            +
            PinboardApi::Post.recent(count: 25, tag: ["ruby", "programming"])
         | 
| 113 | 
            +
            ```
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            * [posts/all](https://pinboard.in/api#posts_all) - fetch all bookmarks by date, tag, or range
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            ```ruby
         | 
| 118 | 
            +
            PinboardApi::Post.all
         | 
| 119 | 
            +
            # => [#<PinboardApi::Post:0x007ffe150e1fd0 @description="Techniques to Secure Your Website with Ruby on Rails..."> ...]
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            PinboardApi::Post.all(tag: %w[ruby programming], meta: true, results: 30)
         | 
| 122 | 
            +
            PinboardApi::Post.all(start: 50, fromdt: 2.weeks.ago, todt: 1.week.ago)
         | 
| 123 | 
            +
            ```
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            * [posts/suggest](https://pinboard.in/api#posts_suggest) - fetch popular and recommended tags for a url
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            ```ruby
         | 
| 128 | 
            +
            PinboardApi::Post.suggest("http://blog.com")
         | 
| 129 | 
            +
            # => {"popular"=>["hosting", "blogs", "blog", "free"], "recommended"=>["blog", "blogging", "blogs", "free"]}
         | 
| 130 | 
            +
            ```
         | 
| 71 131 |  | 
| 72 132 |  | 
| 73 133 | 
             
            ### Tag
         | 
| @@ -86,13 +146,11 @@ PinboardApi::Tag.find("leadership") | |
| 86 146 |  | 
| 87 147 | 
             
            ```ruby
         | 
| 88 148 | 
             
            tag = PinboardApi::Tag.find("foo")
         | 
| 149 | 
            +
            tag.destroy
         | 
| 89 150 | 
             
            # => #<PinboardApi::Tag:0x007fdce45f56e0 @name="foo", @count=1>
         | 
| 90 151 |  | 
| 91 | 
            -
             | 
| 92 | 
            -
            # => #<PinboardApi::Tag: | 
| 93 | 
            -
             | 
| 94 | 
            -
            tag = PinboardApi::Tag.find("foo")
         | 
| 95 | 
            -
            # => nil
         | 
| 152 | 
            +
            PinboardApi::Tag.destroy("foo")
         | 
| 153 | 
            +
            # => #<PinboardApi::Tag:0x007fdce45f20f8 @name="foo", @count=1>
         | 
| 96 154 | 
             
            ```
         | 
| 97 155 |  | 
| 98 156 | 
             
            * [tags/rename](https://pinboard.in/api#tags_rename) - rename a tag
         | 
| @@ -116,6 +174,13 @@ PinboardApi::User.secret | |
| 116 174 | 
             
            ```
         | 
| 117 175 |  | 
| 118 176 |  | 
| 177 | 
            +
            ## TODO
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            * Implement Post.add/create
         | 
| 180 | 
            +
            * Implement support for the new `[auth_token](http://pinboard.in/api/#authentication)`
         | 
| 181 | 
            +
            * Cleanup/refactor internal exception handling
         | 
| 182 | 
            +
             | 
| 183 | 
            +
             | 
| 119 184 | 
             
            ## Contributing
         | 
| 120 185 |  | 
| 121 186 | 
             
            1. Fork it
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/pinboard_api.rb
    CHANGED
    
    | @@ -1,6 +1,9 @@ | |
| 1 1 | 
             
            require "faraday"
         | 
| 2 2 | 
             
            require "faraday_middleware"
         | 
| 3 3 |  | 
| 4 | 
            +
            require "core_ext/array"
         | 
| 5 | 
            +
            require "core_ext/hash"
         | 
| 6 | 
            +
             | 
| 4 7 | 
             
            require "pinboard_api/post"
         | 
| 5 8 | 
             
            require "pinboard_api/tag"
         | 
| 6 9 | 
             
            require "pinboard_api/user"
         | 
| @@ -10,30 +13,33 @@ module PinboardApi | |
| 10 13 |  | 
| 11 14 | 
             
              class << self
         | 
| 12 15 | 
             
                attr_accessor :username, :password, :adapter, :ssl_options
         | 
| 16 | 
            +
              end
         | 
| 13 17 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 18 | 
            +
              def self.adapter
         | 
| 19 | 
            +
                @adapter ||= :net_http
         | 
| 20 | 
            +
              end
         | 
| 17 21 |  | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 22 | 
            +
              def self.ssl_options
         | 
| 23 | 
            +
                @ssl_options ||= {}
         | 
| 24 | 
            +
              end
         | 
| 21 25 |  | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 26 | 
            +
              def self.api_version
         | 
| 27 | 
            +
                "v1"
         | 
| 28 | 
            +
              end
         | 
| 25 29 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 30 | 
            +
              def self.api_url
         | 
| 31 | 
            +
                "https://#{username}:#{password}@api.pinboard.in"
         | 
| 32 | 
            +
              end
         | 
| 29 33 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                  end
         | 
| 34 | 
            +
              def self.connection
         | 
| 35 | 
            +
                Faraday.new(url: api_url, ssl: ssl_options) do |builder|
         | 
| 36 | 
            +
                  builder.response :logger if ENV["PINBOARD_LOGGER"]
         | 
| 37 | 
            +
                  builder.response :xml, content_type: /\bxml$/
         | 
| 38 | 
            +
                  builder.adapter adapter
         | 
| 36 39 | 
             
                end
         | 
| 37 40 | 
             
              end
         | 
| 38 41 |  | 
| 42 | 
            +
              def self.request(path, options = {}, &blk)
         | 
| 43 | 
            +
                PinboardApi.connection.get(path, options, &blk)
         | 
| 44 | 
            +
              end
         | 
| 39 45 | 
             
            end
         | 
    
        data/lib/pinboard_api/post.rb
    CHANGED
    
    | @@ -1,55 +1,137 @@ | |
| 1 1 | 
             
            module PinboardApi
         | 
| 2 2 | 
             
              class Post
         | 
| 3 3 |  | 
| 4 | 
            -
                attr_reader :description, :extended, :hash, : | 
| 4 | 
            +
                attr_reader :description, :extended, :hash, :meta, :url
         | 
| 5 5 |  | 
| 6 6 | 
             
                def initialize(attributes = {})
         | 
| 7 | 
            +
                  attributes.stringify_keys!
         | 
| 8 | 
            +
             | 
| 7 9 | 
             
                  @description = attributes["description"]
         | 
| 8 10 | 
             
                  @extended    = attributes["extended"]
         | 
| 9 11 | 
             
                  @hash        = attributes["hash"]
         | 
| 10 | 
            -
                  @href        = attributes["href"]
         | 
| 11 12 | 
             
                  @meta        = attributes["meta"]
         | 
| 13 | 
            +
                  @url         = attributes["url"] || attributes["href"]
         | 
| 12 14 | 
             
                  @tags        = attributes["tags"] || attributes["tag"]
         | 
| 13 15 | 
             
                  @time        = attributes["time"] || Time.now
         | 
| 14 16 | 
             
                end
         | 
| 15 17 |  | 
| 16 18 | 
             
                def time
         | 
| 17 | 
            -
                   | 
| 18 | 
            -
                    @time
         | 
| 19 | 
            -
                  elsif @time.is_a?(Date)
         | 
| 20 | 
            -
                    @time.to_time
         | 
| 21 | 
            -
                  else
         | 
| 22 | 
            -
                    Time.parse(@time)
         | 
| 23 | 
            -
                  end
         | 
| 19 | 
            +
                  @time.is_a?(String) ? Time.parse(@time) : @time.to_time
         | 
| 24 20 | 
             
                end
         | 
| 25 21 |  | 
| 26 22 | 
             
                def tags
         | 
| 27 23 | 
             
                  @tags.is_a?(String) ? @tags.split(/\s+/) : @tags
         | 
| 28 24 | 
             
                end
         | 
| 29 25 |  | 
| 26 | 
            +
                def destroy
         | 
| 27 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/delete"
         | 
| 28 | 
            +
                  body = PinboardApi.request(path, url: @url).body["result"]
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  if body && body.fetch("code", "") == "done"
         | 
| 31 | 
            +
                    self
         | 
| 32 | 
            +
                  else
         | 
| 33 | 
            +
                    raise RuntimeError, "unknown response"
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def self.destroy(url)
         | 
| 38 | 
            +
                  if post = find(url: url).first
         | 
| 39 | 
            +
                    post.destroy
         | 
| 40 | 
            +
                  else
         | 
| 41 | 
            +
                    raise RuntimeError, "unknown response"
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def self.all(options = {})
         | 
| 46 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/all"
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  tag    = tag_param_string(options[:tag])
         | 
| 49 | 
            +
                  fromdt = dt_param_string(options[:fromdt])
         | 
| 50 | 
            +
                  todt   = dt_param_string(options[:todt])
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  response = PinboardApi.request(path) do |req|
         | 
| 53 | 
            +
                    req.params["tag"]     = tag if tag
         | 
| 54 | 
            +
                    req.params["start"]   = options[:start] if options[:start]
         | 
| 55 | 
            +
                    req.params["results"] = options[:results] if options[:results]
         | 
| 56 | 
            +
                    req.params["fromdt"]  = fromdt if fromdt
         | 
| 57 | 
            +
                    req.params["todt"]    = todt if todt
         | 
| 58 | 
            +
                    req.params["meta"]    = 1 if options[:meta]
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  extract_posts(response.body["posts"])
         | 
| 62 | 
            +
                end
         | 
| 30 63 |  | 
| 31 64 | 
             
                def self.find(options = {})
         | 
| 32 65 | 
             
                  path = "/#{PinboardApi.api_version}/posts/get"
         | 
| 33 | 
            -
                  response = PinboardApi. | 
| 66 | 
            +
                  response = PinboardApi.request(path) do |req|
         | 
| 34 67 | 
             
                    options.each_pair { |k,v| req.params[k.to_s] = v }
         | 
| 35 68 | 
             
                  end
         | 
| 69 | 
            +
                  extract_posts(response.body["posts"])
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def self.last_update
         | 
| 73 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/update"
         | 
| 74 | 
            +
                  body = PinboardApi.request(path).body
         | 
| 75 | 
            +
                  Time.parse(body["update"]["time"])
         | 
| 76 | 
            +
                end
         | 
| 36 77 |  | 
| 37 | 
            -
             | 
| 38 | 
            -
                   | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 78 | 
            +
                def self.suggest(url)
         | 
| 79 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/suggest"
         | 
| 80 | 
            +
                  response = PinboardApi.request(path, url: url)
         | 
| 81 | 
            +
                  response.body["suggested"]
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                def self.recent(options = {})
         | 
| 85 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/recent"
         | 
| 86 | 
            +
                  tag = tag_param_string(options[:tag])
         | 
| 87 | 
            +
                  count = options[:count]
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  response = PinboardApi.request(path) do |req|
         | 
| 90 | 
            +
                    req.params["tag"] = tag if tag
         | 
| 91 | 
            +
                    req.params["count"] = count if count
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  extract_posts(response.body["posts"])
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def self.dates(options = {})
         | 
| 98 | 
            +
                  path = "/#{PinboardApi.api_version}/posts/dates"
         | 
| 99 | 
            +
                  tag = tag_param_string(options[:tag])
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  response = PinboardApi.request(path) do |req|
         | 
| 102 | 
            +
                    req.params["tag"] = tag if tag
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  dates = response.body["dates"]["date"]
         | 
| 106 | 
            +
                  dates.map do |date|
         | 
| 107 | 
            +
                    { "count" => date["count"].to_i, "date" =>  Date.parse(date["date"]) }
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
             | 
| 112 | 
            +
                def self.extract_posts(payload)
         | 
| 113 | 
            +
                  unless payload.respond_to?(:keys) && payload.keys.include?("post")
         | 
| 114 | 
            +
                    return Array.new
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  # response.body["posts"] - "429 Too Many Requests.  Wait 60 seconds before fetching posts/all again."
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  payload.inject([]) do |collection, (key, attrs)|
         | 
| 120 | 
            +
                    if key == "post"
         | 
| 121 | 
            +
                      Array.wrap(attrs).each do |post|
         | 
| 122 | 
            +
                        Array.wrap(collection) << new(post)
         | 
| 123 | 
            +
                      end
         | 
| 42 124 | 
             
                    end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                    Array.new
         | 
| 125 | 
            +
                    collection
         | 
| 45 126 | 
             
                  end
         | 
| 46 127 | 
             
                end
         | 
| 47 128 |  | 
| 48 | 
            -
                def self. | 
| 49 | 
            -
                   | 
| 50 | 
            -
                  body = PinboardApi.connection.get(path).body
         | 
| 51 | 
            -
                  Time.parse(body["update"]["time"])
         | 
| 129 | 
            +
                def self.dt_param_string(time)
         | 
| 130 | 
            +
                  time.nil? ? nil : time.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
         | 
| 52 131 | 
             
                end
         | 
| 53 132 |  | 
| 133 | 
            +
                def self.tag_param_string(tags)
         | 
| 134 | 
            +
                  tags.nil? ? nil : Array.wrap(tags).join(",")
         | 
| 135 | 
            +
                end
         | 
| 54 136 | 
             
              end
         | 
| 55 137 | 
             
            end
         | 
    
        data/lib/pinboard_api/tag.rb
    CHANGED
    
    | @@ -9,25 +9,22 @@ module PinboardApi | |
| 9 9 |  | 
| 10 10 | 
             
                def rename(new_name)
         | 
| 11 11 | 
             
                  path = "/#{PinboardApi.api_version}/tags/rename"
         | 
| 12 | 
            -
                  response = PinboardApi. | 
| 13 | 
            -
                    req.params["old"] =  | 
| 12 | 
            +
                  response = PinboardApi.request(path) do |req|
         | 
| 13 | 
            +
                    req.params["old"] = @name
         | 
| 14 14 | 
             
                    req.params["new"] = new_name.to_s
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 | 
             
                  body = response.body
         | 
| 17 17 |  | 
| 18 18 | 
             
                  if body["result"] == "done"
         | 
| 19 | 
            -
                    Tag.new("name" => new_name, "count" =>  | 
| 19 | 
            +
                    Tag.new("name" => new_name, "count" => @count)
         | 
| 20 20 | 
             
                  else
         | 
| 21 21 | 
             
                    raise body["result"].to_s
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 | 
            -
                def  | 
| 25 | 
            +
                def destroy
         | 
| 26 26 | 
             
                  path = "/#{PinboardApi.api_version}/tags/delete"
         | 
| 27 | 
            -
                   | 
| 28 | 
            -
                    req.params["tag"] = self.name
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
                  body = response.body
         | 
| 27 | 
            +
                  body = PinboardApi.request(path, tag: @name).body
         | 
| 31 28 |  | 
| 32 29 | 
             
                  if body["result"] == "done"
         | 
| 33 30 | 
             
                    self
         | 
| @@ -38,13 +35,18 @@ module PinboardApi | |
| 38 35 |  | 
| 39 36 | 
             
                def self.all
         | 
| 40 37 | 
             
                  path = "/#{PinboardApi.api_version}/tags/get"
         | 
| 41 | 
            -
                  body = PinboardApi. | 
| 38 | 
            +
                  body = PinboardApi.request(path).body
         | 
| 42 39 | 
             
                  body["tags"]["tag"].map { |tag| new(tag) }
         | 
| 40 | 
            +
                rescue
         | 
| 41 | 
            +
                  raise RuntimeError, "unknown response"
         | 
| 43 42 | 
             
                end
         | 
| 44 43 |  | 
| 45 44 | 
             
                def self.find(name)
         | 
| 46 45 | 
             
                  all.detect { |t| t.name == name }
         | 
| 47 46 | 
             
                end
         | 
| 48 47 |  | 
| 48 | 
            +
                def self.destroy(tag)
         | 
| 49 | 
            +
                  find(tag).destroy
         | 
| 50 | 
            +
                end
         | 
| 49 51 | 
             
              end
         | 
| 50 52 | 
             
            end
         |