piwigo-api 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yaml +18 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +14 -1
- data/README.md +5 -6
- data/Rakefile +6 -6
- data/bin/console +3 -3
- data/lib/piwigo/albums.rb +147 -156
- data/lib/piwigo/image_uploader.rb +142 -0
- data/lib/piwigo/images.rb +142 -89
- data/lib/piwigo/session.rb +104 -103
- data/lib/piwigo/version.rb +1 -1
- data/lib/piwigo.rb +1 -1
- data/piwigo-api.gemspec +22 -21
- metadata +26 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b631bbf1feb2e43cdc914db7f8ae0e839739951a99bbf00d1789c65f64524d1
|
|
4
|
+
data.tar.gz: 460e4d390cc2362865f0b9f168bd821f0b0451599daceaa8afaceca137ebc71e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68fe0e10a5ccfc1522b8fdef5c0f964e7702ff0d676282d406aa811d5f39bf29fb4893be125a8143ce9033f077043c3277fc6d871c23374060bab506bac687b3
|
|
7
|
+
data.tar.gz: 9e42d435b2c00cd85db2ebc2d77511497f9f7ba7ec7d2deb7b1e61d08434566a31d844fa80a864a2bbe92431fb81bbc545eaa1277c4eb51518ee650b8ac83549
|
data/.gitignore
CHANGED
data/.rubocop.yaml
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
0.4.0 - 2019-11-20
|
|
8
|
+
- Add methods to check for the existance of a specific image and to upload images
|
|
9
|
+
|
|
7
10
|
0.3.1 - 2019-11-20
|
|
8
11
|
- Add a codecov.yaml for coverage reports
|
|
9
12
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
piwigo-api (0.
|
|
4
|
+
piwigo-api (0.4.0)
|
|
5
5
|
http (~> 4.2)
|
|
6
6
|
logger (~> 1.4)
|
|
7
7
|
|
|
@@ -10,6 +10,11 @@ GEM
|
|
|
10
10
|
specs:
|
|
11
11
|
addressable (2.7.0)
|
|
12
12
|
public_suffix (>= 2.0.2, < 5.0)
|
|
13
|
+
codecov (0.1.16)
|
|
14
|
+
json
|
|
15
|
+
simplecov
|
|
16
|
+
url
|
|
17
|
+
docile (1.3.2)
|
|
13
18
|
domain_name (0.5.20190701)
|
|
14
19
|
unf (>= 0.0.5, < 1.0.0)
|
|
15
20
|
ffi (1.11.2-x64-mingw32)
|
|
@@ -26,13 +31,20 @@ GEM
|
|
|
26
31
|
http-form_data (2.1.1)
|
|
27
32
|
http-parser (1.2.1)
|
|
28
33
|
ffi-compiler (>= 1.0, < 2.0)
|
|
34
|
+
json (2.2.0)
|
|
29
35
|
logger (1.4.1)
|
|
30
36
|
minitest (5.13.0)
|
|
31
37
|
public_suffix (4.0.1)
|
|
32
38
|
rake (10.5.0)
|
|
39
|
+
simplecov (0.17.1)
|
|
40
|
+
docile (~> 1.1)
|
|
41
|
+
json (>= 1.8, < 3)
|
|
42
|
+
simplecov-html (~> 0.10.0)
|
|
43
|
+
simplecov-html (0.10.2)
|
|
33
44
|
unf (0.1.4)
|
|
34
45
|
unf_ext
|
|
35
46
|
unf_ext (0.0.7.6)
|
|
47
|
+
url (0.3.2)
|
|
36
48
|
|
|
37
49
|
PLATFORMS
|
|
38
50
|
ruby
|
|
@@ -40,6 +52,7 @@ PLATFORMS
|
|
|
40
52
|
|
|
41
53
|
DEPENDENCIES
|
|
42
54
|
bundler (~> 2.0)
|
|
55
|
+
codecov (>= 0.1.10)
|
|
43
56
|
minitest (~> 5.0)
|
|
44
57
|
piwigo-api!
|
|
45
58
|
rake (~> 10.0)
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Piwigo-API
|
|
2
2
|
|
|
3
|
-

|
|
3
|
+
 [](https://codecov.io/gh/KKDad/piwigo-api)  [](https://badge.fury.io/rb/piwigo-api)
|
|
4
4
|
|
|
5
5
|
[Piwigo](https://piwigo.org/) is open source web application to manage your collection of photos, and other medias. Piwigo provides an API for interacting with it.
|
|
6
6
|
|
|
@@ -24,9 +24,9 @@ Or install it yourself as:
|
|
|
24
24
|
|
|
25
25
|
## Usage
|
|
26
26
|
|
|
27
|
-
Just include 'piwigo/session' and the related classes, then querying Piwigo is fairly quick and straightforward.
|
|
27
|
+
Just include 'piwigo/session' and the related classes, then querying Piwigo is fairly quick and straightforward. The latest RubyDocs for [piwigo-api](https://rubydoc.info/github/KKDad/piwigo-api) can be loacated on [rubydoc.info](https://rubydoc.info).
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
### Get the second album and all of it's children
|
|
30
30
|
|
|
31
31
|
```ruby
|
|
32
32
|
require 'piwigo/session'
|
|
@@ -39,7 +39,7 @@ unless session.nil?
|
|
|
39
39
|
end
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
### Add a new album
|
|
43
43
|
```ruby
|
|
44
44
|
require 'piwigo/session'
|
|
45
45
|
require 'piwigo/albums'
|
|
@@ -52,7 +52,7 @@ unless session.nil?
|
|
|
52
52
|
end
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
### List the Contents of an Album
|
|
56
56
|
|
|
57
57
|
```ruby
|
|
58
58
|
require 'piwigo/session'
|
|
@@ -61,7 +61,6 @@ require 'piwigo/images'
|
|
|
61
61
|
session = Piwigo::Session.login('mypiwigo.fqdn', 'Adrian', 'mypassword', https: false)
|
|
62
62
|
unless session.nil?
|
|
63
63
|
results = Piwigo::Images.getImages(session, album_id: 4)
|
|
64
|
-
|
|
65
64
|
results[:images].each { |image| p "#{image.id}, #{image.name} - #{image.element_url}" }
|
|
66
65
|
end
|
|
67
66
|
```
|
data/Rakefile
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'rake/testtask'
|
|
3
3
|
|
|
4
4
|
Rake::TestTask.new(:test) do |t|
|
|
5
|
-
t.libs <<
|
|
6
|
-
t.libs <<
|
|
7
|
-
t.test_files = FileList[
|
|
5
|
+
t.libs << 'test'
|
|
6
|
+
t.libs << 'lib'
|
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
task :
|
|
10
|
+
task default: :test
|
data/bin/console
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'piwigo'
|
|
5
5
|
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
|
@@ -10,5 +10,5 @@ require "piwigo"
|
|
|
10
10
|
# require "pry"
|
|
11
11
|
# Pry.start
|
|
12
12
|
|
|
13
|
-
require
|
|
13
|
+
require 'irb'
|
|
14
14
|
IRB.start(__FILE__)
|
data/lib/piwigo/albums.rb
CHANGED
|
@@ -6,180 +6,171 @@ require 'logger'
|
|
|
6
6
|
# Piwigo organizes images by albums. The album tree has unlimted depth and each photo can belong to multiple albums. The Piwigo API
|
|
7
7
|
# refers to a Album as a Category.
|
|
8
8
|
module Piwigo
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
class Albums
|
|
10
|
+
class Album
|
|
11
|
+
# @return [Number] Album ID
|
|
12
|
+
attr_accessor :id
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
# @return [String] Name of the Album
|
|
15
|
+
attr_accessor :name
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
# @return [String] Album Description
|
|
18
|
+
attr_accessor :comment
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
# ???
|
|
21
|
+
attr_accessor :permalink
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
# @return [String] public or private
|
|
24
|
+
attr_accessor :status
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
# ???
|
|
27
|
+
attr_accessor :uppercats
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# The rank of an album
|
|
30
|
+
attr_accessor :global_rank
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
# @return [Number] ID of the parent album, nil of this is a top-level album (Aka ParentID)
|
|
33
|
+
attr_accessor :id_uppercat
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
# @return [Number] Number of the Newest photos, excluding child albums
|
|
36
|
+
attr_accessor :nb_images
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
# @return [Number] Number of the Newest photos, including child albums
|
|
39
|
+
attr_accessor :total_nb_images
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
# ID of the representative photo for an album. This photo doesn't have to belong to the album.
|
|
42
|
+
attr_accessor :representative_picture_id
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
# @return [DateTime] Date of the Newest photos, excluding child albums
|
|
45
|
+
attr_accessor :date_last
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
# @return [DateTime] Date of the Newest photos, including child albums
|
|
48
|
+
attr_accessor :max_date_last
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
# @return [Number] Number of child albums inside this album
|
|
51
|
+
attr_accessor :nb_categories
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
# @return [Atring] Album URL
|
|
54
|
+
attr_accessor :url
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
# @return [String] Thumbnail URL
|
|
57
|
+
attr_accessor :tn_url
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
def initialize(hash: nil)
|
|
60
|
+
hash&.each { |key, value| send("#{key}=", value) }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Returns a list of albums
|
|
65
|
+
#
|
|
66
|
+
# @param [Session] session - Session
|
|
67
|
+
# @param [Number] album_id - Album to fetch, Optional
|
|
68
|
+
# @param [Boolean] recursive - Include subalbums, Optional
|
|
69
|
+
# @param [Boolean] public - Only include public albums, Optional
|
|
70
|
+
# @param [Boolean] fullname - ???, Optional
|
|
71
|
+
# @param [String] thumbnail_size - Size of thumbname to return, One of: square, thumb, 2small, xsmall, small, medium, large, xlarge, xxlarge. Optional
|
|
72
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
73
|
+
#
|
|
74
|
+
# @return [Array<Album>] All albums that match the criteria, or nil there were no matches
|
|
75
|
+
def self.list(session, album_id: nil, recursive: false, public: false, fullname: false, thumbnail_size: 'thumb', logger: nil)
|
|
76
|
+
raise 'Invalid session' if session.uri.nil?
|
|
77
|
+
|
|
78
|
+
logger ||= Logger.new(STDOUT)
|
|
79
|
+
|
|
80
|
+
begin
|
|
81
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
82
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
83
|
+
request.body = "method=pwg.categories.getList&cat_id=#{album_id}&recursive=#{recursive}&public=#{public}&fullname=#{fullname}&thumbnail_size=#{thumbnail_size}"
|
|
84
|
+
request['Cookie'] = [session.id]
|
|
85
|
+
|
|
86
|
+
# Send the request
|
|
87
|
+
response = http.request(request)
|
|
88
|
+
if response.code == '200'
|
|
89
|
+
data = JSON.parse(response.body)
|
|
90
|
+
albums = data['result']['categories'].map { |hash| Album.new(hash: hash) }
|
|
91
|
+
logger.info "Album List succeeded: #{albums.size} albums retrieved."
|
|
92
|
+
albums
|
|
62
93
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
99
|
-
logger.error "Album List failed: #{e.messages}"
|
|
100
|
-
nil
|
|
101
|
-
end
|
|
94
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
95
|
+
logger.error "Album List failed: #{e.messages}"
|
|
96
|
+
nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Adds an album.
|
|
101
|
+
#
|
|
102
|
+
# @param [Session] session to interact with Piwigo
|
|
103
|
+
# @param [Album] album album to create
|
|
104
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
105
|
+
#
|
|
106
|
+
# @return [Album] newly created album
|
|
107
|
+
def self.add(session, album, logger: nil)
|
|
108
|
+
raise 'Invalid session' if session.uri.nil?
|
|
109
|
+
raise 'Invalid album' if album.nil?
|
|
110
|
+
|
|
111
|
+
logger ||= Logger.new(STDOUT)
|
|
112
|
+
|
|
113
|
+
begin
|
|
114
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
115
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
116
|
+
request.body = "method=pwg.categories.add&name=#{album.name}"
|
|
117
|
+
request.body.concat "&parent=#{album.id_uppercat}" unless album.id_uppercat.nil?
|
|
118
|
+
request.body.concat "&comment=#{album.comment}" unless album.comment.nil?
|
|
119
|
+
request.body.concat "&status=#{album.status}" unless album.status.nil?
|
|
120
|
+
request['Cookie'] = [session.id]
|
|
121
|
+
|
|
122
|
+
# Send the request
|
|
123
|
+
response = http.request(request)
|
|
124
|
+
if response.code == '200'
|
|
125
|
+
data = JSON.parse(response.body)
|
|
126
|
+
album.id = data['result']['id']
|
|
127
|
+
logger.info "Album Add succeeded: #{album.id} created."
|
|
128
|
+
album
|
|
102
129
|
end
|
|
130
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
131
|
+
logger.error "Album Add failed: #{e.messages}"
|
|
132
|
+
nil
|
|
133
|
+
end
|
|
134
|
+
end
|
|
103
135
|
|
|
136
|
+
# Deletes album(s).
|
|
137
|
+
#
|
|
138
|
+
# @param [Session] piwigo session
|
|
139
|
+
# @param [Number] id of the album to remove
|
|
140
|
+
# @param [String] photo_deletion_mode can be "no_delete" (may create orphan photos), "delete_orphans" (default mode, only deletes photos linked to no other album)
|
|
141
|
+
# or "force_delete" (delete all photos, even those linked to other albums)
|
|
142
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
143
|
+
#
|
|
144
|
+
# @return [Boolean] true if album was deleted
|
|
145
|
+
def self.delete(session, id, photo_deletion_mode: nil, logger: nil)
|
|
146
|
+
raise 'Invalid session' if session.uri.nil?
|
|
147
|
+
|
|
148
|
+
logger ||= Logger.new(STDOUT)
|
|
149
|
+
|
|
150
|
+
begin
|
|
151
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
152
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
153
|
+
request.body = "method=pwg.categories.delete&category_id=#{id}"
|
|
154
|
+
request.body.concat "&photo_deletion_mode=#{photo_deletion_mode}" unless photo_deletion_mode.nil?
|
|
155
|
+
request.body.concat "&pwg_token=#{session.pwg_token}"
|
|
156
|
+
request['Cookie'] = [session.id]
|
|
157
|
+
|
|
158
|
+
# Send the request
|
|
159
|
+
response = http.request(request)
|
|
160
|
+
if response.code == '200'
|
|
161
|
+
data = JSON.parse(response.body)
|
|
162
|
+
logger.info "Album Delete succeeded: #{data}"
|
|
163
|
+
true
|
|
164
|
+
else
|
|
165
|
+
p response.code
|
|
166
|
+
p response.body
|
|
167
|
+
false
|
|
104
168
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
#
|
|
111
|
-
# @return [Album] newly created album
|
|
112
|
-
def self.add(session, album, logger: nil)
|
|
113
|
-
raise "Invalid session" if session.uri.nil?
|
|
114
|
-
raise "Invalid album" if album.nil?
|
|
115
|
-
|
|
116
|
-
logger = logger || Logger.new(STDOUT)
|
|
117
|
-
|
|
118
|
-
begin
|
|
119
|
-
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
120
|
-
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
121
|
-
request.body = "method=pwg.categories.add&name=#{album.name}"
|
|
122
|
-
request.body.concat "&parent=#{album.id_uppercat}" unless album.id_uppercat.nil?
|
|
123
|
-
request.body.concat "&comment=#{album.comment}" unless album.comment.nil?
|
|
124
|
-
request.body.concat "&status=#{album.status}" unless album.status.nil?
|
|
125
|
-
request['Cookie'] = [session.id]
|
|
126
|
-
|
|
127
|
-
# Send the request
|
|
128
|
-
response = http.request(request)
|
|
129
|
-
if response.code == '200'
|
|
130
|
-
data = JSON.parse(response.body)
|
|
131
|
-
album.id = albums = data['result']['id']
|
|
132
|
-
logger.info "Album Add succeeded: #{album.id} created."
|
|
133
|
-
album
|
|
134
|
-
else
|
|
135
|
-
nil
|
|
136
|
-
|
|
137
|
-
end
|
|
138
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
139
|
-
logger.error "Album Add failed: #{e.messages}"
|
|
140
|
-
nil
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
# Deletes album(s).
|
|
146
|
-
#
|
|
147
|
-
# @param [Session] piwigo session
|
|
148
|
-
# @param [Number] id of the album to remove
|
|
149
|
-
# @param [String] photo_deletion_mode can be "no_delete" (may create orphan photos), "delete_orphans" (default mode, only deletes photos linked to no other album)
|
|
150
|
-
# or "force_delete" (delete all photos, even those linked to other albums)
|
|
151
|
-
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
152
|
-
#
|
|
153
|
-
# @return [Boolean] true if album was deleted
|
|
154
|
-
def self.delete(session, id, photo_deletion_mode: nil, logger: nil)
|
|
155
|
-
raise "Invalid session" if session.uri.nil?
|
|
156
|
-
|
|
157
|
-
logger = logger || Logger.new(STDOUT)
|
|
158
|
-
|
|
159
|
-
begin
|
|
160
|
-
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
161
|
-
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
162
|
-
request.body = "method=pwg.categories.delete&category_id=#{id}"
|
|
163
|
-
request.body.concat "&photo_deletion_mode=#{photo_deletion_mode}" unless photo_deletion_mode.nil?
|
|
164
|
-
request.body.concat "&pwg_token=#{session.pwg_token}"
|
|
165
|
-
request['Cookie'] = [session.id]
|
|
166
|
-
|
|
167
|
-
# Send the request
|
|
168
|
-
response = http.request(request)
|
|
169
|
-
if response.code == '200'
|
|
170
|
-
data = JSON.parse(response.body)
|
|
171
|
-
logger.info "Album Delete succeeded."
|
|
172
|
-
true
|
|
173
|
-
else
|
|
174
|
-
p response.code
|
|
175
|
-
p response.body
|
|
176
|
-
false
|
|
177
|
-
|
|
178
|
-
end
|
|
179
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
180
|
-
logger.error "Album delete: #{e.messages}"
|
|
181
|
-
false
|
|
182
|
-
end
|
|
183
|
-
end
|
|
169
|
+
end
|
|
170
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
171
|
+
logger.error "Album delete: #{e.messages}"
|
|
172
|
+
false
|
|
173
|
+
end
|
|
184
174
|
end
|
|
185
|
-
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'logger'
|
|
5
|
+
require 'digest'
|
|
6
|
+
require 'base64'
|
|
7
|
+
|
|
8
|
+
# Add a photo.
|
|
9
|
+
#
|
|
10
|
+
# To avoid limitations on HTTP POST maximum size, the piwigo requires the image to be splitted into several calls to pwg.images.addChunk
|
|
11
|
+
# and then a single call to pwg.images.add.
|
|
12
|
+
#
|
|
13
|
+
# Reference: https://piwigo.org/doc/doku.php?id=dev:webapi:pwg.images.add
|
|
14
|
+
module Piwigo
|
|
15
|
+
class Images
|
|
16
|
+
class ImageUploader
|
|
17
|
+
MEGABYTE = 1024 * 1024
|
|
18
|
+
|
|
19
|
+
# Create a new ImageUploader
|
|
20
|
+
#
|
|
21
|
+
# @param [Session] session - session to a piwigo instance
|
|
22
|
+
def initialize(logger: nil)
|
|
23
|
+
@logger = logger || Logger.new(STDOUT)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Add a photo to Piwigo
|
|
27
|
+
#
|
|
28
|
+
# @param [<Type>] session
|
|
29
|
+
# @param [<Type>] filename of the file to upload
|
|
30
|
+
# @param [<Type>] name of the image
|
|
31
|
+
#
|
|
32
|
+
# @return [Boolean] True if successful
|
|
33
|
+
def Upload(session, filename, name)
|
|
34
|
+
@session = session
|
|
35
|
+
raise 'Invalid session' if @session.uri.nil?
|
|
36
|
+
|
|
37
|
+
unless File.exist? filename
|
|
38
|
+
@Logger.error "No such file: #{filename}"
|
|
39
|
+
return false
|
|
40
|
+
end
|
|
41
|
+
chunk_num = 0
|
|
42
|
+
image_content = File.binread(filename)
|
|
43
|
+
original_sum = Digest::MD5.hexdigest(image_content)
|
|
44
|
+
encoded_content = Base64.encode64(image_content)
|
|
45
|
+
io = StringIO.new(encoded_content)
|
|
46
|
+
until io.eof?
|
|
47
|
+
chunk = io.read(MEGABYTE)
|
|
48
|
+
addChunk(chunk, original_sum, chunk_num)
|
|
49
|
+
chunk_num += 1
|
|
50
|
+
end
|
|
51
|
+
add(original_sum, filename, name)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Add a chunk of a file.
|
|
57
|
+
#
|
|
58
|
+
# @param [String] data - substring of the base64 encoded binary file
|
|
59
|
+
# @param [String] original_sum - md5sum of the original photo, used as a unique identifier, not to check the chunk upload
|
|
60
|
+
# @param [Number] position - the numeric position of the chunk among all chunks of the given file
|
|
61
|
+
#
|
|
62
|
+
# @return [Boolean] true if successful
|
|
63
|
+
def addChunk(data, original_sum, position)
|
|
64
|
+
http = Net::HTTP.new(@session.uri.host, @session.uri.port)
|
|
65
|
+
request = Net::HTTP::Post.new(@session.uri.request_uri)
|
|
66
|
+
form = {
|
|
67
|
+
method: 'pwg.images.addChunk',
|
|
68
|
+
original_sum: original_sum,
|
|
69
|
+
position: position,
|
|
70
|
+
data: data
|
|
71
|
+
}
|
|
72
|
+
request.set_form_data(form)
|
|
73
|
+
request['Cookie'] = [@session.id]
|
|
74
|
+
|
|
75
|
+
response = http.request(request)
|
|
76
|
+
if response.code == '200'
|
|
77
|
+
data = JSON.parse(response.body)
|
|
78
|
+
@logger.info "Image AddChunk ##{position} succeeded: #{data}"
|
|
79
|
+
true
|
|
80
|
+
else
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
84
|
+
@logger.error "Image AddChunk failed: #{e.messages}"
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Add an image. Pwg.images.addChunk must have been called before (maybe several times).
|
|
89
|
+
#
|
|
90
|
+
# @param [<Type>] original_sum - md5sum that makes the photo unique
|
|
91
|
+
# @param [<Type>] original_filename
|
|
92
|
+
# @param [<Type>] name
|
|
93
|
+
# @param [<Type>] author
|
|
94
|
+
# @param [Number] level - 0 (—-), 1 (Contacts), 2 (Friends), 4 (Family), 8 (Admins)
|
|
95
|
+
# @param [String] date_creation - formatted as 2009-03-26
|
|
96
|
+
# @param [<Type>] comment -
|
|
97
|
+
# @param [<Type>] categories - list of category identifiers where you want the photo to be shown. Optionaly, you can set a rank inside the each category.
|
|
98
|
+
# Example : '19,3;16,0;134' will associate the photo to category 19 at rank 3, to category 16 at rank 0 (first position) and
|
|
99
|
+
# to category 134 with an automatic rank (last position).
|
|
100
|
+
# @param [<Type>] image_id - give an image_id if you want to update an existing photo
|
|
101
|
+
#
|
|
102
|
+
# @return [Boolean] True if successful
|
|
103
|
+
def add(original_sum, original_filename, name, author: nil, level: nil, date_creation: nil, comment: nil, categories: nil, image_id: nil)
|
|
104
|
+
|
|
105
|
+
http = Net::HTTP.new(@session.uri.host, @session.uri.port)
|
|
106
|
+
request = Net::HTTP::Post.new(@session.uri.request_uri)
|
|
107
|
+
form = {
|
|
108
|
+
method: 'pwg.images.add',
|
|
109
|
+
original_sum: original_sum,
|
|
110
|
+
original_filename: original_filename,
|
|
111
|
+
name: name
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
form[:author] = author unless author.nil?
|
|
115
|
+
form[:level] = level unless level.nil?
|
|
116
|
+
form[:date_creation] = date_creation unless date_creation.nil?
|
|
117
|
+
form[:comment] = comment unless comment.nil?
|
|
118
|
+
form[:categories] = categories unless categories.nil?
|
|
119
|
+
form[:image_id] = image_id unless image_id.nil?
|
|
120
|
+
request.set_form_data(form)
|
|
121
|
+
|
|
122
|
+
request['Cookie'] = [@session.id]
|
|
123
|
+
|
|
124
|
+
response = http.request(request)
|
|
125
|
+
if response.code == '500'
|
|
126
|
+
@logger.error "Image Add failed: #{response.messages}"
|
|
127
|
+
false
|
|
128
|
+
elsif response.code == '200'
|
|
129
|
+
data = JSON.parse(response.body)
|
|
130
|
+
p data
|
|
131
|
+
@logger.info 'Image Add succeeded.'
|
|
132
|
+
true
|
|
133
|
+
else
|
|
134
|
+
false
|
|
135
|
+
end
|
|
136
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
137
|
+
@logger.error "Image Add failed: #{e.messages}"
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
data/lib/piwigo/images.rb
CHANGED
|
@@ -1,117 +1,170 @@
|
|
|
1
|
+
require 'base64'
|
|
1
2
|
require 'net/http'
|
|
2
3
|
require 'uri'
|
|
3
4
|
require 'json'
|
|
4
5
|
require 'logger'
|
|
6
|
+
require 'digest'
|
|
7
|
+
require_relative 'image_uploader'
|
|
5
8
|
|
|
6
9
|
# Piwigo organizes images by albums. The album tree has unlimted depth and each photo can belong to multiple albums. The Piwigo API
|
|
7
10
|
# refers to a Album as a Category.
|
|
8
11
|
module Piwigo
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
class Images
|
|
13
|
+
class Image
|
|
14
|
+
# @return [Number] Unique ID idenifying this ie
|
|
15
|
+
attr_accessor :id
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
# @return [Number] Width of the image in pixels
|
|
18
|
+
attr_accessor :width
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
# @return [Number] Height of the image in pixels
|
|
21
|
+
attr_accessor :height
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
# @return [Number] Number of times the image has been viewed
|
|
24
|
+
attr_accessor :hit
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
# @return [String] Filename for the image
|
|
27
|
+
attr_accessor :file
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
# @return [String] Name of the image
|
|
30
|
+
attr_accessor :name
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
# @return [String] Comments about the image
|
|
33
|
+
attr_accessor :comment
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
# @return [DateTime] DateTime when the image was taken
|
|
36
|
+
attr_accessor :date_creation
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
# @return [DateTime] DateTime when the image was uploaded to Piwigo
|
|
39
|
+
attr_accessor :date_available
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
# @return [String] URL to the image page
|
|
42
|
+
attr_accessor :page_url
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
# @return [String] URL to the image itself
|
|
45
|
+
attr_accessor :element_url
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
# @return [Array<String>] Links to different sizes of the image
|
|
48
|
+
attr_accessor :derivatives
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
# @return [<Type>] List of all of the Albums this image is in
|
|
51
|
+
attr_accessor :categories
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
def initialize(hash: nil)
|
|
54
|
+
hash&.each { |key, value| send("#{key}=", value) }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class Paging # rubocop:todo Style/Documentation
|
|
59
|
+
# @return [Number] Page number of the results
|
|
60
|
+
attr_accessor :page
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
attr_accessor :page
|
|
62
|
+
# @return [Number] Number of images requesed per page
|
|
63
|
+
attr_accessor :per_page
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
# @return [Number] Number of Images on this page. When this is less then the number per page, then there are no more results.
|
|
66
|
+
attr_accessor :count
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
# @return [Number] Total number of images across all pages
|
|
69
|
+
attr_accessor :total_count
|
|
70
|
+
|
|
71
|
+
def initialize(hash: nil)
|
|
72
|
+
hash&.each { |key, value| send("#{key}=", value) }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
# Returns elements for the corresponding categories.
|
|
77
|
+
# order comma separated fields for sorting
|
|
78
|
+
#
|
|
79
|
+
# @param [Session] session
|
|
80
|
+
# @param [Number] album_id - Can be empty if recursive is true.
|
|
81
|
+
# @param [Boolean] recursive - Include images from child albums
|
|
82
|
+
# @param [Number] per_page - Number of items to include per page
|
|
83
|
+
# @param [Number] page - Page to retrieve
|
|
84
|
+
# @param [String] order - One or more of id, file, name, hit, rating_score, date_creation, date_available or random
|
|
85
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
86
|
+
#
|
|
87
|
+
# @return [Hash] <description>
|
|
88
|
+
def self.getImages(session, album_id: nil, recursive: nil, per_page: 100, page: 0, order: nil, logger: nil)
|
|
89
|
+
raise 'Invalid session' if session.uri.nil?
|
|
90
|
+
|
|
91
|
+
logger ||= Logger.new(STDOUT)
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
95
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
96
|
+
form = {
|
|
97
|
+
method: 'pwg.categories.getImages'
|
|
98
|
+
}
|
|
99
|
+
form[:cat_id] = album_id unless album_id.nil?
|
|
100
|
+
form[:recursive] = recursive unless recursive.nil?
|
|
101
|
+
form[:per_page] = per_page unless per_page.nil?
|
|
102
|
+
form[:order] = order unless order.nil?
|
|
103
|
+
request.set_form_data(form)
|
|
104
|
+
request['Cookie'] = [session.id]
|
|
105
|
+
|
|
106
|
+
# Send the request
|
|
107
|
+
response = http.request(request)
|
|
108
|
+
if response.code == '200'
|
|
109
|
+
data = JSON.parse(response.body)
|
|
110
|
+
paging = Paging.new hash: data['result']['paging']
|
|
111
|
+
images = data['result']['images'].map { |hash| Image.new(hash: hash) }
|
|
112
|
+
logger.info "Image List succeeded: #{images.size} images retrieved."
|
|
113
|
+
{ paging: paging, images: images }
|
|
71
114
|
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
begin
|
|
90
|
-
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
91
|
-
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
92
|
-
request.body = "method=pwg.categories.getImages"
|
|
93
|
-
request.body.concat "&cat_id=#{album_id}" unless album_id.nil?
|
|
94
|
-
request.body.concat "&recursive=#{recursive}" unless recursive.nil?
|
|
95
|
-
request.body.concat "&per_page=#{per_page}" unless album_id.nil?
|
|
96
|
-
request.body.concat "&order=#{order}" unless order.nil?
|
|
97
|
-
request['Cookie'] = [session.id]
|
|
98
|
-
|
|
99
|
-
# Send the request
|
|
100
|
-
response = http.request(request)
|
|
101
|
-
if response.code == '200'
|
|
102
|
-
data = JSON.parse(response.body)
|
|
103
|
-
paging = Paging.new hash: data['result']['paging']
|
|
104
|
-
images = data['result']['images'].map{ |hash| Image.new(hash: hash) }
|
|
105
|
-
logger.info "Image List succeeded: #{images.size} images retrieved."
|
|
106
|
-
{ :paging => paging, :images => images }
|
|
107
|
-
else
|
|
108
|
-
nil
|
|
109
|
-
end
|
|
110
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
111
|
-
logger.error "Image List failed: #{e.messages}"
|
|
112
|
-
nil
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
116
|
+
logger.error "Image List failed: #{e.messages}"
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Add a photo to Piwigo
|
|
122
|
+
#
|
|
123
|
+
# @param [<Type>] session
|
|
124
|
+
# @param [<Type>] filename of the file to upload
|
|
125
|
+
# @param [<Type>] name of the image
|
|
126
|
+
#
|
|
127
|
+
# @return [Boolean] True if successful
|
|
128
|
+
def self.Upload(session, file, name)
|
|
129
|
+
ImageUploader.new(session, file, name).Upload
|
|
130
|
+
end
|
|
115
131
|
|
|
132
|
+
# Checks existence of images
|
|
133
|
+
#
|
|
134
|
+
# @param [Session] session
|
|
135
|
+
# @param [String] file to check
|
|
136
|
+
# @param [Logger] logger
|
|
137
|
+
#
|
|
138
|
+
# @return [Number] Piwigo image_id if matched, nil if not present
|
|
139
|
+
def self.Lookup(session, file, logger: nil)
|
|
140
|
+
raise 'Invalid session' if session.uri.nil?
|
|
141
|
+
|
|
142
|
+
logger ||= Logger.new(STDOUT)
|
|
143
|
+
image_content = File.binread(file)
|
|
144
|
+
file_sum = Digest::MD5.hexdigest(image_content)
|
|
145
|
+
|
|
146
|
+
begin
|
|
147
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
|
148
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
|
149
|
+
form = {
|
|
150
|
+
method: 'pwg.images.exist',
|
|
151
|
+
md5sum_list: file_sum,
|
|
152
|
+
filename_list: file
|
|
153
|
+
}
|
|
154
|
+
request.set_form_data(form)
|
|
155
|
+
request['Cookie'] = [session.id]
|
|
156
|
+
|
|
157
|
+
# Send the request
|
|
158
|
+
response = http.request(request)
|
|
159
|
+
if response.code == '200'
|
|
160
|
+
data = JSON.parse(response.body)
|
|
161
|
+
logger.info "Image Lookup succeeded: #{data['result']}"
|
|
162
|
+
data['result'][file_sum]
|
|
163
|
+
end
|
|
164
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
165
|
+
logger.error "Image Lookup failed: #{e.messages}"
|
|
166
|
+
nil
|
|
167
|
+
end
|
|
116
168
|
end
|
|
117
|
-
end
|
|
169
|
+
end
|
|
170
|
+
end
|
data/lib/piwigo/session.rb
CHANGED
|
@@ -4,115 +4,116 @@ require 'json'
|
|
|
4
4
|
require 'logger'
|
|
5
5
|
|
|
6
6
|
module Piwigo
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
attr_accessor :id
|
|
7
|
+
# Class to hold the Piwigo session the rest of the API needs to pass in order to access the API
|
|
8
|
+
class Session
|
|
9
|
+
# @return [String] Piwigo session cookie
|
|
10
|
+
attr_accessor :id
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
# @return [URI::HTTP] Piwigo host associated with this session
|
|
13
|
+
attr_accessor :uri
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
# @return [String] token required for admin methods
|
|
16
|
+
attr_accessor :pwg_token
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
# @return [String] token required for admin methods
|
|
19
|
+
attr_accessor :username
|
|
21
20
|
|
|
21
|
+
def initialize(id, uri)
|
|
22
|
+
self.id = id
|
|
23
|
+
self.uri = uri
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
self.uri = uri
|
|
25
|
+
status
|
|
26
|
+
end
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
self.username = data['result']['username']
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
54
|
-
logger.error "Unexpected failed: #{e.messages}"
|
|
55
|
-
end
|
|
56
|
-
nil
|
|
57
|
-
|
|
28
|
+
# Gets information about the current session. Also provides a token useable with admin methods.
|
|
29
|
+
# @return [<Type>] <description>
|
|
30
|
+
def status
|
|
31
|
+
logger ||= Logger.new(STDOUT)
|
|
32
|
+
|
|
33
|
+
begin
|
|
34
|
+
# Create the HTTP objects
|
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
36
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
|
37
|
+
form = {
|
|
38
|
+
method: 'pwg.session.getStatus'
|
|
39
|
+
}
|
|
40
|
+
request.set_form_data(form)
|
|
41
|
+
request['Cookie'] = id
|
|
42
|
+
|
|
43
|
+
# Send the request
|
|
44
|
+
response = http.request(request)
|
|
45
|
+
|
|
46
|
+
if response.code == '200'
|
|
47
|
+
logger.info 'Status succeeded'
|
|
48
|
+
data = JSON.parse(response.body)
|
|
49
|
+
self.pwg_token = data['result']['pwg_token']
|
|
50
|
+
self.username = data['result']['username']
|
|
58
51
|
end
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
52
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
53
|
+
logger.error "Unexpected failed: #{e.messages}"
|
|
54
|
+
end
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Logout of the current session
|
|
59
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
60
|
+
def logout(logger: nil)
|
|
61
|
+
raise 'This session has already been logged out' if uri.nil?
|
|
62
|
+
|
|
63
|
+
logger ||= Logger.new(STDOUT)
|
|
64
|
+
|
|
65
|
+
# Create the HTTP objects
|
|
66
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
67
|
+
request = Net::HTTP::Get.new(uri.request_uri + '&method=pwg.session.logout')
|
|
68
|
+
request['Cookie'] = id
|
|
69
|
+
|
|
70
|
+
# Send the request
|
|
71
|
+
response = http.request(request)
|
|
72
|
+
logger.info "Logout succeeded: #{response.body}" if response.code == '200'
|
|
73
|
+
self.id = nil
|
|
74
|
+
self.uri = nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Log into the piwigo API and grab the session id for subsequent calls.
|
|
78
|
+
# @param [string] piwigo - host to connect to. Can be fqdn or ip.
|
|
79
|
+
# @param [string] username - user to connect as
|
|
80
|
+
# @param [string] password - password for user
|
|
81
|
+
# @param [boolean] https - Use HTTPS?
|
|
82
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
83
|
+
def self.login(host, username, password, https: true, logger: nil)
|
|
84
|
+
raise 'host should not be nil' if host.nil?
|
|
85
|
+
raise 'username should not be nil' if username.nil?
|
|
86
|
+
|
|
87
|
+
logger ||= Logger.new(STDOUT)
|
|
88
|
+
|
|
89
|
+
begin
|
|
90
|
+
uri = https ? URI::HTTPS.build(host: host, path: '/ws.php', query: 'format=json') :
|
|
91
|
+
URI::HTTP.build(host: host, path: '/ws.php', query: 'format=json')
|
|
92
|
+
|
|
93
|
+
# Create the HTTP objects
|
|
94
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
95
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
|
96
|
+
form = {
|
|
97
|
+
method: 'pwg.session.login',
|
|
98
|
+
username: username,
|
|
99
|
+
password: password
|
|
100
|
+
}
|
|
101
|
+
request.set_form_data(form)
|
|
102
|
+
|
|
103
|
+
# Send the request
|
|
104
|
+
response = http.request(request)
|
|
105
|
+
|
|
106
|
+
if response.code == '200'
|
|
107
|
+
logger.info "Login succeeded: #{response.body}"
|
|
108
|
+
pwg_id = response.response['set-cookie'].split(';').select { |i| i.strip.start_with? 'pwg_id' }.first
|
|
109
|
+
return Session.new(pwg_id, uri)
|
|
110
|
+
else
|
|
111
|
+
logger.error "Login failed: #{response.body}"
|
|
76
112
|
end
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
# @param [string] username - user to connect as
|
|
82
|
-
# @param [string] password - password for user
|
|
83
|
-
# @param [boolean] https - Use HTTPS?
|
|
84
|
-
# @param [Logger] logger logger to output debug messages to (Optional)
|
|
85
|
-
def self.login(host, username, password, https: true, logger: nil)
|
|
86
|
-
|
|
87
|
-
raise "host should not be nil" if host.nil?
|
|
88
|
-
raise "username should not be nil" if username.nil?
|
|
89
|
-
logger = logger || Logger.new(STDOUT)
|
|
90
|
-
|
|
91
|
-
begin
|
|
92
|
-
|
|
93
|
-
uri = https ? URI::HTTPS.build(host: host, path: "/ws.php", query: "format=json") :
|
|
94
|
-
URI::HTTP.build(host: host, path: "/ws.php", query: "format=json")
|
|
95
|
-
|
|
96
|
-
# Create the HTTP objects
|
|
97
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
98
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
|
99
|
-
request.body = "method=pwg.session.login&username=#{username}&password=#{password}"
|
|
100
|
-
|
|
101
|
-
# Send the request
|
|
102
|
-
response = http.request(request)
|
|
103
|
-
|
|
104
|
-
if response.code == '200'
|
|
105
|
-
logger.info "Login succeeded: #{response.body}"
|
|
106
|
-
pwg_id = response.response['set-cookie'].split(';').select { |i| i.strip.start_with? "pwg_id" }.first
|
|
107
|
-
return Session.new(pwg_id, uri)
|
|
108
|
-
else
|
|
109
|
-
logger.error "Login failed: #{response.body}"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
113
|
-
logger.error "Login failed: #{e.messages}"
|
|
114
|
-
end
|
|
115
|
-
nil
|
|
116
|
-
end
|
|
113
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
|
114
|
+
logger.error "Login failed: #{e.messages}"
|
|
115
|
+
end
|
|
116
|
+
nil
|
|
117
117
|
end
|
|
118
|
-
end
|
|
118
|
+
end
|
|
119
|
+
end
|
data/lib/piwigo/version.rb
CHANGED
data/lib/piwigo.rb
CHANGED
data/piwigo-api.gemspec
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
lib = File.expand_path(
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require
|
|
3
|
+
require 'piwigo/version'
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name =
|
|
6
|
+
spec.name = 'piwigo-api'
|
|
7
7
|
spec.version = Piwigo::VERSION
|
|
8
|
-
spec.authors = [
|
|
9
|
-
spec.email = [
|
|
8
|
+
spec.authors = ['Adrian Gilbert']
|
|
9
|
+
spec.email = ['adrian@gilbert.ca']
|
|
10
10
|
|
|
11
|
-
spec.summary =
|
|
12
|
-
spec.description =
|
|
13
|
-
spec.homepage =
|
|
14
|
-
spec.license =
|
|
11
|
+
spec.summary = 'Gem to interact with the Piwigo API'
|
|
12
|
+
spec.description = 'Piwigo is open source web application to manage your collection of photos, and other medias. Piwigo provides an API for interacting with it. This is a ruby-based client for interacting with a Piwigo instance using the Piwigo API.'
|
|
13
|
+
spec.homepage = 'https://github.com/kkdad/piwigo-api'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
15
|
|
|
16
|
-
spec.metadata[
|
|
17
|
-
spec.metadata[
|
|
18
|
-
spec.metadata[
|
|
19
|
-
spec.metadata[
|
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/kkdad/piwigo-api'
|
|
18
|
+
spec.metadata['changelog_uri'] = 'https://github.com/kkdad/piwigo-api/CHANGELOG.md'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://rubydoc.info/github/KKDad/piwigo-api/master'
|
|
20
20
|
|
|
21
21
|
# Specify which files should be added to the gem when it is released.
|
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
23
|
-
spec.files
|
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
24
24
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
25
25
|
end
|
|
26
|
-
spec.bindir =
|
|
26
|
+
spec.bindir = 'exe'
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
-
spec.require_paths = [
|
|
28
|
+
spec.require_paths = ['lib']
|
|
29
29
|
|
|
30
|
-
spec.add_development_dependency
|
|
31
|
-
spec.add_development_dependency
|
|
32
|
-
spec.add_development_dependency
|
|
30
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
31
|
+
spec.add_development_dependency 'codecov', '>= 0.1.10'
|
|
32
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
33
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
33
34
|
|
|
34
|
-
spec.add_runtime_dependency
|
|
35
|
-
spec.add_runtime_dependency
|
|
35
|
+
spec.add_runtime_dependency 'http', '~>4.2'
|
|
36
|
+
spec.add_runtime_dependency 'logger', '~>1.4'
|
|
36
37
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: piwigo-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrian Gilbert
|
|
@@ -25,19 +25,19 @@ dependencies:
|
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '2.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: codecov
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 0.1.10
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 0.1.10
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: minitest
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -53,19 +53,19 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '5.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: rake
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
62
|
-
type: :
|
|
61
|
+
version: '10.0'
|
|
62
|
+
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
68
|
+
version: '10.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: http
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,6 +80,20 @@ dependencies:
|
|
|
80
80
|
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '4.2'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: logger
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.4'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '1.4'
|
|
83
97
|
description: Piwigo is open source web application to manage your collection of photos,
|
|
84
98
|
and other medias. Piwigo provides an API for interacting with it. This is a ruby-based
|
|
85
99
|
client for interacting with a Piwigo instance using the Piwigo API.
|
|
@@ -92,6 +106,7 @@ files:
|
|
|
92
106
|
- ".github/workflows/gempush.yml"
|
|
93
107
|
- ".github/workflows/ruby.yml"
|
|
94
108
|
- ".gitignore"
|
|
109
|
+
- ".rubocop.yaml"
|
|
95
110
|
- ".travis.yml"
|
|
96
111
|
- ".vscode/launch.json"
|
|
97
112
|
- CHANGELOG.md
|
|
@@ -105,6 +120,7 @@ files:
|
|
|
105
120
|
- codecov.yml
|
|
106
121
|
- lib/piwigo.rb
|
|
107
122
|
- lib/piwigo/albums.rb
|
|
123
|
+
- lib/piwigo/image_uploader.rb
|
|
108
124
|
- lib/piwigo/images.rb
|
|
109
125
|
- lib/piwigo/session.rb
|
|
110
126
|
- lib/piwigo/version.rb
|