flickollage 0.0.3
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.
- 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 [](https://badge.fury.io/rb/flickollage) [](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
|
+

|
24
|
+
|
25
|
+
$ flickollage generate --dict=spec/fixtures/mountains --output mountains.png
|
26
|
+
|
27
|
+

|
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
|