stackbuilders-campfire_export 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 +7 -0
- data/.gitignore +44 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +160 -0
- data/README.md +114 -0
- data/Rakefile +12 -0
- data/bin/campfire_export +66 -0
- data/campfire_export.gemspec +36 -0
- data/lib/campfire_export/account.rb +32 -0
- data/lib/campfire_export/exception.rb +16 -0
- data/lib/campfire_export/message.rb +95 -0
- data/lib/campfire_export/room.rb +44 -0
- data/lib/campfire_export/timezone.rb +168 -0
- data/lib/campfire_export/transcript.rb +100 -0
- data/lib/campfire_export/upload.rb +78 -0
- data/lib/campfire_export/version.rb +3 -0
- data/lib/campfire_export.rb +133 -0
- data/spec/campfire_export/account_spec.rb +85 -0
- data/spec/campfire_export/message_spec.rb +60 -0
- data/spec/campfire_export/room_spec.rb +27 -0
- data/spec/spec_helper.rb +4 -0
- metadata +174 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
module CampfireExport
|
2
|
+
class Upload
|
3
|
+
include CampfireExport::IO
|
4
|
+
attr_accessor :message, :room, :date, :id, :filename, :content_type, :byte_size, :full_url
|
5
|
+
|
6
|
+
def initialize(message)
|
7
|
+
@message = message
|
8
|
+
@room = message.room
|
9
|
+
@date = message.date
|
10
|
+
@deleted = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def deleted?
|
14
|
+
@deleted
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_image?
|
18
|
+
content_type.start_with?("image/")
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload_dir
|
22
|
+
"uploads/#{id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Image thumbnails are used to inline image uploads in HTML transcripts.
|
26
|
+
def thumb_dir
|
27
|
+
"thumbs/#{id}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def export
|
31
|
+
begin
|
32
|
+
log(:info, " #{message.body} ... ")
|
33
|
+
|
34
|
+
# Get the upload object corresponding to this message.
|
35
|
+
upload_path = "/room/#{room.id}/messages/#{message.id}/upload.xml"
|
36
|
+
upload = Nokogiri::XML get(upload_path).body
|
37
|
+
|
38
|
+
# Get the upload itself and export it.
|
39
|
+
@id = upload.xpath('/upload/id').text
|
40
|
+
@byte_size = upload.xpath('/upload/byte-size').text.to_i
|
41
|
+
@content_type = upload.xpath('/upload/content-type').text
|
42
|
+
@filename = upload.xpath('/upload/name').text
|
43
|
+
@full_url = upload.xpath('/upload/full-url').text
|
44
|
+
|
45
|
+
export_content(upload_dir)
|
46
|
+
export_content(thumb_dir, path_component="thumb/#{id}", verify=false) if is_image?
|
47
|
+
|
48
|
+
log(:info, "ok\n")
|
49
|
+
rescue CampfireExport::Exception => e
|
50
|
+
if e.code == 404
|
51
|
+
# If the upload 404s, that should mean it was subsequently deleted.
|
52
|
+
@deleted = true
|
53
|
+
log(:info, "deleted\n")
|
54
|
+
else
|
55
|
+
raise e
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def export_content(content_dir, path_component=nil, verify=true)
|
61
|
+
# If the export directory name is different than the URL path component,
|
62
|
+
# the caller can define the path_component separately.
|
63
|
+
path_component ||= content_dir
|
64
|
+
|
65
|
+
# Write uploads to a subdirectory, using the upload ID as a directory
|
66
|
+
# name to avoid overwriting multiple uploads of the same file within
|
67
|
+
# the same day (for instance, if 'Picture 1.png' is uploaded twice
|
68
|
+
# in a day, this will preserve both copies). This path pattern also
|
69
|
+
# matches the tail of the upload path in the HTML transcript, making
|
70
|
+
# it easier to make downloads functional from the HTML transcripts.
|
71
|
+
content_path = "/room/#{room.id}/#{path_component}/#{CGI.escape(filename)}"
|
72
|
+
content = get(content_path).body
|
73
|
+
FileUtils.mkdir_p(File.join(export_dir, content_dir))
|
74
|
+
export_file(content, "#{content_dir}/#{filename}", 'wb')
|
75
|
+
verify_export("#{content_dir}/#{filename}", byte_size) if verify
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Portions copyright 2011 Marc Hedlund <marc@precipice.org>.
|
4
|
+
# Adapted from https://gist.github.com/821553 and ancestors.
|
5
|
+
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
# campfire_export.rb -- export Campfire transcripts and uploaded files.
|
19
|
+
#
|
20
|
+
# Since Campfire (www.campfirenow.com) doesn't provide an export feature,
|
21
|
+
# this script implements one via the Campfire API.
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
|
25
|
+
require 'cgi'
|
26
|
+
require 'fileutils'
|
27
|
+
require 'httparty'
|
28
|
+
require 'nokogiri'
|
29
|
+
require 'retryable'
|
30
|
+
require 'time'
|
31
|
+
require 'yaml'
|
32
|
+
|
33
|
+
module CampfireExport
|
34
|
+
module IO
|
35
|
+
MAX_RETRIES = 5
|
36
|
+
|
37
|
+
def api_url(path)
|
38
|
+
"#{CampfireExport::Account.base_url}#{path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(path, params = {})
|
42
|
+
url = api_url(path)
|
43
|
+
|
44
|
+
response = Retryable.retryable(:tries => MAX_RETRIES) do |retries, exception|
|
45
|
+
if retries > 0
|
46
|
+
msg = "Attempt ##{retries} to fetch #{path} failed, " +
|
47
|
+
"#{MAX_RETRIES - retries} attempts remaining"
|
48
|
+
log :error, msg, exception
|
49
|
+
end
|
50
|
+
|
51
|
+
HTTParty.get(url, :query => params, :basic_auth =>
|
52
|
+
{:username => CampfireExport::Account.api_token, :password => 'X'})
|
53
|
+
end
|
54
|
+
|
55
|
+
if response.code >= 400
|
56
|
+
raise CampfireExport::Exception.new(url, response.message, response.code)
|
57
|
+
end
|
58
|
+
response
|
59
|
+
end
|
60
|
+
|
61
|
+
def zero_pad(number)
|
62
|
+
"%02d" % number
|
63
|
+
end
|
64
|
+
|
65
|
+
# Requires that room and date be defined in the calling object.
|
66
|
+
def export_dir
|
67
|
+
"campfire/#{Account.subdomain}/#{room.name}/" +
|
68
|
+
"#{date.year}/#{zero_pad(date.mon)}/#{zero_pad(date.day)}"
|
69
|
+
end
|
70
|
+
|
71
|
+
# Requires that room_name and date be defined in the calling object.
|
72
|
+
def export_file(content, filename, mode='w')
|
73
|
+
# Check to make sure we're writing into the target directory tree.
|
74
|
+
true_path = File.expand_path(File.join(export_dir, filename))
|
75
|
+
|
76
|
+
unless true_path.start_with?(File.expand_path(export_dir))
|
77
|
+
raise CampfireExport::Exception.new("#{export_dir}/#{filename}",
|
78
|
+
"can't export file to a directory higher than target directory; " +
|
79
|
+
"expected: #{File.expand_path(export_dir)}, actual: #{true_path}.")
|
80
|
+
end
|
81
|
+
|
82
|
+
if File.exists?("#{export_dir}/#{filename}")
|
83
|
+
log(:error, "#{export_dir}/#{filename} failed: file already exists")
|
84
|
+
else
|
85
|
+
open("#{export_dir}/#{filename}", mode) do |file|
|
86
|
+
file.write content
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def verify_export(filename, expected_size)
|
92
|
+
full_path = "#{export_dir}/#{filename}"
|
93
|
+
unless File.exists?(full_path)
|
94
|
+
raise CampfireExport::Exception.new(full_path,
|
95
|
+
"file should have been exported but did not make it to disk")
|
96
|
+
end
|
97
|
+
unless File.size(full_path) == expected_size
|
98
|
+
raise CampfireExport::Exception.new(full_path,
|
99
|
+
"exported file exists but is not the right size " +
|
100
|
+
"(expected: #{expected_size}, actual: #{File.size(full_path)})")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def log(level, message, exception=nil)
|
105
|
+
case level
|
106
|
+
when :error
|
107
|
+
short_error = ["*** Error: #{message}", exception].compact.join(": ")
|
108
|
+
$stderr.puts short_error
|
109
|
+
open("campfire/export_errors.txt", 'a') do |log|
|
110
|
+
log.write short_error
|
111
|
+
unless exception.nil?
|
112
|
+
log.write %Q{\n\t#{exception.backtrace.join("\n\t")}}
|
113
|
+
end
|
114
|
+
log.write "\n"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
print message
|
118
|
+
$stdout.flush
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
require 'campfire_export/timezone'
|
126
|
+
|
127
|
+
require 'campfire_export/account'
|
128
|
+
require 'campfire_export/exception'
|
129
|
+
require 'campfire_export/message'
|
130
|
+
require 'campfire_export/room'
|
131
|
+
require 'campfire_export/transcript'
|
132
|
+
require 'campfire_export/upload'
|
133
|
+
require 'campfire_export/version'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CampfireExport
|
4
|
+
describe Account do
|
5
|
+
before(:each) do
|
6
|
+
@subdomain = "test-subdomain"
|
7
|
+
@api_token = "test-apikey"
|
8
|
+
@account = Account.new(@subdomain, @api_token)
|
9
|
+
|
10
|
+
@good_timezone = '<?xml version="1.0" encoding="UTF-8"?>' +
|
11
|
+
'<account>' +
|
12
|
+
' <time-zone>America/Los_Angeles</time-zone>' +
|
13
|
+
' <owner-id type="integer">99999</owner-id>' +
|
14
|
+
' <created-at type="datetime">2010-01-31T18:30:18Z</created-at>' +
|
15
|
+
' <storage type="integer">9999999</storage>' +
|
16
|
+
' <plan>basic</plan>' +
|
17
|
+
' <updated-at type="datetime">2010-01-31T18:31:55Z</updated-at>' +
|
18
|
+
' <subdomain>example</subdomain>' +
|
19
|
+
' <name>Example</name>' +
|
20
|
+
' <id type="integer">999999</id>' +
|
21
|
+
'</account>'
|
22
|
+
|
23
|
+
@bad_timezone = @good_timezone.gsub('America/Los_Angeles',
|
24
|
+
'No Such Timezone')
|
25
|
+
@account_xml = stub("Account XML")
|
26
|
+
@account_xml.stub(:body).and_return(@good_timezone)
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when it is created" do
|
30
|
+
it "sets up the account config variables" do
|
31
|
+
Account.subdomain.should equal(@subdomain)
|
32
|
+
Account.api_token.should equal(@api_token)
|
33
|
+
Account.base_url.should == "https://#{@subdomain}.campfirenow.com"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when timezone is loaded" do
|
38
|
+
it "determines the user's timezone" do
|
39
|
+
@account.should_receive(:get).with("/account.xml"
|
40
|
+
).and_return(@account_xml)
|
41
|
+
@account.find_timezone
|
42
|
+
Account.timezone.to_s.should == "America - Los Angeles"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "raises an error if it gets a bad time zone identifier" do
|
46
|
+
@account_xml.stub(:body).and_return(@bad_timezone)
|
47
|
+
@account.stub(:get).with("/account.xml"
|
48
|
+
).and_return(@account_xml)
|
49
|
+
expect {
|
50
|
+
@account.find_timezone
|
51
|
+
}.to raise_error(TZInfo::InvalidTimezoneIdentifier)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises an error if it can't get the account settings at all" do
|
55
|
+
@account.stub(:get).with("/account.xml"
|
56
|
+
).and_raise(CampfireExport::Exception.new("/account/settings",
|
57
|
+
"Not Found", 404))
|
58
|
+
expect {
|
59
|
+
@account.find_timezone
|
60
|
+
}.to raise_error(CampfireExport::Exception)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when rooms are requested" do
|
65
|
+
it "returns an array of rooms" do
|
66
|
+
room_xml = "<rooms><room>1</room><room>2</room><room>3</room></rooms>"
|
67
|
+
room_doc = mock("room doc")
|
68
|
+
room_doc.should_receive(:body).and_return(room_xml)
|
69
|
+
@account.should_receive(:get).with('/rooms.xml').and_return(room_doc)
|
70
|
+
room = mock("room")
|
71
|
+
Room.should_receive(:new).exactly(3).times.and_return(room)
|
72
|
+
@account.rooms.should have(3).items
|
73
|
+
end
|
74
|
+
|
75
|
+
it "raises an error if it can't get the room list" do
|
76
|
+
@account.stub(:get).with('/rooms.xml'
|
77
|
+
).and_raise(CampfireExport::Exception.new('/rooms.xml',
|
78
|
+
"Not Found", 404))
|
79
|
+
expect {
|
80
|
+
@account.rooms
|
81
|
+
}.to raise_error(CampfireExport::Exception)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CampfireExport
|
4
|
+
describe Message do
|
5
|
+
include TimeZone
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@messages = Nokogiri::XML <<XML
|
9
|
+
<messages>
|
10
|
+
<message>
|
11
|
+
<created-at type="datetime">2012-05-11T17:45:00Z</created-at>
|
12
|
+
<id type="integer">111</id>
|
13
|
+
<room-id type="integer">222</room-id>
|
14
|
+
<user-id type="integer" nil="true"/>
|
15
|
+
<body nil="true"/>
|
16
|
+
<type>TimestampMessage</type>
|
17
|
+
</message>
|
18
|
+
<message>
|
19
|
+
<created-at type="datetime">2012-05-11T17:47:20Z</created-at>
|
20
|
+
<id type="integer">333</id>
|
21
|
+
<room-id type="integer">222</room-id>
|
22
|
+
<user-id type="integer">555</user-id>
|
23
|
+
<body>This is a tweet</body>
|
24
|
+
<type>TweetMessage</type>
|
25
|
+
<tweet>
|
26
|
+
<id>20100487385931234</id>
|
27
|
+
<message>This is a tweet</message>
|
28
|
+
<author_username>twitter_user</author_username>
|
29
|
+
<author_avatar_url>avatar.jpg</author_avatar_url>
|
30
|
+
</tweet>
|
31
|
+
</message>
|
32
|
+
<message>
|
33
|
+
<created-at type="datetime">2012-05-11T17:47:23Z</created-at>
|
34
|
+
<id type="integer">666</id>
|
35
|
+
<room-id type="integer">222</room-id>
|
36
|
+
<user-id type="integer">555</user-id>
|
37
|
+
<body>Regular message</body>
|
38
|
+
<type>TextMessage</type>
|
39
|
+
</message>
|
40
|
+
</messages>
|
41
|
+
XML
|
42
|
+
Account.timezone = find_tzinfo("America/Los_Angeles")
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when it is created" do
|
46
|
+
it "sets up basic properties" do
|
47
|
+
message = Message.new(@messages.xpath('/messages/message[3]')[0], nil, nil)
|
48
|
+
message.body.should == "Regular message"
|
49
|
+
message.id.should == "666"
|
50
|
+
message.timestamp.should == "10:47 AM"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "handles tweets correctly" do
|
54
|
+
message = Message.new(@messages.xpath('/messages/message[2]'), nil, nil)
|
55
|
+
message.body.should == "This is a tweet"
|
56
|
+
message.id.should == "333"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CampfireExport
|
4
|
+
describe Room do
|
5
|
+
include TimeZone
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
doc = Nokogiri::XML "<room><name>Test Room</name><id>666</id>" +
|
9
|
+
"<created-at>2009-11-17T19:41:38Z</created-at></room>"
|
10
|
+
@room_xml = doc.xpath('/room')
|
11
|
+
Account.timezone = find_tzinfo("America/Los_Angeles")
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when it is created" do
|
15
|
+
it "sets up basic properties" do
|
16
|
+
room = Room.new(@room_xml)
|
17
|
+
room.name.should == "Test Room"
|
18
|
+
room.id.should == "666"
|
19
|
+
room.created_at.should == DateTime.parse("2009-11-17T11:41:38Z")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when it finds the last update" do
|
24
|
+
it "loads the last update from the most recent message"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stackbuilders-campfire_export
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marc Hedlund
|
8
|
+
- Justin Leitgeb
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-03-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.6'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.6'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: tzinfo
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.2'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.2'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: httparty
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.13'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0.13'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: nokogiri
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '1.6'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.6'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: retryable
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '2.0'
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '2.0'
|
112
|
+
description: |-
|
113
|
+
Exports content from all rooms in a
|
114
|
+
37signals Campfire account. Creates a directory containing transcripts
|
115
|
+
and content uploaded to each one of your rooms. Can be configured to
|
116
|
+
recognize start and end date of content export.
|
117
|
+
email:
|
118
|
+
- marc@precipice.org
|
119
|
+
- justin@stackbuilders.com
|
120
|
+
executables:
|
121
|
+
- campfire_export
|
122
|
+
extensions: []
|
123
|
+
extra_rdoc_files: []
|
124
|
+
files:
|
125
|
+
- ".gitignore"
|
126
|
+
- ".travis.yml"
|
127
|
+
- Gemfile
|
128
|
+
- LICENSE.txt
|
129
|
+
- README.md
|
130
|
+
- Rakefile
|
131
|
+
- bin/campfire_export
|
132
|
+
- campfire_export.gemspec
|
133
|
+
- lib/campfire_export.rb
|
134
|
+
- lib/campfire_export/account.rb
|
135
|
+
- lib/campfire_export/exception.rb
|
136
|
+
- lib/campfire_export/message.rb
|
137
|
+
- lib/campfire_export/room.rb
|
138
|
+
- lib/campfire_export/timezone.rb
|
139
|
+
- lib/campfire_export/transcript.rb
|
140
|
+
- lib/campfire_export/upload.rb
|
141
|
+
- lib/campfire_export/version.rb
|
142
|
+
- spec/campfire_export/account_spec.rb
|
143
|
+
- spec/campfire_export/message_spec.rb
|
144
|
+
- spec/campfire_export/room_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: https://github.com/stackbuilders/campfire_export
|
147
|
+
licenses:
|
148
|
+
- Apache 2.0
|
149
|
+
metadata: {}
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 1.9.3
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project: campfire_export
|
166
|
+
rubygems_version: 2.4.6
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Export transcripts and uploaded files from your 37signals' Campfire account.
|
170
|
+
test_files:
|
171
|
+
- spec/campfire_export/account_spec.rb
|
172
|
+
- spec/campfire_export/message_spec.rb
|
173
|
+
- spec/campfire_export/room_spec.rb
|
174
|
+
- spec/spec_helper.rb
|