redd 0.8.0.pre.2 → 0.8.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/README.md +4 -0
- data/bin/console +1 -1
- data/lib/redd/api_client.rb +1 -1
- data/lib/redd/models/basic_model.rb +5 -0
- data/lib/redd/models/conversation.rb +82 -0
- data/lib/redd/models/listing.rb +5 -0
- data/lib/redd/models/live_thread.rb +67 -0
- data/lib/redd/models/mod_mail.rb +45 -0
- data/lib/redd/models/more_comments.rb +5 -0
- data/lib/redd/models/postable.rb +10 -0
- data/lib/redd/models/session.rb +32 -14
- data/lib/redd/models/submission.rb +11 -0
- data/lib/redd/models/subreddit.rb +1 -0
- data/lib/redd/utilities/error_handler.rb +5 -4
- data/lib/redd/utilities/unmarshaller.rb +11 -9
- data/lib/redd/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca106c8ea55f1c1278f643802a357163ebca48cc
|
4
|
+
data.tar.gz: 38302c79dbc6c94813c182b5b0ec2b0cae02c124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c379f17013fbd83957752e7e745b8f55bc37b96f7cb96ad4d08252f1857b57258cf2fe5fcb8a711f65217908ad703b2e4a506720833226fcc89d36fefe2e9f62
|
7
|
+
data.tar.gz: a95cee5b5b15124d6867f1a998c9abb21b7aace479d23ff32e85e86b06c6dac129ffa9dedfc169ce6612a1bfe07614b5a79d8b4d1e5fd506b938bc0bd8b4cdfb
|
data/README.md
CHANGED
@@ -40,6 +40,10 @@ end
|
|
40
40
|
**Yes**, that's all there is to it! You don't need to handle rate-limiting, refresh access tokens
|
41
41
|
or protect against issues on reddit's end (like 5xx errors).
|
42
42
|
|
43
|
+
#### Where can I find the documentation?
|
44
|
+
|
45
|
+
[**Latest**](www.rubydoc.info/gems/redd) / [**GitHub**](http://www.rubydoc.info/github/avinashbot/redd/master/Redd/Models/Session)
|
46
|
+
|
43
47
|
#### How can I contact you?
|
44
48
|
[Reddit](https://www.reddit.com/message/compose/?to=Mustermind) /
|
45
49
|
[GitHub](https://github.com/avinashbot/redd/issues/new) /
|
data/bin/console
CHANGED
@@ -37,7 +37,7 @@ server.mount_proc '/authenticate' do |_, res|
|
|
37
37
|
state: '0',
|
38
38
|
redirect_uri: 'http://localhost:8000/redirect',
|
39
39
|
'scope': %w(identity read subscribe privatemessages wikiread submit vote edit modposts history
|
40
|
-
modflair modconfig)
|
40
|
+
modflair modconfig modmail livemanage)
|
41
41
|
)
|
42
42
|
)
|
43
43
|
end
|
data/lib/redd/api_client.rb
CHANGED
@@ -66,7 +66,7 @@ module Redd
|
|
66
66
|
|
67
67
|
def model(verb, path, options = {})
|
68
68
|
# XXX: make unmarshal explicit in methods?
|
69
|
-
unmarshal(
|
69
|
+
unmarshal(send(verb, path, options).body)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Makes a request, ensuring not to break the rate limit by sleeping.
|
@@ -56,6 +56,11 @@ module Redd
|
|
56
56
|
@attributes
|
57
57
|
end
|
58
58
|
|
59
|
+
# @return [Array<self>] an array representation of self
|
60
|
+
def to_ary
|
61
|
+
[self]
|
62
|
+
end
|
63
|
+
|
59
64
|
# Checks whether an attribute is supported by method_missing.
|
60
65
|
# @param method_name [Symbol] the method name or attribute to check
|
61
66
|
# @param include_private [Boolean] whether to also include private methods
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lazy_model'
|
4
|
+
|
5
|
+
module Redd
|
6
|
+
module Models
|
7
|
+
# Represents a conversation in the new modmail.
|
8
|
+
# TODO: add message and modmail-specific user type
|
9
|
+
class Conversation < LazyModel
|
10
|
+
# Get a Conversation from its id.
|
11
|
+
# @option hash [String] :id the base36 id (e.g. abc123)
|
12
|
+
# @return [Conversation]
|
13
|
+
def self.from_response(client, hash)
|
14
|
+
id = hash.fetch(:id)
|
15
|
+
new(client) do |c|
|
16
|
+
response = c.get("/api/mod/conversations/#{id}").body
|
17
|
+
response[:conversation].merge(
|
18
|
+
messages: response[:messages],
|
19
|
+
user: response[:user],
|
20
|
+
mod_actions: response[:modActions]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get a Conversation from its id.
|
26
|
+
# @param id [String] the base36 id (e.g. abc123)
|
27
|
+
# @return [Conversation]
|
28
|
+
def self.from_id(client, id)
|
29
|
+
from_response(client, id: id)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Mark this conversation as read.
|
33
|
+
def mark_as_read
|
34
|
+
@client.post('/api/mod/conversations/read', conversationIds: [get_attribute(:id)])
|
35
|
+
end
|
36
|
+
|
37
|
+
# Mark this conversation as unread.
|
38
|
+
def mark_as_unread
|
39
|
+
@client.post('/api/mod/conversations/unread', conversationIds: [get_attribute(:id)])
|
40
|
+
end
|
41
|
+
|
42
|
+
# Mark this conversation as archived.
|
43
|
+
def archive
|
44
|
+
perform_action(:post, 'archive')
|
45
|
+
end
|
46
|
+
|
47
|
+
# Removed this conversation from archived.
|
48
|
+
def unarchive
|
49
|
+
perform_action(:post, 'unarchive')
|
50
|
+
end
|
51
|
+
|
52
|
+
# Highlight this conversation.
|
53
|
+
def highlight
|
54
|
+
perform_action(:post, 'highlight')
|
55
|
+
end
|
56
|
+
|
57
|
+
# Remove the highlight on this conversation.
|
58
|
+
def unhighlight
|
59
|
+
perform_action(:delete, 'highlight')
|
60
|
+
end
|
61
|
+
|
62
|
+
# Mute this conversation.
|
63
|
+
def mute
|
64
|
+
perform_action(:post, 'mute')
|
65
|
+
end
|
66
|
+
|
67
|
+
# Unmute this conversation.
|
68
|
+
def unmute
|
69
|
+
perform_action(:post, 'unmute')
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Perform an action on a conversation.
|
75
|
+
# @param method [:post, :delete] the method to use
|
76
|
+
# @param action [String] the name of the action
|
77
|
+
def perform_action(method, action)
|
78
|
+
@client.send(method, "/api/mod/conversations/#{id}/#{action}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/redd/models/listing.rb
CHANGED
@@ -16,6 +16,11 @@ module Redd
|
|
16
16
|
new(client, hash)
|
17
17
|
end
|
18
18
|
|
19
|
+
# @return [Array<Comment, Submission, PrivateMessage>] an array representation of self
|
20
|
+
def to_ary
|
21
|
+
get_attribute(:children)
|
22
|
+
end
|
23
|
+
|
19
24
|
%i([] each empty? first last).each do |method_name|
|
20
25
|
define_method(method_name) do |*args, &block|
|
21
26
|
get_attribute(:children).public_send(method_name, *args, &block)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lazy_model'
|
4
|
+
|
5
|
+
module Redd
|
6
|
+
module Models
|
7
|
+
# Represents a live thread.
|
8
|
+
class LiveThread < LazyModel
|
9
|
+
# Get a Conversation from its id.
|
10
|
+
# @option hash [String] :id the base36 id (e.g. abc123)
|
11
|
+
# @return [Conversation]
|
12
|
+
def self.from_response(client, hash)
|
13
|
+
id = hash.fetch(:id)
|
14
|
+
new(client, hash) { |c| c.get("/live/#{id}/about").body[:data] }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get a LiveThread from its id.
|
18
|
+
# @param id [String] the id
|
19
|
+
# @return [LiveThread]
|
20
|
+
def self.from_id(client, id)
|
21
|
+
from_response(client, id: id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Configure the settings of this live thread
|
25
|
+
# @param params [Hash] a list of params to send with the request
|
26
|
+
# @option params [String] :description the new description
|
27
|
+
# @option params [Boolean] :nsfw whether the thread is for users 18 and above
|
28
|
+
# @option params [String] :resources the new resources
|
29
|
+
# @option params [String] :title the thread title
|
30
|
+
def configure(**params)
|
31
|
+
@client.post("/api/live/#{get_attribute(:id)}/edit", params)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Add an update to this live event.
|
35
|
+
# @param body [String] the update text
|
36
|
+
def update(body)
|
37
|
+
@client.post("/api/live/#{get_attribute(:id)}/update", body: body)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Array<User>] the contributors to this thread
|
41
|
+
def contributors
|
42
|
+
@client.get("/live/#{get_attribute(:id)}/contributors").body[0][:data].map do |user|
|
43
|
+
User.from_response(@client, user)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Array<User>] users invited to contribute to this thread
|
48
|
+
def invited_contributors
|
49
|
+
@client.get("/live/#{get_attribute(:id)}/contributors").body[1][:data].map do |user|
|
50
|
+
User.from_response(@client, user)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns all discussions that link to this live thread.
|
55
|
+
# @param params [Hash] a list of params to send with the request
|
56
|
+
# @option params [String] :after return results after the given fullname
|
57
|
+
# @option params [String] :before return results before the given fullname
|
58
|
+
# @option params [Integer] :count the number of items already seen in the listing
|
59
|
+
# @option params [1..100] :limit the maximum number of things to return
|
60
|
+
#
|
61
|
+
# @return [Listing<Submission>]
|
62
|
+
def discussions(**params)
|
63
|
+
@client.model(:get, "/live/#{get_attribute(:id)}/discussions", params)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'basic_model'
|
4
|
+
require_relative 'subreddit'
|
5
|
+
require_relative 'conversation'
|
6
|
+
|
7
|
+
module Redd
|
8
|
+
module Models
|
9
|
+
# A container for the new modmail.
|
10
|
+
# XXX: Instead of making ModMail a dumb container, could it be a lazy wrapper for #unread_count?
|
11
|
+
class ModMail < BasicModel
|
12
|
+
# @return [#highlighted, #notifications, #archived, #new, #inprogress, #mod] the number of
|
13
|
+
# unread messages in each category
|
14
|
+
def unread_count
|
15
|
+
BasicModel.new(nil, @client.get('/api/mod/conversations/unread/count').body)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Array<Subreddit>] moderated subreddits that are enrolled in the new modmail
|
19
|
+
def enrolled
|
20
|
+
@client.get('/api/mod/conversations/subreddits').body[:subreddits].map do |_, s|
|
21
|
+
Subreddit.from_response(@client, s.merge(last_updated: s.delete(:lastUpdated)))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the conversations
|
26
|
+
# @param after [String] base36 modmail conversation id
|
27
|
+
# @param subreddits [Subreddit, Array<Subreddit>] the subreddits to limit to
|
28
|
+
# @param limit [Integer] an integer (default: 25)
|
29
|
+
# @param sort [:recent, :mod, :user, :unread] the sort order
|
30
|
+
# @param state [:new, :inprogress, :mod, :notifications, :archived, :highlighted, :all] the
|
31
|
+
# state to limit the conversations by
|
32
|
+
def conversations(subreddits: nil, **params)
|
33
|
+
params[:entity] = Array(subreddits).map(&:display_name).join(',') if subreddits
|
34
|
+
@client.get('/api/mod/conversations', **params).body
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get a conversation from its base36 id.
|
38
|
+
# @param id [String] the conversation's id
|
39
|
+
# @return [Conversation]
|
40
|
+
def get(id)
|
41
|
+
Conversation.from_id(@client, id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -19,6 +19,11 @@ module Redd
|
|
19
19
|
)
|
20
20
|
end
|
21
21
|
|
22
|
+
# @return [Array<String>] an array representation of self
|
23
|
+
def to_ary
|
24
|
+
get_attribute(:children)
|
25
|
+
end
|
26
|
+
|
22
27
|
# Keep expanding until all top-level MoreComments are converted to comments
|
23
28
|
def recursive_expand(link:, sort: 'best')
|
24
29
|
# FIXME: this returns a flattened listing of comments and doesn't preserve the structure
|
data/lib/redd/models/postable.rb
CHANGED
@@ -56,6 +56,16 @@ module Redd
|
|
56
56
|
vote(0)
|
57
57
|
end
|
58
58
|
|
59
|
+
# Send replies to this thing to the user's inbox.
|
60
|
+
def enable_inbox_replies
|
61
|
+
@client.post('/api/sendreplies', id: get_attribute(:name), state: true)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Stop sending replies to this thing to the user's inbox.
|
65
|
+
def disable_inbox_replies
|
66
|
+
@client.post('/api/sendreplies', id: get_attribute(:name), state: false)
|
67
|
+
end
|
68
|
+
|
59
69
|
private
|
60
70
|
|
61
71
|
# Send a vote.
|
data/lib/redd/models/session.rb
CHANGED
@@ -9,6 +9,16 @@ module Redd
|
|
9
9
|
class Session < BasicModel
|
10
10
|
include Searchable
|
11
11
|
|
12
|
+
# @return [ModMail] the new modmail
|
13
|
+
def modmail
|
14
|
+
ModMail.new(@client)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [LiveThread] the live thread
|
18
|
+
def live_thread(id)
|
19
|
+
LiveThread.from_id(client, id)
|
20
|
+
end
|
21
|
+
|
12
22
|
# @return [FrontPage] the user's front page
|
13
23
|
def front_page
|
14
24
|
FrontPage.new(@client)
|
@@ -62,20 +72,14 @@ module Redd
|
|
62
72
|
|
63
73
|
# Return a listing of the user's inbox (including comment replies and private messages).
|
64
74
|
#
|
65
|
-
# @param category ['inbox', 'unread', 'sent']
|
66
|
-
#
|
67
|
-
# @param
|
68
|
-
#
|
69
|
-
# @
|
70
|
-
# @option params [
|
71
|
-
#
|
72
|
-
# @
|
73
|
-
# fullname.
|
74
|
-
# @option params [Integer] :count (0) The number of items already seen
|
75
|
-
# in the listing.
|
76
|
-
# @option params [1..100] :limit (25) The maximum number of things to
|
77
|
-
# return.
|
78
|
-
# @return [Listing]
|
75
|
+
# @param category ['inbox', 'unread', 'sent', 'moderator'] the category of messages to view
|
76
|
+
# @param mark [Boolean] whether to remove the orangered from the user's inbox
|
77
|
+
# @param params [Hash] a list of optional params to send with the request
|
78
|
+
# @option params [String] :after return results after the given fullname
|
79
|
+
# @option params [String] :before return results before the given fullname
|
80
|
+
# @option params [Integer] :count (0) the number of items already seen in the listing
|
81
|
+
# @option params [1..100] :limit (25) the maximum number of things to return
|
82
|
+
# @return [Listing<Comment, PrivateMessage>]
|
79
83
|
def my_messages(category: 'inbox', mark: false, **params)
|
80
84
|
@client.model(:get, "/message/#{category}.json", params.merge(mark: mark))
|
81
85
|
end
|
@@ -84,6 +88,20 @@ module Redd
|
|
84
88
|
def read_all_messages
|
85
89
|
@client.post('/api/read_all_messages')
|
86
90
|
end
|
91
|
+
|
92
|
+
# @return [Array<User>] the logged-in user's friends
|
93
|
+
def friends
|
94
|
+
@client.get('/api/v1/me/friends').body[:data][:children].map do |h|
|
95
|
+
User.from_response(@client, name: h[:name], id: h[:id].tr('t2_', ''), since: h[:date])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Array<User>] users blocked by the logged-in user
|
100
|
+
def blocked
|
101
|
+
@client.get('/prefs/blocked').body[:data][:children].map do |h|
|
102
|
+
User.from_response(@client, name: h[:name], id: h[:id].tr('t2_', ''), since: h[:date])
|
103
|
+
end
|
104
|
+
end
|
87
105
|
end
|
88
106
|
end
|
89
107
|
end
|
@@ -33,6 +33,17 @@ module Redd
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# Get all submissions for the same url.
|
37
|
+
# @param params [Hash] A list of optional params to send with the request.
|
38
|
+
# @option params [String] :after return results after the given fullname
|
39
|
+
# @option params [String] :before return results before the given fullname
|
40
|
+
# @option params [Integer] :count (0) the number of items already seen in the listing
|
41
|
+
# @option params [1..100] :limit (25) the maximum number of things to return
|
42
|
+
# @return [Listing<Submission>]
|
43
|
+
def duplicates(**params)
|
44
|
+
@client.unmarshal(@client.get("/duplicates/#{get_attribute(:id)}", params).body[1])
|
45
|
+
end
|
46
|
+
|
36
47
|
# Mark the link as "Not Suitable For Work".
|
37
48
|
def mark_as_nsfw
|
38
49
|
@client.get('/api/marknsfw', id: get_attribute(:name))
|
@@ -141,6 +141,7 @@ module Redd
|
|
141
141
|
# @return [Array<Hash>]
|
142
142
|
def relationship_listing(type, **params)
|
143
143
|
# TODO: add methods to determine if a certain user was banned/muted/etc
|
144
|
+
# TODO: return User types?
|
144
145
|
user_list = @client.get("/r/#{get_attribute(:display_name)}/about/#{type}", params).body
|
145
146
|
user_list[:data][:children]
|
146
147
|
end
|
@@ -8,7 +8,7 @@ module Redd
|
|
8
8
|
class ErrorHandler
|
9
9
|
HTTP_ERRORS = {
|
10
10
|
400 => Redd::BadRequest,
|
11
|
-
403 => Redd::Forbidden,
|
11
|
+
# 403 => Redd::Forbidden,
|
12
12
|
404 => Redd::NotFound,
|
13
13
|
500 => Redd::ServerError,
|
14
14
|
502 => Redd::ServerError,
|
@@ -23,12 +23,13 @@ module Redd
|
|
23
23
|
|
24
24
|
def check_error(response, raw:)
|
25
25
|
# TODO: deal with errors of type { fields:, explanation:, message:, reason: }
|
26
|
-
if !raw && response.body
|
27
|
-
!response.body[:json][:errors].empty?
|
26
|
+
if !raw && response.body.is_a?(Hash) && response.body[:json] &&
|
27
|
+
response.body[:json][:errors] && !response.body[:json][:errors].empty?
|
28
28
|
Redd::APIError.new(response)
|
29
29
|
elsif HTTP_ERRORS.key?(response.code)
|
30
30
|
HTTP_ERRORS[response.code].new(response)
|
31
|
-
elsif response.code == 401
|
31
|
+
elsif response.code == 401 || response.code == 403
|
32
|
+
# FIXME: i think insufficient_scope comes with 403 and invalid_token with 401
|
32
33
|
AUTHORIZATION_ERRORS.each do |key, klass|
|
33
34
|
auth_header = response.headers['www-authenticate']
|
34
35
|
return klass.new(response) if auth_header && auth_header.include?(key)
|
@@ -5,16 +5,18 @@ module Redd
|
|
5
5
|
# Unmarshals hashes into objects.
|
6
6
|
class Unmarshaller
|
7
7
|
# Contains the mapping from 'kind' strings to classes.
|
8
|
+
# TODO: UserList type!
|
8
9
|
MAPPING = {
|
9
|
-
't1'
|
10
|
-
't2'
|
11
|
-
't3'
|
12
|
-
't4'
|
13
|
-
't5'
|
14
|
-
'more'
|
15
|
-
'wikipage'
|
16
|
-
'Listing'
|
17
|
-
'LabeledMulti'
|
10
|
+
't1' => Models::Comment,
|
11
|
+
't2' => Models::User,
|
12
|
+
't3' => Models::Submission,
|
13
|
+
't4' => Models::PrivateMessage,
|
14
|
+
't5' => Models::Subreddit,
|
15
|
+
'more' => Models::MoreComments,
|
16
|
+
'wikipage' => Models::WikiPage,
|
17
|
+
'Listing' => Models::Listing,
|
18
|
+
'LabeledMulti' => Models::Multireddit,
|
19
|
+
'LiveUpdateEvent' => Models::LiveThread
|
18
20
|
}.freeze
|
19
21
|
|
20
22
|
def initialize(client)
|
data/lib/redd/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Avinash Dwarapu
|
@@ -152,11 +152,14 @@ files:
|
|
152
152
|
- lib/redd/models/access.rb
|
153
153
|
- lib/redd/models/basic_model.rb
|
154
154
|
- lib/redd/models/comment.rb
|
155
|
+
- lib/redd/models/conversation.rb
|
155
156
|
- lib/redd/models/front_page.rb
|
156
157
|
- lib/redd/models/inboxable.rb
|
157
158
|
- lib/redd/models/lazy_model.rb
|
158
159
|
- lib/redd/models/listing.rb
|
160
|
+
- lib/redd/models/live_thread.rb
|
159
161
|
- lib/redd/models/messageable.rb
|
162
|
+
- lib/redd/models/mod_mail.rb
|
160
163
|
- lib/redd/models/moderatable.rb
|
161
164
|
- lib/redd/models/more_comments.rb
|
162
165
|
- lib/redd/models/multireddit.rb
|
@@ -191,9 +194,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
194
|
version: '0'
|
192
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
196
|
requirements:
|
194
|
-
- - "
|
197
|
+
- - ">="
|
195
198
|
- !ruby/object:Gem::Version
|
196
|
-
version:
|
199
|
+
version: '0'
|
197
200
|
requirements: []
|
198
201
|
rubyforge_project:
|
199
202
|
rubygems_version: 2.6.8
|