flickollage 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +12 -0
- data/.travis.yml +14 -0
- data/Gemfile +3 -0
- data/README.md +27 -0
- data/bin/flickollage +8 -0
- data/flickollage.gemspec +26 -0
- data/lib/flickollage/cli.rb +44 -0
- data/lib/flickollage/collage.rb +80 -0
- data/lib/flickollage/dictionary.rb +47 -0
- data/lib/flickollage/image.rb +45 -0
- data/lib/flickollage/logger.rb +7 -0
- data/lib/flickollage.rb +32 -0
- data/spec/fixtures/cities.png +0 -0
- data/spec/fixtures/collage.jpg +0 -0
- data/spec/fixtures/mountains +24 -0
- data/spec/fixtures/mountains.png +0 -0
- data/spec/fixtures/rothko.jpg +0 -0
- data/spec/fixtures/vcr_cassettes/flickr.yml +112 -0
- data/spec/fixtures/vcr_cassettes/flickr_download.yml +4863 -0
- data/spec/fixtures/vcr_cassettes/flickr_download_not_found.yml +60 -0
- data/spec/fixtures/vcr_cassettes/flickr_not_found.yml +57 -0
- data/spec/lib/collage_spec.rb +68 -0
- data/spec/lib/dictionary_spec.rb +89 -0
- data/spec/lib/image_spec.rb +78 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/flickollage_helpers.rb +11 -0
- data/spec/support/similar_image_matcher.rb +12 -0
- metadata +200 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0bf1524178358a9af7ccece83dff0511d631733f
|
4
|
+
data.tar.gz: 7b52460521ecd5ec1633f780b15c525ec9651afe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2acf6edde06c4bc7a5326ba2401949c1f564d9fada5236cc6f0d90ac05c963606788d564fba590bd83dd0af853a9116586747ab6796ba42187277140e40186b8
|
7
|
+
data.tar.gz: 05fdea90eb41ebd282ab9c1ee32c355de1baceeab78dd93b138a35b0516cb76f62c9919de0cc9a63137aa2ada5f8fed2fd1c7eac9ad3db5d7417268c69a151a2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Flickollage [![Gem Version](https://badge.fury.io/rb/flickollage.svg)](https://badge.fury.io/rb/flickollage) [![Build Status](https://travis-ci.org/alexandrz/flickollage.svg?branch=master)](https://travis-ci.org/alexandrz/flickollage)
|
2
|
+
|
3
|
+
A simple command-line tool that accepts a list of words as arguments and generates
|
4
|
+
a collage grid from ten top-rated images found on Flickr using the provided keywords.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
You can install Flickollage from rubygems. It requires Ruby version >= 2.0 and
|
9
|
+
ImageMagick or GraphicsMagick command-line tool.
|
10
|
+
|
11
|
+
$ gem install flickollage
|
12
|
+
|
13
|
+
## Flickr access key
|
14
|
+
|
15
|
+
You need to provide Flickr access key and shared secret. It can be done using environment
|
16
|
+
variables `FLICKR_API_KEY` and `FLICKR_SHARED_SECRET` or command-line options
|
17
|
+
`--flickr-api-key` and `--flickr-shared-key`.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
$ flickollage generate -n 2 --rows=1 --cols=2 --width=300 --height=200 Berlin 'New York'
|
22
|
+
|
23
|
+
![Cities Collage](spec/fixtures/cities.png)
|
24
|
+
|
25
|
+
$ flickollage generate --dict=spec/fixtures/mountains --output mountains.png
|
26
|
+
|
27
|
+
![Mountains Collage](spec/fixtures/mountains.png)
|
data/bin/flickollage
ADDED
data/flickollage.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'flickollage'
|
3
|
+
s.version = '0.0.3'
|
4
|
+
s.date = '2017-03-05'
|
5
|
+
s.summary = 'Flickollage Collage Generator'
|
6
|
+
s.description = 'Flickollage is a simple command line tool for generating collages'
|
7
|
+
s.authors = ['Aleksandr Zykov']
|
8
|
+
s.email = 'alexandrz@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/alexandrz/flickollage'
|
10
|
+
s.license = 'MIT'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
|
17
|
+
s.add_dependency 'thor', '~> 0.19'
|
18
|
+
s.add_dependency 'flickraw', '~> 0.9'
|
19
|
+
s.add_dependency 'mini_magick', '~> 4.6'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'dotenv'
|
23
|
+
s.add_development_dependency 'vcr'
|
24
|
+
s.add_development_dependency 'webmock'
|
25
|
+
s.add_development_dependency 'rubocop', '~> 0.47.1'
|
26
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'dotenv'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
# Flickollage Command Line Interface
|
6
|
+
module Flickollage
|
7
|
+
class CLI < ::Thor
|
8
|
+
include Logger
|
9
|
+
|
10
|
+
desc 'generate [LIST OF WORDS]', 'Generate collage from the list of words'
|
11
|
+
option :dict,
|
12
|
+
type: :string, aliases: '-d', default: Dictionary.default_dict_path,
|
13
|
+
desc: 'Path of the dictionatry file'
|
14
|
+
option :output,
|
15
|
+
type: :string, aliases: '-o', default: 'collage.png',
|
16
|
+
desc: 'Output image file name'
|
17
|
+
option :flickr_api_key,
|
18
|
+
type: :string,
|
19
|
+
desc: 'Flickr API Key, can also be set using environment variable'
|
20
|
+
option :flickr_shared_secret,
|
21
|
+
type: :string,
|
22
|
+
desc: 'Flickr Shared Secret, can also be set using environment variable'
|
23
|
+
option :number, type: :numeric, aliases: '-n', default: 10
|
24
|
+
option :rows, type: :numeric, aliases: '-r', default: 5
|
25
|
+
option :cols, type: :numeric, aliases: '-c', default: 2
|
26
|
+
option :width, type: :numeric, aliases: '-w', default: 200
|
27
|
+
option :height, type: :numeric, aliases: '-h', default: 150
|
28
|
+
option :verbose, type: :boolean, aliases: '-v'
|
29
|
+
long_desc <<-LONGDESC
|
30
|
+
`flickollage generate dolomites annapurna` will generate a photo collage.
|
31
|
+
|
32
|
+
You can provide flickr api key and shared secret using options described before
|
33
|
+
or environment variables `FLICKR_API_KEY` and `FLICKR_SHARED_SECRET`.
|
34
|
+
LONGDESC
|
35
|
+
def generate(*words)
|
36
|
+
Flickollage.init_logger(options)
|
37
|
+
return unless Flickollage.configure_flickraw(options)
|
38
|
+
Flickollage::Collage.new(words, options).generate_collage
|
39
|
+
rescue Flickollage::Error => e
|
40
|
+
logger.error(e.message)
|
41
|
+
logger.debug(e.inspect)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Flickollage
|
2
|
+
class Collage
|
3
|
+
include Logger
|
4
|
+
class Error < ::Flickollage::Error; end
|
5
|
+
|
6
|
+
attr_reader :dictionary
|
7
|
+
attr_reader :words
|
8
|
+
attr_reader :options
|
9
|
+
attr_reader :images
|
10
|
+
|
11
|
+
RETRY_LIMIT = 10
|
12
|
+
|
13
|
+
def initialize(words, options)
|
14
|
+
@words = words
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
init_dictionary
|
18
|
+
load_images
|
19
|
+
download_images
|
20
|
+
crop_images(options[:width], options[:height])
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_collage(path = nil)
|
24
|
+
path ||= options[:output]
|
25
|
+
MiniMagick::Tool::Montage.new do |montage|
|
26
|
+
images.each { |image| montage << image.image.path }
|
27
|
+
|
28
|
+
montage.geometry "#{options[:width]}x#{options[:height]}+0+0"
|
29
|
+
montage.tile "#{options[:cols]}x#{options[:rows]}"
|
30
|
+
montage.background 'black'
|
31
|
+
|
32
|
+
montage << path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def init_dictionary
|
39
|
+
@dictionary = Dictionary.new(options[:dict])
|
40
|
+
@dictionary.append(words)
|
41
|
+
rescue Flickollage::Dictionary::Error
|
42
|
+
@dictionary = Dictionary.new(words)
|
43
|
+
end
|
44
|
+
|
45
|
+
def download_images
|
46
|
+
images.each(&:download)
|
47
|
+
end
|
48
|
+
|
49
|
+
def crop_images(width, height)
|
50
|
+
images.each do |image|
|
51
|
+
image.crop(width, height)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def load_images
|
56
|
+
@images = []
|
57
|
+
options[:number].times do
|
58
|
+
@images << load_image
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_image(attempt = 1)
|
63
|
+
word = dictionary.pop
|
64
|
+
not_enought_words unless word
|
65
|
+
Image.new(word)
|
66
|
+
rescue Flickollage::Image::Error
|
67
|
+
too_many_attempts if attempt == RETRY_LIMIT
|
68
|
+
load_image(attempt + 1)
|
69
|
+
end
|
70
|
+
|
71
|
+
def not_enought_words
|
72
|
+
raise Flickollage::Error,
|
73
|
+
'Not enought words. Please, specify more words or provide a bigger dictionary.'
|
74
|
+
end
|
75
|
+
|
76
|
+
def too_many_attempts
|
77
|
+
raise Flickollage::Error, 'Could not load images. Please, try later.'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Flickollage
|
2
|
+
class Dictionary
|
3
|
+
class Error < ::Flickollage::Error; end
|
4
|
+
|
5
|
+
MAX_DICT_LENGTH = 1_500_000
|
6
|
+
|
7
|
+
COMMON_DICT_PATHS = %w(
|
8
|
+
/usr/share/dict/words
|
9
|
+
/usr/dict/words
|
10
|
+
).freeze
|
11
|
+
|
12
|
+
attr_reader :words
|
13
|
+
|
14
|
+
def initialize(path_or_words)
|
15
|
+
@words = []
|
16
|
+
load_from_file(path_or_words) if path_or_words.is_a?(String)
|
17
|
+
@words = path_or_words.reverse if path_or_words.is_a?(Array)
|
18
|
+
end
|
19
|
+
|
20
|
+
def pop
|
21
|
+
@words.pop
|
22
|
+
end
|
23
|
+
|
24
|
+
def append(words)
|
25
|
+
@words += words.reverse
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def load_from_file(path)
|
31
|
+
File.foreach(path).with_index do |line, i|
|
32
|
+
break if i >= MAX_DICT_LENGTH
|
33
|
+
line = line.chop
|
34
|
+
@words << line unless line.empty?
|
35
|
+
end
|
36
|
+
@words.shuffle!
|
37
|
+
rescue Errno::ENOENT
|
38
|
+
raise Error, 'Dictionary file not found'
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def default_dict_path
|
43
|
+
COMMON_DICT_PATHS.find { |path| File.exist?(path) } || COMMON_DICT_PATHS.first
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Flickollage
|
2
|
+
class Image
|
3
|
+
include Logger
|
4
|
+
class Error < ::Flickollage::Error; end
|
5
|
+
|
6
|
+
attr_reader :word
|
7
|
+
attr_reader :url
|
8
|
+
attr_accessor :image
|
9
|
+
|
10
|
+
def initialize(word)
|
11
|
+
@word = word
|
12
|
+
search_on_flickr(word)
|
13
|
+
end
|
14
|
+
|
15
|
+
def download
|
16
|
+
logger.debug("Downloading an image: #{url}")
|
17
|
+
@image = MiniMagick::Image.open(url)
|
18
|
+
file_not_found unless @image
|
19
|
+
@image
|
20
|
+
end
|
21
|
+
|
22
|
+
def crop(width, height)
|
23
|
+
image.combine_options do |b|
|
24
|
+
b.resize "#{width}x#{height}^"
|
25
|
+
b.gravity 'Center'
|
26
|
+
b.extent "#{width}x#{height}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def file_not_found
|
33
|
+
raise Error, "Failed to load an image for keyword '#{word}'."
|
34
|
+
end
|
35
|
+
|
36
|
+
def search_on_flickr(word)
|
37
|
+
photo = flickr.photos.search(tags: word, sort: 'interestingness-desc', per_page: 1)[0]
|
38
|
+
raise Error, 'Could not find an image using this keyword' unless photo
|
39
|
+
@url = FlickRaw.url_b(photo)
|
40
|
+
logger.debug("Found an image for keyword '#{word}': #{@url}")
|
41
|
+
rescue FlickRaw::FailedResponse
|
42
|
+
raise ::Flickollage::Error, 'Invalid Flickr API key'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/flickollage.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'flickraw'
|
2
|
+
require 'mini_magick'
|
3
|
+
|
4
|
+
module Flickollage
|
5
|
+
class Error < StandardError; end
|
6
|
+
class << self
|
7
|
+
attr_accessor :logger
|
8
|
+
|
9
|
+
def init_logger(options = {})
|
10
|
+
Flickollage.logger = ::Logger.new(STDOUT).tap do |logger|
|
11
|
+
logger.level = options[:verbose] ? ::Logger::DEBUG : ::Logger::INFO
|
12
|
+
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
13
|
+
"#{msg}\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure_flickraw(options)
|
19
|
+
FlickRaw.api_key = ENV['FLICKR_API_KEY'] || options[:flickr_api_key]
|
20
|
+
FlickRaw.shared_secret = ENV['FLICKR_SHARED_SECRET'] || options[:flickr_shared_secret]
|
21
|
+
return true if FlickRaw.api_key && FlickRaw.shared_secret
|
22
|
+
logger.error 'Flickr configuration is not provided.'
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'flickollage/logger.rb'
|
29
|
+
require 'flickollage/dictionary.rb'
|
30
|
+
require 'flickollage/image.rb'
|
31
|
+
require 'flickollage/collage.rb'
|
32
|
+
require 'flickollage/cli.rb'
|
Binary file
|
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Mont Blanc
|
2
|
+
Monte Rosa
|
3
|
+
Liskamm
|
4
|
+
Weisshorn
|
5
|
+
Matterhorn
|
6
|
+
Dent Blanche
|
7
|
+
Grand Combin
|
8
|
+
Finsteraarhorn
|
9
|
+
Zinalrothorn
|
10
|
+
Grandes Jorasses
|
11
|
+
|
12
|
+
|
13
|
+
Alphubel
|
14
|
+
Rimpfischhorn
|
15
|
+
Aletschhorn
|
16
|
+
Strahlhorn
|
17
|
+
Dent d'Hérens
|
18
|
+
Breithorn
|
19
|
+
Jungfrau
|
20
|
+
Aiguille Verte
|
21
|
+
Mönch
|
22
|
+
Barre des Écrins
|
23
|
+
Schreckhorn
|
24
|
+
Ober Gabelhorn
|
Binary file
|
Binary file
|
@@ -0,0 +1,112 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://api.flickr.com/services/rest/
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: method=flickr.reflection.getMethods&format=json&nojsoncallback=1
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- FlickRaw/0.9.9
|
16
|
+
Content-Type:
|
17
|
+
- application/x-www-form-urlencoded
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Sun, 05 Mar 2017 11:41:25 GMT
|
25
|
+
Content-Type:
|
26
|
+
- application/json
|
27
|
+
Content-Length:
|
28
|
+
- '1438'
|
29
|
+
P3p:
|
30
|
+
- policyref="https://policies.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM
|
31
|
+
DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND
|
32
|
+
PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
|
33
|
+
X-Content-Type-Options:
|
34
|
+
- nosniff
|
35
|
+
Cache-Control:
|
36
|
+
- private
|
37
|
+
X-Served-By:
|
38
|
+
- www245.flickr.bf1.yahoo.com
|
39
|
+
X-Frame-Options:
|
40
|
+
- SAMEORIGIN
|
41
|
+
Vary:
|
42
|
+
- Accept-Encoding
|
43
|
+
Age:
|
44
|
+
- '0'
|
45
|
+
Via:
|
46
|
+
- http/1.1 fts101.flickr.bf1.yahoo.com (ApacheTrafficServer [cMsSf ]), http/1.1
|
47
|
+
e20.ycpi.lob.yahoo.com (ApacheTrafficServer [cMsSf ])
|
48
|
+
Server:
|
49
|
+
- ATS
|
50
|
+
Connection:
|
51
|
+
- keep-alive
|
52
|
+
body:
|
53
|
+
encoding: ASCII-8BIT
|
54
|
+
string: '{"methods":{"method":[{"_content":"flickr.activity.userComments"},{"_content":"flickr.activity.userPhotos"},{"_content":"flickr.auth.checkToken"},{"_content":"flickr.auth.getFrob"},{"_content":"flickr.auth.getFullToken"},{"_content":"flickr.auth.getToken"},{"_content":"flickr.auth.oauth.checkToken"},{"_content":"flickr.auth.oauth.getAccessToken"},{"_content":"flickr.blogs.getList"},{"_content":"flickr.blogs.getServices"},{"_content":"flickr.blogs.postPhoto"},{"_content":"flickr.cameras.getBrandModels"},{"_content":"flickr.cameras.getBrands"},{"_content":"flickr.collections.getInfo"},{"_content":"flickr.collections.getTree"},{"_content":"flickr.commons.getInstitutions"},{"_content":"flickr.contacts.getList"},{"_content":"flickr.contacts.getListRecentlyUploaded"},{"_content":"flickr.contacts.getPublicList"},{"_content":"flickr.contacts.getTaggingSuggestions"},{"_content":"flickr.favorites.add"},{"_content":"flickr.favorites.getContext"},{"_content":"flickr.favorites.getList"},{"_content":"flickr.favorites.getPublicList"},{"_content":"flickr.favorites.remove"},{"_content":"flickr.galleries.addPhoto"},{"_content":"flickr.galleries.create"},{"_content":"flickr.galleries.editMeta"},{"_content":"flickr.galleries.editPhoto"},{"_content":"flickr.galleries.editPhotos"},{"_content":"flickr.galleries.getInfo"},{"_content":"flickr.galleries.getList"},{"_content":"flickr.galleries.getListForPhoto"},{"_content":"flickr.galleries.getPhotos"},{"_content":"flickr.groups.browse"},{"_content":"flickr.groups.discuss.replies.add"},{"_content":"flickr.groups.discuss.replies.delete"},{"_content":"flickr.groups.discuss.replies.edit"},{"_content":"flickr.groups.discuss.replies.getInfo"},{"_content":"flickr.groups.discuss.replies.getList"},{"_content":"flickr.groups.discuss.topics.add"},{"_content":"flickr.groups.discuss.topics.getInfo"},{"_content":"flickr.groups.discuss.topics.getList"},{"_content":"flickr.groups.getInfo"},{"_content":"flickr.groups.join"},{"_content":"flickr.groups.joinRequest"},{"_content":"flickr.groups.leave"},{"_content":"flickr.groups.members.getList"},{"_content":"flickr.groups.pools.add"},{"_content":"flickr.groups.pools.getContext"},{"_content":"flickr.groups.pools.getGroups"},{"_content":"flickr.groups.pools.getPhotos"},{"_content":"flickr.groups.pools.remove"},{"_content":"flickr.groups.search"},{"_content":"flickr.interestingness.getList"},{"_content":"flickr.machinetags.getNamespaces"},{"_content":"flickr.machinetags.getPairs"},{"_content":"flickr.machinetags.getPredicates"},{"_content":"flickr.machinetags.getRecentValues"},{"_content":"flickr.machinetags.getValues"},{"_content":"flickr.panda.getList"},{"_content":"flickr.panda.getPhotos"},{"_content":"flickr.people.findByEmail"},{"_content":"flickr.people.findByUsername"},{"_content":"flickr.people.getGroups"},{"_content":"flickr.people.getInfo"},{"_content":"flickr.people.getLimits"},{"_content":"flickr.people.getPhotos"},{"_content":"flickr.people.getPhotosOf"},{"_content":"flickr.people.getPublicGroups"},{"_content":"flickr.people.getPublicPhotos"},{"_content":"flickr.people.getUploadStatus"},{"_content":"flickr.photos.addTags"},{"_content":"flickr.photos.comments.addComment"},{"_content":"flickr.photos.comments.deleteComment"},{"_content":"flickr.photos.comments.editComment"},{"_content":"flickr.photos.comments.getList"},{"_content":"flickr.photos.comments.getRecentForContacts"},{"_content":"flickr.photos.delete"},{"_content":"flickr.photos.geo.batchCorrectLocation"},{"_content":"flickr.photos.geo.correctLocation"},{"_content":"flickr.photos.geo.getLocation"},{"_content":"flickr.photos.geo.getPerms"},{"_content":"flickr.photos.geo.photosForLocation"},{"_content":"flickr.photos.geo.removeLocation"},{"_content":"flickr.photos.geo.setContext"},{"_content":"flickr.photos.geo.setLocation"},{"_content":"flickr.photos.geo.setPerms"},{"_content":"flickr.photos.getAllContexts"},{"_content":"flickr.photos.getContactsPhotos"},{"_content":"flickr.photos.getContactsPublicPhotos"},{"_content":"flickr.photos.getContext"},{"_content":"flickr.photos.getCounts"},{"_content":"flickr.photos.getExif"},{"_content":"flickr.photos.getFavorites"},{"_content":"flickr.photos.getInfo"},{"_content":"flickr.photos.getNotInSet"},{"_content":"flickr.photos.getPerms"},{"_content":"flickr.photos.getPopular"},{"_content":"flickr.photos.getRecent"},{"_content":"flickr.photos.getSizes"},{"_content":"flickr.photos.getUntagged"},{"_content":"flickr.photos.getWithGeoData"},{"_content":"flickr.photos.getWithoutGeoData"},{"_content":"flickr.photos.licenses.getInfo"},{"_content":"flickr.photos.licenses.setLicense"},{"_content":"flickr.photos.notes.add"},{"_content":"flickr.photos.notes.delete"},{"_content":"flickr.photos.notes.edit"},{"_content":"flickr.photos.people.add"},{"_content":"flickr.photos.people.delete"},{"_content":"flickr.photos.people.deleteCoords"},{"_content":"flickr.photos.people.editCoords"},{"_content":"flickr.photos.people.getList"},{"_content":"flickr.photos.recentlyUpdated"},{"_content":"flickr.photos.removeTag"},{"_content":"flickr.photos.search"},{"_content":"flickr.photos.setContentType"},{"_content":"flickr.photos.setDates"},{"_content":"flickr.photos.setMeta"},{"_content":"flickr.photos.setPerms"},{"_content":"flickr.photos.setSafetyLevel"},{"_content":"flickr.photos.setTags"},{"_content":"flickr.photos.suggestions.approveSuggestion"},{"_content":"flickr.photos.suggestions.getList"},{"_content":"flickr.photos.suggestions.rejectSuggestion"},{"_content":"flickr.photos.suggestions.removeSuggestion"},{"_content":"flickr.photos.suggestions.suggestLocation"},{"_content":"flickr.photos.transform.rotate"},{"_content":"flickr.photos.upload.checkTickets"},{"_content":"flickr.photosets.addPhoto"},{"_content":"flickr.photosets.comments.addComment"},{"_content":"flickr.photosets.comments.deleteComment"},{"_content":"flickr.photosets.comments.editComment"},{"_content":"flickr.photosets.comments.getList"},{"_content":"flickr.photosets.create"},{"_content":"flickr.photosets.delete"},{"_content":"flickr.photosets.editMeta"},{"_content":"flickr.photosets.editPhotos"},{"_content":"flickr.photosets.getContext"},{"_content":"flickr.photosets.getInfo"},{"_content":"flickr.photosets.getList"},{"_content":"flickr.photosets.getPhotos"},{"_content":"flickr.photosets.orderSets"},{"_content":"flickr.photosets.removePhoto"},{"_content":"flickr.photosets.removePhotos"},{"_content":"flickr.photosets.reorderPhotos"},{"_content":"flickr.photosets.setPrimaryPhoto"},{"_content":"flickr.places.find"},{"_content":"flickr.places.findByLatLon"},{"_content":"flickr.places.getChildrenWithPhotosPublic"},{"_content":"flickr.places.getInfo"},{"_content":"flickr.places.getInfoByUrl"},{"_content":"flickr.places.getPlaceTypes"},{"_content":"flickr.places.getShapeHistory"},{"_content":"flickr.places.getTopPlacesList"},{"_content":"flickr.places.placesForBoundingBox"},{"_content":"flickr.places.placesForContacts"},{"_content":"flickr.places.placesForTags"},{"_content":"flickr.places.placesForUser"},{"_content":"flickr.places.resolvePlaceId"},{"_content":"flickr.places.resolvePlaceURL"},{"_content":"flickr.places.tagsForPlace"},{"_content":"flickr.prefs.getContentType"},{"_content":"flickr.prefs.getGeoPerms"},{"_content":"flickr.prefs.getHidden"},{"_content":"flickr.prefs.getPrivacy"},{"_content":"flickr.prefs.getSafetyLevel"},{"_content":"flickr.profile.getProfile"},{"_content":"flickr.push.getSubscriptions"},{"_content":"flickr.push.getTopics"},{"_content":"flickr.push.subscribe"},{"_content":"flickr.push.unsubscribe"},{"_content":"flickr.reflection.getMethodInfo"},{"_content":"flickr.reflection.getMethods"},{"_content":"flickr.stats.getCollectionDomains"},{"_content":"flickr.stats.getCollectionReferrers"},{"_content":"flickr.stats.getCollectionStats"},{"_content":"flickr.stats.getCSVFiles"},{"_content":"flickr.stats.getPhotoDomains"},{"_content":"flickr.stats.getPhotoReferrers"},{"_content":"flickr.stats.getPhotosetDomains"},{"_content":"flickr.stats.getPhotosetReferrers"},{"_content":"flickr.stats.getPhotosetStats"},{"_content":"flickr.stats.getPhotoStats"},{"_content":"flickr.stats.getPhotostreamDomains"},{"_content":"flickr.stats.getPhotostreamReferrers"},{"_content":"flickr.stats.getPhotostreamStats"},{"_content":"flickr.stats.getPopularPhotos"},{"_content":"flickr.stats.getTotalViews"},{"_content":"flickr.tags.getClusterPhotos"},{"_content":"flickr.tags.getClusters"},{"_content":"flickr.tags.getHotList"},{"_content":"flickr.tags.getListPhoto"},{"_content":"flickr.tags.getListUser"},{"_content":"flickr.tags.getListUserPopular"},{"_content":"flickr.tags.getListUserRaw"},{"_content":"flickr.tags.getMostFrequentlyUsed"},{"_content":"flickr.tags.getRelated"},{"_content":"flickr.test.echo"},{"_content":"flickr.test.login"},{"_content":"flickr.test.null"},{"_content":"flickr.urls.getGroup"},{"_content":"flickr.urls.getUserPhotos"},{"_content":"flickr.urls.getUserProfile"},{"_content":"flickr.urls.lookupGallery"},{"_content":"flickr.urls.lookupGroup"},{"_content":"flickr.urls.lookupUser"}]},"stat":"ok"}'
|
55
|
+
http_version:
|
56
|
+
recorded_at: Sun, 05 Mar 2017 11:41:25 GMT
|
57
|
+
- request:
|
58
|
+
method: post
|
59
|
+
uri: https://api.flickr.com/services/rest/
|
60
|
+
body:
|
61
|
+
encoding: US-ASCII
|
62
|
+
string: tags=dolomites&sort=interestingness-desc&per_page=1&method=flickr.photos.search&format=json&nojsoncallback=1
|
63
|
+
headers:
|
64
|
+
Accept-Encoding:
|
65
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
66
|
+
Accept:
|
67
|
+
- "*/*"
|
68
|
+
User-Agent:
|
69
|
+
- FlickRaw/0.9.9
|
70
|
+
Content-Type:
|
71
|
+
- application/x-www-form-urlencoded
|
72
|
+
response:
|
73
|
+
status:
|
74
|
+
code: 200
|
75
|
+
message: OK
|
76
|
+
headers:
|
77
|
+
Date:
|
78
|
+
- Sun, 05 Mar 2017 11:41:25 GMT
|
79
|
+
Content-Type:
|
80
|
+
- application/json
|
81
|
+
Content-Length:
|
82
|
+
- '196'
|
83
|
+
P3p:
|
84
|
+
- policyref="https://policies.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM
|
85
|
+
DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND
|
86
|
+
PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
|
87
|
+
X-Content-Type-Options:
|
88
|
+
- nosniff
|
89
|
+
Cache-Control:
|
90
|
+
- private
|
91
|
+
X-Served-By:
|
92
|
+
- bm-www930.flickr.bf1.yahoo.com
|
93
|
+
X-Frame-Options:
|
94
|
+
- SAMEORIGIN
|
95
|
+
Vary:
|
96
|
+
- Accept-Encoding
|
97
|
+
Age:
|
98
|
+
- '0'
|
99
|
+
Via:
|
100
|
+
- http/1.1 fts110.flickr.bf1.yahoo.com (ApacheTrafficServer [cMsSf ]), http/1.1
|
101
|
+
e22.ycpi.lob.yahoo.com (ApacheTrafficServer [cMsSf ])
|
102
|
+
Server:
|
103
|
+
- ATS
|
104
|
+
Connection:
|
105
|
+
- keep-alive
|
106
|
+
body:
|
107
|
+
encoding: ASCII-8BIT
|
108
|
+
string: '{"photos":{"page":1,"pages":159876,"perpage":1,"total":"159876","photo":[{"id":"33209118996","owner":"48059305@N03","secret":"1e1d0a66ee","server":"758","farm":1,"title":"Magic
|
109
|
+
dawn at Lusia alp","ispublic":1,"isfriend":0,"isfamily":0}]},"stat":"ok"}'
|
110
|
+
http_version:
|
111
|
+
recorded_at: Sun, 05 Mar 2017 11:41:25 GMT
|
112
|
+
recorded_with: VCR 2.9.2
|