weasyl-ruby 0.1.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 +7 -0
- data/lib/weasyl.rb +39 -0
- data/lib/weasyl/api.rb +59 -0
- data/lib/weasyl/media.rb +157 -0
- data/lib/weasyl/messages.rb +97 -0
- data/lib/weasyl/submission.rb +87 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4a1d6133b4d7d2241406cf52b4a8bdf5661b6ec3
|
4
|
+
data.tar.gz: 2ac8ef501b4271827d0ae8f0aeeed3fe1d0c375f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7cd7647771291b304b3e1b40c748224e8f2651e06f9fa165a96d7a77a96a2f1b03edc7d20efe2eb9c71e3302483914933f3526a8755a6b6b71ca986bd21c887b
|
7
|
+
data.tar.gz: 598cb59ae9f73dd7f65431e5ff90d7381e57548bfda4060dfedf5836b6cae6f8346aaa62bd48dae21268a1820bb51ae6402302879d244d0a788a48c00605065f
|
data/lib/weasyl.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Maxine Michalski <maxine@furfind.net>
|
4
|
+
#
|
5
|
+
# This file is part of Weasyl.
|
6
|
+
#
|
7
|
+
# Weasyl is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Weasyl is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Weasyl. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'open-uri'
|
21
|
+
require 'uri'
|
22
|
+
require 'json'
|
23
|
+
|
24
|
+
require_relative 'weasyl/api'
|
25
|
+
require_relative 'weasyl/messages'
|
26
|
+
require_relative 'weasyl/submission'
|
27
|
+
|
28
|
+
# Namespace for all classes in this gem.
|
29
|
+
# @author Maxine Michalski
|
30
|
+
# @since 0.1.0
|
31
|
+
module Weasyl
|
32
|
+
MAJOR = 0
|
33
|
+
MINOR = 1
|
34
|
+
PATCH = 0
|
35
|
+
NAME = 'weasyl-ruby'
|
36
|
+
AUTHOR = '~maxinered'
|
37
|
+
VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
38
|
+
USER_AGENT = "#{Weasyl::NAME}/#{Weasyl::VERSION} by #{Weasyl::AUTHOR}"
|
39
|
+
end
|
data/lib/weasyl/api.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Maxine Michalski <maxine@furfind.net>
|
4
|
+
#
|
5
|
+
# This file is part of Weasyl.
|
6
|
+
#
|
7
|
+
# Weasyl is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Weasyl is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Weasyl. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'singleton'
|
21
|
+
module Weasyl
|
22
|
+
# @author Maxine Michalski
|
23
|
+
# Helper class to abstract actual API communication
|
24
|
+
# @since 0.1.0
|
25
|
+
class API
|
26
|
+
include Singleton
|
27
|
+
# Sets the API key. OAuth isn't supported yet.
|
28
|
+
# @notice This method is not supposed to be used directly!
|
29
|
+
# @return [String] API key for weasyl API
|
30
|
+
attr_accessor :key
|
31
|
+
def fetch(endpoint, params = {})
|
32
|
+
params = if params.empty?
|
33
|
+
''
|
34
|
+
else
|
35
|
+
"?#{params.to_a.map { |a| a.join('=') }.join('&')}"
|
36
|
+
end
|
37
|
+
raise ArgumentError, 'API key can\'t be empty' if @key.nil?
|
38
|
+
JSON.parse(URI.parse("https://weasyl.com/api/#{endpoint}#{params}")
|
39
|
+
.read('X-Weasyl-API-Key' => @key, 'User-Agent' => Weasyl::USER_AGENT),
|
40
|
+
symbolize_names: true)
|
41
|
+
end
|
42
|
+
|
43
|
+
# A test method to test API connection
|
44
|
+
# @author Maxine Michalski
|
45
|
+
# @return [Hash] A Hash object with user information
|
46
|
+
# @since 0.1.0
|
47
|
+
def whoami
|
48
|
+
fetch(:whoami)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Display version of weasyl API we connected to
|
52
|
+
# @author Maxine Michalski
|
53
|
+
# @since 0.1.0
|
54
|
+
# @return [String] String that shows current weasyl API version
|
55
|
+
def version
|
56
|
+
fetch(:version)[:short_sha]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/weasyl/media.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Maxine Michalski <maxine@furfind.net>
|
4
|
+
#
|
5
|
+
# This file is part of Weasyl.
|
6
|
+
#
|
7
|
+
# Weasyl is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Weasyl is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Weasyl. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module Weasyl
|
21
|
+
# Container for media information
|
22
|
+
# @author Maxine Michalski
|
23
|
+
# @since 0.1.0
|
24
|
+
class Media
|
25
|
+
# @return [Array<Weasyl::Thumbnail>] List of thumbnails attached to this
|
26
|
+
# media item
|
27
|
+
attr_reader :thumbnails
|
28
|
+
|
29
|
+
# @return [Array<Weasyl::Thumbnail>] List of cover images attached to this
|
30
|
+
# media item
|
31
|
+
attr_reader :covers
|
32
|
+
|
33
|
+
# @return [Array<Weasyl::Thumbnail>] List of media files attached to this
|
34
|
+
# media item
|
35
|
+
attr_reader :media_files
|
36
|
+
|
37
|
+
# Initializer for a Media object
|
38
|
+
# @author Maxine Michalski
|
39
|
+
# @since 0.1.0
|
40
|
+
# @notice Special thumbnail objects are not supported at this point
|
41
|
+
# @return object
|
42
|
+
def initialize(media)
|
43
|
+
@thumbnails = media[:thumbnail].map { |m| Weasyl::Thumbnail.new(m) }
|
44
|
+
unless media[:cover].nil?
|
45
|
+
@covers = media[:cover].map { |m| Weasyl::Cover.new(m) }
|
46
|
+
end
|
47
|
+
return if media[:submission].nil?
|
48
|
+
@media_files = media[:submission].map { |m| Weasyl::MediaFile.new(m) }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Test for the presence of covers
|
52
|
+
# @author Maxine Michalski
|
53
|
+
# @since 0.1.0
|
54
|
+
# @return [Boolean]
|
55
|
+
def covers?
|
56
|
+
!@covers.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
# Test for the presence of media files
|
60
|
+
# @author Maxine Michalski
|
61
|
+
# @since 0.1.0
|
62
|
+
# @return [Boolean]
|
63
|
+
def media_files?
|
64
|
+
!@media_files.nil?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Base class for media items
|
69
|
+
# @author Maxine Michalski
|
70
|
+
# @since 0.1.0
|
71
|
+
class MediaItem
|
72
|
+
# @return [Integer] Media ID of this item
|
73
|
+
# @notice Can be nil
|
74
|
+
attr_reader :id
|
75
|
+
|
76
|
+
# @return [URI] Media URL to thumbnail
|
77
|
+
attr_reader :url
|
78
|
+
|
79
|
+
# @return [Array<Weasyl::Link>] Links to other media
|
80
|
+
# @notice This attribute can be nil
|
81
|
+
attr_reader :links
|
82
|
+
|
83
|
+
# Shared initializer for all Media items
|
84
|
+
# @author Maxine Michalski
|
85
|
+
# @since 0.1.0
|
86
|
+
def initialize(item)
|
87
|
+
@id = item[:mediaid]
|
88
|
+
@url = URI.parse(item[:url])
|
89
|
+
return if item[:links].nil?
|
90
|
+
@links = item[:links].map do |k, v|
|
91
|
+
Weasyl::Link.new(k, v)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Indicator of if this MediaItem has an ID or not
|
96
|
+
# @author Maxine Michalski
|
97
|
+
# @since 0.1.0
|
98
|
+
# @return [Boolean]
|
99
|
+
def id?
|
100
|
+
!@id.nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
# Indicator of if this MediaItem object has links or not
|
104
|
+
# @author Maxine Michalski
|
105
|
+
# @since 0.1.0
|
106
|
+
# @return [Boolean]
|
107
|
+
def links?
|
108
|
+
!@links.nil?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Container for Thumbnail information
|
113
|
+
# @author Maxine Michalski
|
114
|
+
# @since 0.1.0
|
115
|
+
class Thumbnail < MediaItem
|
116
|
+
end
|
117
|
+
|
118
|
+
# Container for cover images
|
119
|
+
# @author Maxine Michalski
|
120
|
+
# @since 0.1.0
|
121
|
+
class Cover < MediaItem
|
122
|
+
end
|
123
|
+
|
124
|
+
# Container for Submission media info (the actual file)
|
125
|
+
# @author Maxine Michalski
|
126
|
+
# @since 0.1.0
|
127
|
+
class MediaFile < MediaItem
|
128
|
+
end
|
129
|
+
|
130
|
+
# A relationship between MediaItems
|
131
|
+
# @author Maxine Michalski
|
132
|
+
# @since 0.1.0
|
133
|
+
class Link
|
134
|
+
# @return [Symbol] Type of item this link links
|
135
|
+
attr_reader :type
|
136
|
+
|
137
|
+
# @return [Array<Weasyl::MediaItem>] Items that are linked to
|
138
|
+
attr_reader :links
|
139
|
+
|
140
|
+
# Initializer for link object
|
141
|
+
# @author Maxine Michalski
|
142
|
+
# @since 0.1.0
|
143
|
+
# @return object
|
144
|
+
def initialize(type, link)
|
145
|
+
case @type = type
|
146
|
+
when :cover
|
147
|
+
@links = link.map { |l| Weasyl::Cover.new(l) }
|
148
|
+
when :thumbnail
|
149
|
+
@links = link.map { |l| Weasyl::Thumbnail.new(l) }
|
150
|
+
when :submission
|
151
|
+
@links = link.map { |l| Weasyl::MediaFile.new(l) }
|
152
|
+
else
|
153
|
+
raise ArgumentError, "Unknown type: #{@type}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Maxine Michalski <maxine@furfind.net>
|
4
|
+
#
|
5
|
+
# This file is part of Weasyl.
|
6
|
+
#
|
7
|
+
# Weasyl is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Weasyl is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Weasyl. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module Weasyl
|
21
|
+
# Helper module to fetch information about messages.
|
22
|
+
# @author Maxine Michalski
|
23
|
+
# @since 0.1.0
|
24
|
+
module Messages
|
25
|
+
# Fetch a summary of new message counts
|
26
|
+
# @author Maxine Michalski
|
27
|
+
# @since 0.1.0
|
28
|
+
# @return [Weasyl::Messages::Summary]
|
29
|
+
def self.summary
|
30
|
+
Weasyl::Messages::Summary.new(Weasyl::API.instance
|
31
|
+
.fetch('messages/summary'))
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fetch a list of submissions for the currently logged in user
|
35
|
+
# @author Maxine Michalski
|
36
|
+
# @since 0.1.0
|
37
|
+
# @param count [Integer] max amount of submissions returned (100)
|
38
|
+
# @param backtime [Integer] UNIX EPOCH, only submissions after this time are
|
39
|
+
# returned
|
40
|
+
# @param nexttime [Integer] UNIX EPOCH, only submissions before this time
|
41
|
+
# are returned
|
42
|
+
# @notice This method accepts a block, that goes through all available
|
43
|
+
# submissions. While the non-block version only returns 100 submissions at
|
44
|
+
# all.
|
45
|
+
# @return [Weasyl::SubmissionList]
|
46
|
+
def self.submissions(count = 100, backtime = 0, nexttime = Time.now.to_i)
|
47
|
+
params = { count: count, backtime: backtime, nexttime: nexttime }
|
48
|
+
subs = nil
|
49
|
+
loop do
|
50
|
+
subs = fetch_subs(params)
|
51
|
+
break if subs[:nexttime].nil? || !block_given?
|
52
|
+
subs[:submissions].each { |s| yield s }
|
53
|
+
params[:nexttime] = subs[:nexttime]
|
54
|
+
end
|
55
|
+
subs
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.fetch_subs(params)
|
59
|
+
subs = Weasyl::API.instance.fetch('messages/submissions', params)
|
60
|
+
subs[:submissions].map! do |s|
|
61
|
+
Weasyl::Submission.new(s)
|
62
|
+
end
|
63
|
+
subs
|
64
|
+
end
|
65
|
+
private_class_method :fetch_subs
|
66
|
+
|
67
|
+
# Class that represents a summary of message information.
|
68
|
+
# @author Maxine Michalski
|
69
|
+
# @since 0.1.0
|
70
|
+
class Summary
|
71
|
+
# @return [Integer] Count of unread comments
|
72
|
+
attr_reader :comments
|
73
|
+
|
74
|
+
# @return [Integer] Count of unread journals
|
75
|
+
attr_reader :journals
|
76
|
+
|
77
|
+
# @return [Integer] Count of unread notifications
|
78
|
+
attr_reader :notifications
|
79
|
+
|
80
|
+
# @return [Integer] Count of unseen submissions
|
81
|
+
attr_reader :submissions
|
82
|
+
|
83
|
+
# @return [Integer] Count of unread notes
|
84
|
+
attr_reader :unread_notes
|
85
|
+
|
86
|
+
# Initializer for Message summaries
|
87
|
+
# @author Maxine Michalski
|
88
|
+
# @since 0.1.0
|
89
|
+
# @return object
|
90
|
+
def initialize(sum)
|
91
|
+
sum.each do |k, v|
|
92
|
+
instance_variable_set("@#{k}".to_sym, v)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Maxine Michalski <maxine@furfind.net>
|
4
|
+
#
|
5
|
+
# This file is part of Weasyl.
|
6
|
+
#
|
7
|
+
# Weasyl is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Weasyl is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Weasyl. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'time'
|
21
|
+
require_relative 'media'
|
22
|
+
|
23
|
+
module Weasyl
|
24
|
+
# Container for submission information
|
25
|
+
# @author Maxine Michalski
|
26
|
+
# @since 0.1.0
|
27
|
+
class Submission
|
28
|
+
# @return [String] Owner of submission
|
29
|
+
attr_reader :owner
|
30
|
+
|
31
|
+
# @return [String] Owner of submission
|
32
|
+
attr_reader :owner_login
|
33
|
+
|
34
|
+
# @return [Time] Timestamp when submission was uploaded
|
35
|
+
attr_reader :posted_at
|
36
|
+
|
37
|
+
# @return [String] Rating marker
|
38
|
+
attr_reader :rating
|
39
|
+
|
40
|
+
# @return [Integer] Submission id
|
41
|
+
attr_reader :id
|
42
|
+
|
43
|
+
# @return [String] Submission sub-type
|
44
|
+
attr_reader :subtype
|
45
|
+
|
46
|
+
# @return [Array<String>] Tags associated with this submission
|
47
|
+
attr_reader :tags
|
48
|
+
|
49
|
+
# @return [String] Title of submission
|
50
|
+
attr_reader :title
|
51
|
+
|
52
|
+
# @return [String] Type of submission
|
53
|
+
attr_reader :type
|
54
|
+
|
55
|
+
# @return [URI] Link to submision
|
56
|
+
attr_reader :link
|
57
|
+
|
58
|
+
# @return [Weasyl::Media] Media object for current submission
|
59
|
+
attr_reader :media
|
60
|
+
|
61
|
+
# Initializer for Submission containers
|
62
|
+
# @author Maxine Michalski
|
63
|
+
# @since 0.1.0
|
64
|
+
# @return object
|
65
|
+
def initialize(sub)
|
66
|
+
sub.select! do |k, _|
|
67
|
+
%i[rating tags link owner owner_login submitid title media posted_at
|
68
|
+
subtype type].include?(k)
|
69
|
+
end
|
70
|
+
sub_prepared(sub).each do |k, v|
|
71
|
+
instance_variable_set("@#{k}".to_sym, v)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def sub_prepared(sub)
|
78
|
+
sub.map do |k, v|
|
79
|
+
v = Time.parse(v) if k == :posted_at
|
80
|
+
v = URI.parse(v) if k == :link
|
81
|
+
v = Weasyl::Media.new(v) if k == :media
|
82
|
+
k = :id if k == :submitid
|
83
|
+
[k, v]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: weasyl-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maxine Michalski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
description: Ruby bindings for the weasyl art board
|
28
|
+
email: maxine@furfind.net
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/weasyl.rb
|
34
|
+
- lib/weasyl/api.rb
|
35
|
+
- lib/weasyl/media.rb
|
36
|
+
- lib/weasyl/messages.rb
|
37
|
+
- lib/weasyl/submission.rb
|
38
|
+
homepage: https://github.com/maxine-red/weasyl
|
39
|
+
licenses:
|
40
|
+
- GPL-3.0
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '2.3'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.5.2.1
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Ruby bindings for weasyl
|
62
|
+
test_files: []
|