duraflame 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011 Brian Lopez - http://github.com/brianmario
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Duraflame
2
+
3
+ A command line tool that converts Campfire transcripts to an IRC log format. Allows you to run [pisg](http://pisg.sourceforge.net/) (Perl IRC Statistics Generator) on your Campfire conversations.
4
+
5
+ ## Installation
6
+
7
+ `gem install duraflame`
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ duraflame [arguments]
13
+ -c, --company=COMPANY As in http://{company}.campfirenow.com
14
+ -t, --token=TOKEN Authentication token
15
+ -r, --room=ROOM Room ID
16
+ -o, --output-dir=DIRECTORY Directory where log files will be written
17
+ -s, --start-date=DATE Start date, defaults to today
18
+ -e, --end-date=DATE End date, defaults to today
19
+ ```
20
+
21
+ All arguments are required except for start and end dates, which default to today's date.
22
+
23
+ For example:
24
+
25
+ `duraflame -c your_company -t your_auth_token96be2812d5367c97f2c87e545 -r 1234 -o campfire_logs --start-date 2012-05-25`
26
+
27
+ This command will download transcripts from May 25, 2012 through today.
28
+
29
+ Then run pisg:
30
+
31
+ `pisg -ch 'Room 1' -d campfire_logs -f irssi`
32
+
33
+ ## Todo
34
+ * Improve performance (fetch transcripts concurrently, operate on streams)
35
+ * Fetch transcripts for multiple rooms
data/Rakefile ADDED
@@ -0,0 +1,124 @@
1
+ require 'rake'
2
+ require 'date'
3
+
4
+ #############################################################################
5
+ #
6
+ # Helper functions
7
+ #
8
+ #############################################################################
9
+
10
+ def name
11
+ @name ||= Dir['*.gemspec'].first.split('.').first
12
+ end
13
+
14
+ def version
15
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
16
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
17
+ end
18
+
19
+ def date
20
+ Date.today.to_s
21
+ end
22
+
23
+ def rubyforge_project
24
+ name
25
+ end
26
+
27
+ def gemspec_file
28
+ "#{name}.gemspec"
29
+ end
30
+
31
+ def gem_file
32
+ "#{name}-#{version}.gem"
33
+ end
34
+
35
+ def replace_header(head, header_name)
36
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
37
+ end
38
+
39
+ #############################################################################
40
+ #
41
+ # Standard tasks
42
+ #
43
+ #############################################################################
44
+
45
+ desc "Open an irb session preloaded with this library"
46
+ task :console do
47
+ sh "irb -rubygems -r ./lib/#{name}.rb"
48
+ end
49
+
50
+ #############################################################################
51
+ #
52
+ # Custom tasks (add your own tasks here)
53
+ #
54
+ #############################################################################
55
+
56
+
57
+
58
+ #############################################################################
59
+ #
60
+ # Packaging tasks
61
+ #
62
+ #############################################################################
63
+
64
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
65
+ task :release => :build do
66
+ unless `git branch` =~ /^\* master$/
67
+ puts "You must be on the master branch to release!"
68
+ exit!
69
+ end
70
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
71
+ sh "git tag v#{version}"
72
+ sh "git push origin master"
73
+ sh "git push origin v#{version}"
74
+ sh "gem push pkg/#{name}-#{version}.gem"
75
+ end
76
+
77
+ desc "Build #{gem_file} into the pkg directory"
78
+ task :build => :gemspec do
79
+ sh "mkdir -p pkg"
80
+ sh "gem build #{gemspec_file}"
81
+ sh "mv #{gem_file} pkg"
82
+ end
83
+
84
+ desc "Generate #{gemspec_file}"
85
+ task :gemspec => :validate do
86
+ # read spec file and split out manifest section
87
+ spec = File.read(gemspec_file)
88
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
89
+
90
+ # replace name version and date
91
+ replace_header(head, :name)
92
+ replace_header(head, :version)
93
+ replace_header(head, :date)
94
+ #comment this out if your rubyforge_project has a different name
95
+ replace_header(head, :rubyforge_project)
96
+
97
+ # determine file list from git ls-files
98
+ files = `git ls-files`.
99
+ split("\n").
100
+ sort.
101
+ reject { |file| file =~ /^\./ }.
102
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
103
+ map { |file| " #{file}" }.
104
+ join("\n")
105
+
106
+ # piece file back together and write
107
+ manifest = " s.files = %w[\n#{files}\n ]\n"
108
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
109
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
110
+ puts "Updated #{gemspec_file}"
111
+ end
112
+
113
+ desc "Validate #{gemspec_file}"
114
+ task :validate do
115
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
116
+ unless libfiles.empty?
117
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
118
+ exit!
119
+ end
120
+ unless Dir['VERSION*'].empty?
121
+ puts "A `VERSION` file at root level violates Gem best practices."
122
+ exit!
123
+ end
124
+ end
data/bin/duraflame ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'optparse/date'
5
+ require 'duraflame'
6
+
7
+ options = {}
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = "Usage: duraflame [options]"
11
+
12
+ opts.on("-c", "--company=COMPANY", "As in http://{company}.campfirenow.com") do |company|
13
+ options[:company] = company
14
+ end
15
+
16
+ opts.on("-t", "--token=TOKEN", "Authentication token") do |token|
17
+ options[:token] = token
18
+ end
19
+
20
+ opts.on("-r","--room=ROOM", "Room ID") do |room|
21
+ options[:room] = room
22
+ end
23
+
24
+ opts.on("-o", "--output-dir=DIRECTORY", "Directory where log files will be written") do |dir|
25
+ options[:output_dir] = dir
26
+ end
27
+
28
+ opts.on("-s", "--start-date=DATE", Date, "Start date, defaults to today") do |start_date|
29
+ options[:start_date] = start_date
30
+ end
31
+
32
+ opts.on("-e", "--end-date=DATE", Date, "End date, defaults to today") do |end_date|
33
+ options[:end_date] = end_date
34
+ end
35
+ end.parse!
36
+
37
+ begin
38
+ Duraflame.execute(options)
39
+ rescue Interrupt
40
+ abort
41
+ end
data/duraflame.gemspec ADDED
@@ -0,0 +1,45 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'duraflame'
3
+ s.version = '0.1.0'
4
+ s.date = '2012-05-29'
5
+
6
+ s.summary = "A command line tool that converts Campfire transcripts to an IRC log format"
7
+ s.description = "Generate pisg (Perl IRC Statistics Generator) stats on Campfire conversations"
8
+
9
+ s.authors = ["Alex Kahn"]
10
+ s.email = 'alexanderkahn@gmail.com'
11
+ s.homepage = 'http://github.com/akahn/duraflame'
12
+
13
+ s.require_paths = %w[lib]
14
+
15
+ s.executables = ["duraflame"]
16
+
17
+ s.extra_rdoc_files = %w[README.md MIT-LICENSE]
18
+
19
+ s.add_dependency('httpclient', '~>2.2')
20
+ s.add_dependency('yajl-ruby', '~>1.1')
21
+
22
+ # = MANIFEST =
23
+ s.files = %w[
24
+ MIT-LICENSE
25
+ README.md
26
+ Rakefile
27
+ bin/duraflame
28
+ duraflame.gemspec
29
+ lib/duraflame.rb
30
+ lib/duraflame/client.rb
31
+ lib/duraflame/message.rb
32
+ lib/duraflame/processor.rb
33
+ lib/duraflame/transcript.rb
34
+ lib/duraflame/translator.rb
35
+ lib/duraflame/user_lookup.rb
36
+ spec/fixtures/transcript.json
37
+ spec/fixtures/user1.json
38
+ spec/fixtures/user2.json
39
+ spec/helper.rb
40
+ spec/integration_spec.rb
41
+ ]
42
+ # = MANIFEST =
43
+
44
+ s.test_files = s.files.select { |path| path =~ /^spec\/.*_spec\.rb/ }
45
+ end
@@ -0,0 +1,20 @@
1
+ require 'httpclient'
2
+ require 'yajl'
3
+
4
+ module Duraflame
5
+ # Wraps HTTPClient with knowledge of hostname and authentication
6
+ class Client
7
+ def initialize(company, token)
8
+ @http_client = HTTPClient.new
9
+ @http_client.set_auth(nil, token, nil)
10
+ @uri = URI.parse("https://#{company}.campfirenow.com")
11
+ end
12
+
13
+ def get(path)
14
+ uri = @uri.dup
15
+ uri.path = path
16
+ body = @http_client.get_content(uri)
17
+ Yajl::Parser.parse(body)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ module Duraflame
2
+ # Converts a timestamp, user_id and possible body into irssi log format
3
+ class Message
4
+ def initialize(timestamp, user_id, body)
5
+ @timestamp = timestamp
6
+ @user_id = user_id
7
+ @body = body
8
+ end
9
+
10
+ private
11
+
12
+ def name
13
+ Duraflame.user_names[@user_id]
14
+ end
15
+
16
+ def time
17
+ Time.parse(@timestamp).strftime('%R')
18
+ end
19
+
20
+ attr_reader :body
21
+ end
22
+
23
+ class TextMessage < Message
24
+ def to_s
25
+ [time, "< #{name}>", body].join(' ')
26
+ end
27
+ end
28
+
29
+ class EnterMessage < Message
30
+ def to_s
31
+ [time, '-!-' , name, '[hostname] has joined #campfire'].join(' ')
32
+ end
33
+ end
34
+
35
+ class KickMessage < Message
36
+ def to_s
37
+ [time, '-!-' , name, '[hostname] has left #campfire'].join(' ')
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ require 'duraflame/message'
2
+ require 'duraflame/transcript'
3
+
4
+ module Duraflame
5
+ class Processor
6
+ def initialize(room, date_range, output_directory, http_client)
7
+ @room = room
8
+ @date_range = date_range
9
+ @output_directory = output_directory
10
+ @http_client = http_client
11
+ end
12
+
13
+ def execute
14
+ @date_range.each do |date|
15
+ File.open(@output_directory + "/#{date}-#{@room}.log", 'w') do |file|
16
+ puts "Writing to #{file.path}"
17
+
18
+ Transcript.new(@room, date, @http_client).each_message do |message|
19
+ file.puts message.to_s
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module Duraflame
2
+ class Transcript
3
+ def initialize(room, date, http_client)
4
+ @room = room
5
+ @date = date
6
+ @http_client = http_client
7
+ end
8
+
9
+ def each_message
10
+ @http_client.get(url)['messages'].each do |message|
11
+ if Duraflame.const_defined?(message['type']) # e.g. TextMessage
12
+ message_class = Duraflame.const_get(message['type'])
13
+ args = message.values_at('created_at', 'user_id', 'body')
14
+ yield message_class.new(*args)
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def url
22
+ "/room/%s/transcript/%s/%s/%s.json" %
23
+ [@room, @date.year, @date.month, @date.day]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Duraflame
2
+ module Translator
3
+ extend self
4
+
5
+ def text_message(message)
6
+ date, user, body = message.values_at('created_at', 'user_id', 'body')
7
+ time = date.split(' ')[1].split(':')[0..1].join(':')
8
+ "#{time} <#{user}> #{body}"
9
+ end
10
+
11
+ def enter_message(message)
12
+ time = message['created_at'].split(' ')[1].split(':')[0..1].join(':')
13
+ "#{time} <#{message['user_id']}> has joined"
14
+ end
15
+
16
+ def kick_message(message)
17
+ time = message['created_at'].split(' ')[1].split(':')[0..1].join(':')
18
+ "#{time} <#{message['user_id']}> has left"
19
+ end
20
+
21
+ def upload_message(*)
22
+ end
23
+
24
+ def sound_message(*)
25
+ end
26
+
27
+ def tweet_message(*)
28
+ end
29
+
30
+ def paste_message(*)
31
+ end
32
+
33
+ def timestamp_message(*)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,14 @@
1
+ module Duraflame
2
+ class UserLookup
3
+ def initialize(http_client)
4
+ @users = {}
5
+ @http_client = http_client
6
+ end
7
+
8
+ def [](id)
9
+ @users[id] ||= begin
10
+ @http_client.get("/users/#{id}.json")['user']['name']
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/duraflame.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'duraflame/processor'
2
+ require 'duraflame/user_lookup'
3
+ require 'duraflame/client'
4
+
5
+ module Duraflame
6
+ VERSION = '0.1.0'
7
+
8
+ extend self
9
+
10
+ def execute(options)
11
+ %w[company token output_dir room].each do |option|
12
+ if !options.has_key?(option.to_sym)
13
+ abort "Error: Missing option --#{option}. See duraflame --help."
14
+ end
15
+ instance_variable_set('@' + option, options[option.to_sym])
16
+ end
17
+
18
+ start_date = options.fetch(:start_date, Date.today)
19
+ end_date = options.fetch(:end_date, Date.today)
20
+ Processor.new(@room, start_date..end_date, @output_dir, http_client).execute
21
+ end
22
+
23
+ def http_client
24
+ @http_client ||= Client.new(@company, @token)
25
+ end
26
+
27
+ def user_names
28
+ @user_lookup ||= UserLookup.new(http_client)
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ { "messages" : [ { "body" : null,
2
+ "created_at" : "2012/05/25 04:04:19 +0000",
3
+ "id" : 577169389,
4
+ "room_id" : 1,
5
+ "starred" : false,
6
+ "type" : "EnterMessage",
7
+ "user_id" : 1
8
+ },
9
+ { "body" : "ok, deploying to production",
10
+ "created_at" : "2012/05/25 05:01:23 +0000",
11
+ "id" : 577557437,
12
+ "room_id" : 1,
13
+ "starred" : false,
14
+ "type" : "TextMessage",
15
+ "user_id" : 2
16
+ },
17
+ { "body" : null,
18
+ "created_at" : "2012/05/25 06:20:29 +0000",
19
+ "id" : 577214413,
20
+ "room_id" : 1,
21
+ "starred" : false,
22
+ "type" : "KickMessage",
23
+ "user_id" : 1
24
+ },
25
+ { "body" : null,
26
+ "created_at" : "2012/05/25 07:10:00 +0000",
27
+ "id" : 577173940,
28
+ "room_id" : 1,
29
+ "starred" : false,
30
+ "type" : "TimestampMessage",
31
+ "user_id" : null
32
+ }
33
+ ] }
@@ -0,0 +1 @@
1
+ {"user":{"type":"Member","created_at":"2010/06/14 14:25:24 +0000","admin":true,"id":1,"email_address":"sisko@ds9.starfleet","name":"Benjamin Sisko"}}
@@ -0,0 +1 @@
1
+ {"user":{"type":"Member","created_at":"2012/05/20 12:00:00 +0000","admin":true,"id":2,"email_address":"obrien@ds9.starfleet","name":"Miles O'Brien"}}
data/spec/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'webmock'
3
+ require 'webmock/rspec'
4
+ require_relative '../lib/duraflame'
5
+
6
+ include WebMock::API
@@ -0,0 +1,38 @@
1
+ require_relative 'helper'
2
+
3
+ describe 'Duraflame under integration' do
4
+ before(:all) do
5
+ dir = File.dirname(__FILE__)
6
+ stub_request(:any, /transcript/).to_return(:body => File.open(dir + '/fixtures/transcript.json'))
7
+ stub_request(:any, /users\/1/).to_return(:body => File.open(dir + '/fixtures/user1.json'))
8
+ stub_request(:any, /users\/2/).to_return(:body => File.open(dir + '/fixtures/user2.json'))
9
+
10
+ options = {
11
+ :company => 'paperlesspost',
12
+ :token => 'aoeu',
13
+ :room => 4321,
14
+ :output_dir => Dir.tmpdir,
15
+ :start_date => Date.parse('2012-01-01'),
16
+ :end_date => Date.parse('2012-01-01')
17
+ }
18
+ Duraflame.execute(options)
19
+
20
+ @log = File.readlines(Dir.tmpdir + "/2012-01-01-#{options[:room]}.log")
21
+ end
22
+
23
+ it 'should output three lines' do
24
+ @log.length.should == 3
25
+ end
26
+
27
+ it 'should contain Sisko joining' do
28
+ @log[0].should include('0:04 -!- Benjamin Sisko [hostname] has joined')
29
+ end
30
+
31
+ it "should contain O'Brien's message joining" do
32
+ @log[1].should include("1:01 < Miles O'Brien> ok")
33
+ end
34
+
35
+ it 'should contain Sisko leaving' do
36
+ @log[2].should include('02:20 -!- Benjamin Sisko [hostname] has left')
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duraflame
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Kahn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-29 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httpclient
16
+ requirement: &2154226300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2154226300
25
+ - !ruby/object:Gem::Dependency
26
+ name: yajl-ruby
27
+ requirement: &2154225820 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2154225820
36
+ description: Generate pisg (Perl IRC Statistics Generator) stats on Campfire conversations
37
+ email: alexanderkahn@gmail.com
38
+ executables:
39
+ - duraflame
40
+ extensions: []
41
+ extra_rdoc_files:
42
+ - README.md
43
+ - MIT-LICENSE
44
+ files:
45
+ - MIT-LICENSE
46
+ - README.md
47
+ - Rakefile
48
+ - bin/duraflame
49
+ - duraflame.gemspec
50
+ - lib/duraflame.rb
51
+ - lib/duraflame/client.rb
52
+ - lib/duraflame/message.rb
53
+ - lib/duraflame/processor.rb
54
+ - lib/duraflame/transcript.rb
55
+ - lib/duraflame/translator.rb
56
+ - lib/duraflame/user_lookup.rb
57
+ - spec/fixtures/transcript.json
58
+ - spec/fixtures/user1.json
59
+ - spec/fixtures/user2.json
60
+ - spec/helper.rb
61
+ - spec/integration_spec.rb
62
+ homepage: http://github.com/akahn/duraflame
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.17
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A command line tool that converts Campfire transcripts to an IRC log format
86
+ test_files:
87
+ - spec/integration_spec.rb
88
+ has_rdoc: