lib/thumbtack/posts.rb
# frozen_string_literal: true
module Thumbtack
# Wraps API calls related to posts
class Posts
attr_reader :client
# Initialize a Posts
#
# @param [Client] client
# client to communicate with the Pinboard API
#
# @api private
def initialize(client)
@client = client
end
# Fetch the most recent time a bookmark was added, updated, or deleted
#
# @example
# update_time = posts.update
#
# @return [Time]
#
# @api public
#
# @see https://pinboard.in/api/#posts_update
def update
response = client.get("/posts/update")
Types::Time.deserialize response.fetch("update_time")
end
# Add a bookmark
#
# @example
# posts.add(url, description, tags: ['one', 'two', 'three'])
#
# @param [String] url
# the URL of the bookmark
# @param [String] description
# title of the bookmark
# @param [Hash] options
# options for the bookmark addition
# @option options [String] :extended
# a description of the bookmark
# @option options [Array[String]] :tags
# a list of up to 100 tags
# @option options [Time] :dt
# the creation time for this bookmark
# @option options [Boolean] :replace
# if true, replace any existing bookmark with the same URL
# @option options [Boolean] :shared
# if true, make the bookmark public
# @option options [Boolean] :toread
# if true, mark the bookmark unread
#
# @return [self]
#
# @api public
#
# @see https://pinboard.in/api/#posts_add
def add(url, description, options = EMPTY_HASH)
parameters = Specification.new(
url: Types::URL,
description: Types::Text,
extended: Types::Text,
tags: Types::Tags,
dt: Types::Time,
replace: Types::Boolean,
shared: Types::Boolean,
toread: Types::Boolean
).parameters({url: url, description: description}.merge(options))
client.action("/posts/add", parameters)
self
end
# Delete a bookmark
#
# @example
# posts.delete(url)
#
# @param [String] url
# the URL of the bookmark to delete
#
# @return [self]
#
# @api public
#
# @see https://pinboard.in/api/#posts_delete
def delete(url)
parameters = Specification.new(url: Types::URL).parameters(url: url)
client.action("/posts/delete", parameters)
self
end
# Fetch one or more bookmarks
#
# @example
# bookmarks = posts.get(tag: ['one', 'two', 'three'])
#
# @param [Hash] options
# options to filter the results by
# @option options [Array<String>] :tag
# up to three tags to filter by
# @option options [Time] :dt
# which day the results were bookmarked
# @option options [String] :url
# the URL for this bookmark
# @option options [Boolean] :meta
# if true, include the change detection signature in the results
#
# @return [Array<Post>]
#
# @api public
#
# @see https://pinboard.in/api/#posts_get
def get(options = EMPTY_HASH)
parameters = Specification.new(
tag: Types::Tags,
dt: Types::Time,
url: Types::URL,
meta: Types::Boolean
).parameters(options)
posts_from client.get("/posts/get", parameters)
end
# List the most recent bookmarks
#
# @example
# bookmarks = posts.recent(tag: ['one', 'two', 'three'], count: 25)
#
# @param [Hash] options
# options to filter the results by
# @option options [Array<String>] :tag
# up to three tags to filter by
# @option options [Integer] :count
# the number of results to return
#
# @return [Array<Post>]
#
# @api public
#
# @see https://pinboard.in/api/#posts_recent
def recent(options = EMPTY_HASH)
parameters = Specification.new(
tag: Types::Tags,
count: Types::Integer
).parameters(options)
posts_from client.get("/posts/recent", parameters)
end
# List all bookmarks
#
# @example
# posts.all(todt: yesterday, meta: true, tag: ['one', 'two', 'three'])
#
# @param [Hash] options
# options to filter the results by
# @option options [Array<String>] :tag
# up to three tags to filter by
# @option options [Array<String>] :start
# an offset value
# @option options [Array<String>] :results
# number of results to return
# @option options [Time] :fromdt
# limit results to those created after this time
# @option options [Time] :todt
# limit results to those created before this time
# @option options [Boolean] :meta
# if true, include the change detection signature in the results
#
# @return [Array<Post>]
#
# @api public
#
# @see https://pinboard.in/api/#posts_all
def all(options = EMPTY_HASH)
parameters = Specification.new(
tag: Types::Tags,
start: Types::Integer,
results: Types::Integer,
fromdt: Types::Time,
todt: Types::Time,
meta: Types::Boolean
).parameters(options)
results = client.get("/posts/all", parameters)
results.map { |post_hash| Post.from_hash(post_hash) }
end
# List popular and recommended tags for a URL
#
# @example
# suggestion = posts.suggest(url)
#
# @param [String] url
# URL to fetch suggested tags for
#
# Returns a Hash with two entries, :popular is a list of popular tags,
# :recommended is a list of recommended tags.
#
# @return [Array<Suggestion>]
#
# @api public
#
# @see https://pinboard.in/api/#posts_suggest
def suggest(url)
parameters = Specification.new(url: Types::URL).parameters(url: url)
Suggestion.from_array(client.get("/posts/suggest", parameters))
end
# List dates with the number of bookmarks created on each
#
# @example
# dates = posts.dates(tag: ['one', 'two', 'three'])
#
# @param [Hash] options
# options to filter the results by
# @option options [Array<String>] :tag
# up to three tags to filter by
#
# @return [Hash{Date => Integer}]
# dates on which bookmarks were created associated with the number of
# bookmarks created on that date
#
# @api public
#
# @see https://pinboard.in/api/#posts_dates
def dates(options = EMPTY_HASH)
parameters = Specification.new(tag: Types::Tags).parameters(options)
response = client.get("/posts/dates", parameters)
dates_with_counts_from(response)
end
private
# Create Post objects from posts response
#
# @return [Array<Post>]
#
# @api private
def posts_from(response)
response.fetch("posts", EMPTY_ARRAY).map do |post_hash|
Post.from_hash(post_hash)
end
end
# Create Hash of dates to counts from dates response
#
# @return [Hash{Date => Integer}]
#
# @api private
def dates_with_counts_from(response)
entries = response.fetch("dates", EMPTY_HASH).map do |date, count|
[Types::Date.deserialize(date), count.to_i]
end
Hash[entries]
end
end
end