rgroups 0.1.0 → 0.2.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.
- data/README.rdoc +25 -0
- data/VERSION +1 -1
- data/lib/rgroups.rb +114 -2
- data/rgroups.gemspec +65 -0
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
Ruby API for accessing/updating Google Groups - based on Mechanize. This essentially just screen-scrapes Google Groups and automates clicking on things. It's not entirely efficient, but it sure beats having to script it yourself.
|
4
4
|
|
5
|
+
== Usage
|
6
|
+
Setup is easy!
|
7
|
+
require 'rgroups'
|
8
|
+
rg = RGroup.new
|
9
|
+
rg.login('username', 'password')
|
10
|
+
|
11
|
+
Or, if you're using Google Apps for your Domain (GAFYD):
|
12
|
+
rg = RGroup.new('mydomain.com')
|
13
|
+
rg.login('username', 'password')
|
14
|
+
|
15
|
+
Adding a user to a group:
|
16
|
+
rg.add_user('address@domain.com', 'group', :message => 'message to send to invitees')
|
17
|
+
|
18
|
+
Adding a user directly (only for GAFYD accounts):
|
19
|
+
rg.add_user('address@mydomain.com', 'group', :mode => 'direct', :notify => true, :message => 'message to send to people', :delivery => 'digest')
|
20
|
+
|
21
|
+
Modifying a user's delivery options:
|
22
|
+
rg.update_user('address@domain.com', 'group', 'set_delivery', :value => 'summary')
|
23
|
+
|
24
|
+
Modifying a user's membership type:
|
25
|
+
rg.update_user('address@domain.com', 'group', 'set_member', :value => 'manager')
|
26
|
+
|
27
|
+
== Notes
|
28
|
+
This relies on the 'old style' Google Groups. Please ensure that your group is using the old style before reporting a bug. Support for the new style should come soon...
|
29
|
+
|
5
30
|
== Contributing to rgroups
|
6
31
|
|
7
32
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/rgroups.rb
CHANGED
@@ -6,6 +6,10 @@ class RGroup
|
|
6
6
|
@@DIRECT_ADD = '/manage_members_add'
|
7
7
|
@@INVITE_ADD = '/members_invite'
|
8
8
|
@@GROUP_SETTINGS = '/manage_general'
|
9
|
+
@@ACCESS_SETTINGS = '/manage_access'
|
10
|
+
@@POST_SETTINGS = '/manage_post'
|
11
|
+
@@ADV_SETTINGS = '/manage_advanced'
|
12
|
+
@@SPAM_SETTINGS = '/manage_spam'
|
9
13
|
|
10
14
|
def initialize(*gafyd)
|
11
15
|
@scraper = Mechanize.new
|
@@ -19,7 +23,8 @@ class RGroup
|
|
19
23
|
@GAFYD = true
|
20
24
|
end
|
21
25
|
end
|
22
|
-
|
26
|
+
|
27
|
+
# login to google apps
|
23
28
|
def login(username, password)
|
24
29
|
page = @scraper.get(@LOGIN_URL)
|
25
30
|
f = page.forms[0]
|
@@ -28,6 +33,14 @@ class RGroup
|
|
28
33
|
@scraper.submit(f, f.buttons.first)
|
29
34
|
end
|
30
35
|
|
36
|
+
# add a user
|
37
|
+
# email = email address to add
|
38
|
+
# group = group name
|
39
|
+
# :mode => direct (only for gafyd accounts)
|
40
|
+
# :notify => true/false to notify users they've been added (only for gafyd)
|
41
|
+
# :delivery => only for gafyd
|
42
|
+
# - none, email, summary, one
|
43
|
+
# :message => message to send to person when being added
|
31
44
|
def add_user(email, group, opts={})
|
32
45
|
if (opts[:mode] && opts[:mode].downcase == "direct")
|
33
46
|
raise "direct add mode is only available for gafyd accounts" unless @GAFYD
|
@@ -73,6 +86,13 @@ class RGroup
|
|
73
86
|
@scraper.submit(member_form, member_form.button_with(:name => 'Action.InitialAddMembers'))
|
74
87
|
end
|
75
88
|
|
89
|
+
# update a user
|
90
|
+
# email = email address to update
|
91
|
+
# group = group name
|
92
|
+
# action = set_member, set_email
|
93
|
+
# :value => depends on what you're doing.
|
94
|
+
# - set_member: regular, manager, owner, unsubscribe, ban
|
95
|
+
# - set_email: none, email, summary, one
|
76
96
|
def update_user(email, group, action, opts={})
|
77
97
|
page = @scraper.get(@BASE_URL + group + @@MANAGE)
|
78
98
|
member_set = page.search('//table[@class="memlist"]//td')
|
@@ -120,9 +140,99 @@ class RGroup
|
|
120
140
|
|
121
141
|
end
|
122
142
|
|
143
|
+
# return a hash of group settings
|
144
|
+
def settings(group)
|
145
|
+
settings = {}
|
146
|
+
|
147
|
+
page = @scraper.get(@BASE_URL + group + @@GROUP_SETTINGS)
|
148
|
+
settings['group_name'] = page.search('//div[@id="name_view"]').text.strip
|
149
|
+
settings['group_description'] = page.search('//div[@id="desc_view"]').text.strip
|
150
|
+
settings['group_website'] = page.search('//div[@id="info_url_view"]').text.strip
|
151
|
+
|
152
|
+
|
153
|
+
page = @scraper.get(@BASE_URL + group + @@ACCESS_SETTINGS)
|
154
|
+
form = page.form_with(:id => "GM_form")
|
155
|
+
if (@GAFYD)
|
156
|
+
settings['allow_external'] = form.checkbox_with(:name => 'param.allow_external_members').checked?
|
157
|
+
end
|
158
|
+
form.radiobuttons_with(:name => 'param.archive_view').each do |r|
|
159
|
+
settings['archive_view'] = r.value if r.checked?
|
160
|
+
end
|
161
|
+
form.radiobuttons_with(:name => 'param.members_view').each do |r|
|
162
|
+
settings['member_view'] = r.value if r.checked?
|
163
|
+
end
|
164
|
+
form.radiobuttons_with(:name => 'param.who_can_join').each do |r|
|
165
|
+
settings['can_join'] = r.value if r.checked?
|
166
|
+
end
|
167
|
+
settings['join_question'] = form.field_with(:name => 'param.join_question').value.strip
|
168
|
+
form.radiobuttons_with(:name => 'param.who_can_post').each do |r|
|
169
|
+
settings['who_can_post'] = "managers" if r.checked? && r.value == 'm'
|
170
|
+
settings['who_can_post'] = "members" if r.checked? && r.value == 's'
|
171
|
+
settings['who_can_post'] = "domain" if r.checked? && r.value == 'd'
|
172
|
+
settings['who_can_post'] = "anyone" if r.checked? && r.value == 'p'
|
173
|
+
end
|
174
|
+
settings['mod_non_members'] = form.checkbox_with(:name => 'param.mod_non_members').checked?
|
175
|
+
settings['web_posting'] = form.checkbox_with(:name => 'param.allow_web_posting').checked?
|
176
|
+
form.radiobuttons_with(:name => 'param.who_can_invite').each do |r|
|
177
|
+
settings['who_can_invite'] = r.value if r.checked?
|
178
|
+
end
|
179
|
+
form.radiobuttons_with(:name => 'param.msg_moderation').each do |r|
|
180
|
+
settings['msg_moderation'] = r.value if r.checked?
|
181
|
+
end
|
182
|
+
settings['mod_new_members'] = form.checkbox_with(:name => 'param.mod_new_members').checked?
|
183
|
+
|
184
|
+
|
185
|
+
page = @scraper.get(@BASE_URL + group + @@POST_SETTINGS)
|
186
|
+
form = page.form_with(:id => "GM_form")
|
187
|
+
if (@GAFYD)
|
188
|
+
settings['custom_reply_to'] = form.field_with(:name => 'param.custom_reply_to').value.strip
|
189
|
+
form.field_with(:name => 'param.max_size').options.each do |s|
|
190
|
+
settings['max_size'] = s.value if s.selected?
|
191
|
+
end
|
192
|
+
settings['reply_with_bounce_list'] = form.checkbox_with(:name => 'param.reply_with_bounce_list').checked?
|
193
|
+
end
|
194
|
+
settings['subject_tag'] = form.field_with(:name => 'param.subject_tag').value.strip
|
195
|
+
form.radiobuttons_with(:name => 'param.footer').each do |r|
|
196
|
+
settings['message_footer'] = "none" if r.checked? && r.value == 'n'
|
197
|
+
settings['message_footer'] = "default" if r.checked? && r.value == 'd'
|
198
|
+
settings['message_footer'] = "custom" if r.checked? && r.value == 'c'
|
199
|
+
end
|
200
|
+
settings['reply_to'] = form.field_with(:name => 'param.footer_text').value.strip
|
201
|
+
form.radiobuttons_with(:name => 'param.reply_to').each do |r|
|
202
|
+
settings['reply_to'] = "whole_group" if r.checked? && r.value == 'l'
|
203
|
+
settings['reply_to'] = "author" if r.checked? && r.value == 'a'
|
204
|
+
settings['reply_to'] = "owner" if r.checked? && r.value == 'o'
|
205
|
+
settings['reply_to'] = "user_decide" if r.checked? && r.value == 'n'
|
206
|
+
settings['reply_to'] = "custom" if r.checked? && r.value == 'c'
|
207
|
+
end
|
208
|
+
settings['posting_as_group'] = form.checkbox_with(:name => 'param.posting_as_group').checked?
|
209
|
+
settings['moderation_notify'] = form.checkbox_with(:name => 'param.moderation_notify').checked?
|
210
|
+
settings['moderation_message_text'] = form.field_with(:name => 'param.footer_text').value.strip
|
211
|
+
|
212
|
+
page = @scraper.get(@BASE_URL + group + @@ADV_SETTINGS)
|
213
|
+
form = page.form_with(:id => "GM_form")
|
214
|
+
form.field_with(:name => 'param.lang').options.each do |s|
|
215
|
+
settings['primary_language'] = s.value if s.selected?
|
216
|
+
end
|
217
|
+
settings['fixed_font'] = form.checkbox_with(:name => 'param.font_type').checked?
|
218
|
+
settings['no_archive_msgs'] = form.checkbox_with(:name => 'param.no_archive').checked?
|
219
|
+
settings['group_is_archived'] = form.checkbox_with(:name => 'param.status_archive').checked?
|
220
|
+
settings['google_contact'] = form.checkbox_with(:name => 'param.can_contact').checked?
|
221
|
+
|
222
|
+
page = @scraper.get(@BASE_URL + group + @@SPAM_SETTINGS)
|
223
|
+
form = page.form_with(:id => "GM_form")
|
224
|
+
form.radiobuttons_with(:name => 'param.spam_mode').each do |r|
|
225
|
+
settings['spam_mode'] = "post" if r.checked? && r.value == '0'
|
226
|
+
settings['spam_mode'] = "mod" if r.checked? && r.value == '1'
|
227
|
+
settings['spam_mode'] = "mod_quiet" if r.checked? && r.value == '3'
|
228
|
+
settings['spam_mode'] = "reject" if r.checked? && r.value == '2'
|
229
|
+
end
|
230
|
+
return settings
|
231
|
+
end
|
232
|
+
|
123
233
|
end
|
124
234
|
|
125
|
-
# monkey-patch Mechanize so we can't reuse ssl sessions
|
235
|
+
# monkey-patch Mechanize::HTTP::Agent so we can't reuse ssl sessions
|
126
236
|
# as that seems to break things
|
127
237
|
class Mechanize::HTTP::Agent
|
128
238
|
def reuse_ssl_sessions
|
@@ -134,6 +244,8 @@ class Mechanize::HTTP::Agent
|
|
134
244
|
end
|
135
245
|
end
|
136
246
|
|
247
|
+
# monkey-patch Mechanize so we can't reuse ssl sessions
|
248
|
+
# as that seems to break things
|
137
249
|
class Mechanize
|
138
250
|
def reuse_ssl_sessions
|
139
251
|
@agent.reuse_ssl_sessions
|
data/rgroups.gemspec
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "rgroups"
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Andrew Hayworth"]
|
12
|
+
s.date = "2012-06-18"
|
13
|
+
s.description = "This is a Ruby API for accessing and updating Google Groups. It's based on Mechanize, which means it's essentially screen-scraping."
|
14
|
+
s.email = "ahayworth@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/rgroups.rb",
|
28
|
+
"rgroups.gemspec",
|
29
|
+
"test/helper.rb",
|
30
|
+
"test/test_rgroups.rb"
|
31
|
+
]
|
32
|
+
s.homepage = "http://github.com/ahayworth/rgroups"
|
33
|
+
s.licenses = ["MIT"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = "1.8.24"
|
36
|
+
s.summary = "Ruby API for accessing/updating Google Groups - based on Mechanize"
|
37
|
+
|
38
|
+
if s.respond_to? :specification_version then
|
39
|
+
s.specification_version = 3
|
40
|
+
|
41
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
42
|
+
s.add_runtime_dependency(%q<mechanize>, [">= 0"])
|
43
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
44
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
45
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
46
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
47
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<mechanize>, [">= 0"])
|
50
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
51
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
52
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
53
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
54
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<mechanize>, [">= 0"])
|
58
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
59
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
60
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
61
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
62
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgroups
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andrew Hayworth
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-18 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- Rakefile
|
123
123
|
- VERSION
|
124
124
|
- lib/rgroups.rb
|
125
|
+
- rgroups.gemspec
|
125
126
|
- test/helper.rb
|
126
127
|
- test/test_rgroups.rb
|
127
128
|
homepage: http://github.com/ahayworth/rgroups
|