campfire_export 0.1.0 → 0.1.1

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/Rakefile CHANGED
@@ -1,2 +1,6 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ rspec = RSpec::Core::RakeTask.new
6
+ rspec.rspec_opts = '-f Fuubar --color'
data/bin/campfire_export CHANGED
@@ -53,5 +53,14 @@ ensure_config_for(config, 'subdomain',
53
53
  ensure_config_for(config, 'api_token',
54
54
  "Your Campfire API token (see 'My Info' on your Campfire site)")
55
55
 
56
- account = CampfireExport::Account.new(config['subdomain'], config['api_token'])
57
- account.export(config_date(config, 'start_date'), config_date(config, 'end_date'))
56
+ begin
57
+ account = CampfireExport::Account.new(config['subdomain'],
58
+ config['api_token'])
59
+ account.find_timezone
60
+ account.rooms.each do |room|
61
+ room.export(config_date(config, 'start_date'),
62
+ config_date(config, 'end_date'))
63
+ end
64
+ rescue => e
65
+ puts "Unable to export account: #{e}"
66
+ end
@@ -17,6 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.required_ruby_version = '>= 1.8.7'
18
18
 
19
19
  s.add_development_dependency "bundler", "~> 1.0.15"
20
+ s.add_development_dependency "fuubar", "~> 0.0.5"
21
+ s.add_development_dependency "rspec", "~> 2.6.0"
20
22
  s.add_development_dependency "tzinfo", "~> 0.3.29"
21
23
  s.add_development_dependency "httparty", "~> 0.7.8"
22
24
  s.add_development_dependency "nokogiri", "~> 1.4.5"
@@ -162,7 +162,7 @@ module CampfireExport
162
162
  MAPPING.freeze
163
163
 
164
164
  def find_tzinfo(name)
165
- TZInfo::TimezoneProxy.new(MAPPING[name] || name)
165
+ TZInfo::Timezone.get(MAPPING[name] || name)
166
166
  end
167
167
  end
168
168
  end
@@ -1,3 +1,3 @@
1
1
  module CampfireExport
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -51,14 +51,10 @@ module CampfireExport
51
51
  def zero_pad(number)
52
52
  "%02d" % number
53
53
  end
54
-
55
- def account_dir
56
- "campfire/#{CampfireExport::Account.subdomain}"
57
- end
58
-
54
+
59
55
  # Requires that room and date be defined in the calling object.
60
56
  def export_dir
61
- "#{account_dir}/#{room.name}/" +
57
+ "campfire/#{Account.subdomain}/#{room.name}/" +
62
58
  "#{date.year}/#{zero_pad(date.mon)}/#{zero_pad(date.day)}"
63
59
  end
64
60
 
@@ -66,6 +62,7 @@ module CampfireExport
66
62
  def export_file(content, filename, mode='w')
67
63
  # Check to make sure we're writing into the target directory tree.
68
64
  true_path = File.expand_path(File.join(export_dir, filename))
65
+
69
66
  unless true_path.start_with?(File.expand_path(export_dir))
70
67
  raise CampfireExport::Exception.new("#{export_dir}/#{filename}",
71
68
  "can't export file to a directory higher than target directory; " +
@@ -133,45 +130,28 @@ module CampfireExport
133
130
  @subdomain = ""
134
131
  @api_token = ""
135
132
  @base_url = ""
136
- @timezone = ""
133
+ @timezone = nil
137
134
 
138
135
  class << self
139
136
  attr_accessor :subdomain, :api_token, :base_url, :timezone
140
137
  end
141
138
 
142
139
  def initialize(subdomain, api_token)
143
- CampfireExport::Account.subdomain = subdomain
144
- CampfireExport::Account.api_token = api_token
145
- CampfireExport::Account.base_url = "https://#{subdomain}.campfirenow.com"
146
-
147
- # Make the base directory immediately so we can start logging errors.
148
- FileUtils.mkdir_p account_dir
149
-
150
- CampfireExport::Account.timezone = parse_timezone
140
+ Account.subdomain = subdomain
141
+ Account.api_token = api_token
142
+ Account.base_url = "https://#{subdomain}.campfirenow.com"
151
143
  end
152
-
153
- def parse_timezone
154
- begin
155
- settings_html = Nokogiri::HTML get('/account/settings').body
156
- selected_zone = settings_html.css('select[id="account_time_zone_id"] ' +
157
- '> option[selected="selected"]')
158
- find_tzinfo(selected_zone.attribute("value").text)
159
- rescue => e
160
- log(:error, "couldn't find timezone setting (using GMT instead)", e)
161
- find_tzinfo("Etc/GMT")
162
- end
144
+
145
+ def find_timezone
146
+ settings = Nokogiri::HTML get('/account/settings').body
147
+ selected_zone = settings.css('select[id="account_time_zone_id"] ' +
148
+ '> option[selected="selected"]')
149
+ Account.timezone = find_tzinfo(selected_zone.attribute("value").text)
163
150
  end
164
-
165
- def export(start_date=nil, end_date=nil)
166
- begin
167
- doc = Nokogiri::XML get('/rooms.xml').body
168
- doc.css('room').each do |room_xml|
169
- room = CampfireExport::Room.new(room_xml)
170
- room.export(start_date, end_date)
171
- end
172
- rescue => e
173
- log(:error, "room list download failed", e)
174
- end
151
+
152
+ def rooms
153
+ doc = Nokogiri::XML get('/rooms.xml').body
154
+ doc.css('room').map {|room_xml| Room.new(room_xml) }
175
155
  end
176
156
  end
177
157
 
@@ -180,30 +160,21 @@ module CampfireExport
180
160
  attr_accessor :id, :name, :created_at, :last_update
181
161
 
182
162
  def initialize(room_xml)
183
- @id = room_xml.css('id').text
184
- @name = room_xml.css('name').text
185
-
186
- created_utc = DateTime.parse(room_xml.css('created-at').text)
187
- @created_at = CampfireExport::Account.timezone.utc_to_local(created_utc)
188
-
189
- begin
190
- last_message = Nokogiri::XML get("/room/#{id}/recent.xml?limit=1").body
191
- update_utc = DateTime.parse(last_message.css('created-at').text)
192
- @last_update = CampfireExport::Account.timezone.utc_to_local(update_utc)
193
- rescue => e
194
- log(:error, "couldn't get last update in #{room} (defaulting to today)", e)
195
- @last_update = Time.now
196
- end
163
+ @id = room_xml.css('id').text
164
+ @name = room_xml.css('name').text
165
+ created_utc = DateTime.parse(room_xml.css('created-at').text)
166
+ @created_at = Account.timezone.utc_to_local(created_utc)
197
167
  end
198
-
168
+
199
169
  def export(start_date=nil, end_date=nil)
200
170
  # Figure out how to do the least amount of work while still conforming
201
171
  # to the requester's boundary dates.
172
+ find_last_update
202
173
  start_date.nil? ? date = created_at : date = [start_date, created_at].max
203
174
  end_date.nil? ? end_date = last_update : end_date = [end_date, last_update].min
204
175
 
205
176
  while date <= end_date
206
- transcript = CampfireExport::Transcript.new(self, date)
177
+ transcript = Transcript.new(self, date)
207
178
  transcript.export
208
179
 
209
180
  # Ensure that we stay well below the 37signals API limits.
@@ -211,6 +182,20 @@ module CampfireExport
211
182
  date = date.next
212
183
  end
213
184
  end
185
+
186
+ private
187
+ def find_last_update
188
+ begin
189
+ last_message = Nokogiri::XML get("/room/#{id}/recent.xml?limit=1").body
190
+ update_utc = DateTime.parse(last_message.css('created-at').text)
191
+ @last_update = Account.timezone.utc_to_local(update_utc)
192
+ rescue Exception => e
193
+ log(:error,
194
+ "couldn't get last update in #{room} (defaulting to today)",
195
+ e)
196
+ @last_update = Time.now
197
+ end
198
+ end
214
199
  end
215
200
 
216
201
  class Transcript
@@ -242,7 +227,7 @@ module CampfireExport
242
227
  log(:info, "exporting transcripts\n")
243
228
  begin
244
229
  FileUtils.mkdir_p export_dir
245
- rescue => e
230
+ rescue Exception => e
246
231
  log(:error, "Unable to create #{export_dir}", e)
247
232
  else
248
233
  export_xml
@@ -260,7 +245,7 @@ module CampfireExport
260
245
  begin
261
246
  export_file(xml, 'transcript.xml')
262
247
  verify_export('transcript.xml', xml.to_s.length)
263
- rescue => e
248
+ rescue Exception => e
264
249
  log(:error, "XML transcript export for #{export_dir} failed", e)
265
250
  end
266
251
  end
@@ -273,7 +258,7 @@ module CampfireExport
273
258
  messages.each {|message| plaintext << message.to_s }
274
259
  export_file(plaintext, 'transcript.txt')
275
260
  verify_export('transcript.txt', plaintext.length)
276
- rescue => e
261
+ rescue Exception => e
277
262
  log(:error, "Plaintext transcript export for #{export_dir} failed", e)
278
263
  end
279
264
  end
@@ -293,7 +278,7 @@ module CampfireExport
293
278
 
294
279
  export_file(transcript_html, 'transcript.html')
295
280
  verify_export('transcript.html', transcript_html.length)
296
- rescue => e
281
+ rescue Exception => e
297
282
  log(:error, "HTML transcript export for #{export_dir} failed", e)
298
283
  end
299
284
  end
@@ -303,7 +288,7 @@ module CampfireExport
303
288
  if message.is_upload?
304
289
  begin
305
290
  message.upload.export
306
- rescue => e
291
+ rescue Exception => e
307
292
  path = "#{message.upload.export_dir}/#{message.upload.filename}"
308
293
  log(:error, "Upload export for #{path} failed", e)
309
294
  end
@@ -339,7 +324,7 @@ module CampfireExport
339
324
  @@usernames ||= {}
340
325
  @@usernames[user_id] ||= begin
341
326
  doc = Nokogiri::XML get("/users/#{user_id}.xml").body
342
- rescue
327
+ rescue Exception => e
343
328
  "[unknown user]"
344
329
  else
345
330
  # Take the first name and last initial, if there is more than one name.
@@ -0,0 +1,76 @@
1
+ require 'campfire_export'
2
+ require 'tzinfo'
3
+
4
+ module CampfireExport
5
+ describe Account do
6
+ before(:each) do
7
+ @subdomain = "test-subdomain"
8
+ @api_token = "test-apikey"
9
+ @account = Account.new(@subdomain, @api_token)
10
+
11
+ @good_timezone = '<select id="account_time_zone_id">' +
12
+ '<option selected="selected" value="America/Los_Angeles">' +
13
+ '</option></select>'
14
+ @bad_timezone = @good_timezone.gsub('America/Los_Angeles',
15
+ 'No Such Timezone')
16
+ @timezone_html = stub("timezone HTML block")
17
+ @timezone_html.stub(:body).and_return(@good_timezone)
18
+ end
19
+
20
+ context "when it is created" do
21
+ it "sets up the account config variables" do
22
+ Account.subdomain.should equal(@subdomain)
23
+ Account.api_token.should equal(@api_token)
24
+ Account.base_url.should == "https://#{@subdomain}.campfirenow.com"
25
+ end
26
+ end
27
+
28
+ context "when timezone is loaded" do
29
+ it "determines the user's timezone" do
30
+ @account.should_receive(:get).with("/account/settings"
31
+ ).and_return(@timezone_html)
32
+ @account.find_timezone
33
+ Account.timezone.to_s.should == "America - Los Angeles"
34
+ end
35
+
36
+ it "raises an error if it gets a bad time zone identifier" do
37
+ @timezone_html.stub(:body).and_return(@bad_timezone)
38
+ @account.stub(:get).with("/account/settings"
39
+ ).and_return(@timezone_html)
40
+ expect {
41
+ @account.find_timezone
42
+ }.to raise_error(TZInfo::InvalidTimezoneIdentifier)
43
+ end
44
+
45
+ it "raises an error if it can't get the account settings at all" do
46
+ @account.stub(:get).with("/account/settings"
47
+ ).and_raise(CampfireExport::Exception.new("/account/settings",
48
+ "Not Found", 404))
49
+ expect {
50
+ @account.find_timezone
51
+ }.to raise_error(CampfireExport::Exception)
52
+ end
53
+ end
54
+
55
+ context "when rooms are requested" do
56
+ it "returns an array of rooms" do
57
+ room_xml = "<rooms><room>1</room><room>2</room><room>3</room></rooms>"
58
+ room_doc = mock("room doc")
59
+ room_doc.should_receive(:body).and_return(room_xml)
60
+ @account.should_receive(:get).with('/rooms.xml').and_return(room_doc)
61
+ room = mock("room")
62
+ Room.should_receive(:new).exactly(3).times.and_return(room)
63
+ @account.rooms.should have(3).items
64
+ end
65
+
66
+ it "raises an error if it can't get the room list" do
67
+ @account.stub(:get).with('/rooms.xml'
68
+ ).and_raise(CampfireExport::Exception.new('/rooms.xml',
69
+ "Not Found", 404))
70
+ expect {
71
+ @account.rooms
72
+ }.to raise_error(CampfireExport::Exception)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ require 'campfire_export'
2
+ require 'campfire_export/timezone'
3
+
4
+ require 'nokogiri'
5
+
6
+ module CampfireExport
7
+ describe Room do
8
+ include TimeZone
9
+
10
+ before :each do
11
+ @room_xml = Nokogiri::XML "<room><name>Test Room</name><id>666</id>" +
12
+ "<created-at>2009-11-17T19:41:38Z</created-at></room>"
13
+ Account.timezone = find_tzinfo("America/Los_Angeles")
14
+ end
15
+
16
+ context "when it is created" do
17
+ it "sets up basic properties" do
18
+ room = Room.new(@room_xml)
19
+ room.name.should == "Test Room"
20
+ room.id.should == "666"
21
+ room.created_at.should == DateTime.parse("2009-11-17T11:41:38Z")
22
+ end
23
+ end
24
+
25
+ context "when it finds the last update" do
26
+ it "loads the last update from the most recent message"
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: campfire_export
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 1
9
- - 0
10
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
11
10
  platform: ruby
12
11
  authors:
13
12
  - Marc Hedlund
@@ -15,17 +14,16 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-07-09 00:00:00 Z
17
+ date: 2011-08-04 00:00:00 -04:00
18
+ default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bundler
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
24
  requirements:
26
25
  - - ~>
27
26
  - !ruby/object:Gem::Version
28
- hash: 9
29
27
  segments:
30
28
  - 1
31
29
  - 0
@@ -34,53 +32,75 @@ dependencies:
34
32
  type: :development
35
33
  version_requirements: *id001
36
34
  - !ruby/object:Gem::Dependency
37
- name: tzinfo
35
+ name: fuubar
38
36
  prerelease: false
39
37
  requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
38
  requirements:
42
39
  - - ~>
43
40
  - !ruby/object:Gem::Version
44
- hash: 41
41
+ segments:
42
+ - 0
43
+ - 0
44
+ - 5
45
+ version: 0.0.5
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 2
57
+ - 6
58
+ - 0
59
+ version: 2.6.0
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: tzinfo
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
45
69
  segments:
46
70
  - 0
47
71
  - 3
48
72
  - 29
49
73
  version: 0.3.29
50
74
  type: :development
51
- version_requirements: *id002
75
+ version_requirements: *id004
52
76
  - !ruby/object:Gem::Dependency
53
77
  name: httparty
54
78
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
57
80
  requirements:
58
81
  - - ~>
59
82
  - !ruby/object:Gem::Version
60
- hash: 19
61
83
  segments:
62
84
  - 0
63
85
  - 7
64
86
  - 8
65
87
  version: 0.7.8
66
88
  type: :development
67
- version_requirements: *id003
89
+ version_requirements: *id005
68
90
  - !ruby/object:Gem::Dependency
69
91
  name: nokogiri
70
92
  prerelease: false
71
- requirement: &id004 !ruby/object:Gem::Requirement
72
- none: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
73
94
  requirements:
74
95
  - - ~>
75
96
  - !ruby/object:Gem::Version
76
- hash: 13
77
97
  segments:
78
98
  - 1
79
99
  - 4
80
100
  - 5
81
101
  version: 1.4.5
82
102
  type: :development
83
- version_requirements: *id004
103
+ version_requirements: *id006
84
104
  description: Export transcripts and uploaded files from your 37signals' Campfire account.
85
105
  email:
86
106
  - marc@precipice.org
@@ -101,6 +121,9 @@ files:
101
121
  - lib/campfire_export.rb
102
122
  - lib/campfire_export/timezone.rb
103
123
  - lib/campfire_export/version.rb
124
+ - spec/campfire_export/account_spec.rb
125
+ - spec/campfire_export/room_spec.rb
126
+ has_rdoc: true
104
127
  homepage: https://github.com/precipice/campfire_export
105
128
  licenses:
106
129
  - Apache 2.0
@@ -110,31 +133,28 @@ rdoc_options: []
110
133
  require_paths:
111
134
  - lib
112
135
  required_ruby_version: !ruby/object:Gem::Requirement
113
- none: false
114
136
  requirements:
115
137
  - - ">="
116
138
  - !ruby/object:Gem::Version
117
- hash: 57
118
139
  segments:
119
140
  - 1
120
141
  - 8
121
142
  - 7
122
143
  version: 1.8.7
123
144
  required_rubygems_version: !ruby/object:Gem::Requirement
124
- none: false
125
145
  requirements:
126
146
  - - ">="
127
147
  - !ruby/object:Gem::Version
128
- hash: 3
129
148
  segments:
130
149
  - 0
131
150
  version: "0"
132
151
  requirements: []
133
152
 
134
153
  rubyforge_project: campfire_export
135
- rubygems_version: 1.8.5
154
+ rubygems_version: 1.3.6
136
155
  signing_key:
137
156
  specification_version: 3
138
157
  summary: Export transcripts and uploaded files from your 37signals' Campfire account.
139
- test_files: []
140
-
158
+ test_files:
159
+ - spec/campfire_export/account_spec.rb
160
+ - spec/campfire_export/room_spec.rb