tkellem 0.9.1 → 0.9.2

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/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore CHANGED
@@ -1,8 +1,8 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/*
5
4
  coverage/*
6
5
  doc/*
7
6
  .yardoc/*
8
7
  test.log
8
+ tmp/*
data/.travis.yml CHANGED
@@ -1,8 +1,13 @@
1
1
  language: ruby
2
+ bundler_args: --without development
2
3
  rvm:
3
4
  - "1.9.3"
4
5
  - "2.0.0"
5
- - rbx-19mode
6
6
  # uncomment this line if your project needs to run something other than `rake`:
7
7
  # script: bundle exec rspec spec
8
+ matrix:
9
+ allow_failures:
10
+ # this is intermittently failing with "attempt to unlock a mutex that is not locked" errors
11
+ # while creating an EM threadpool
12
+ - rvm: "2.0.0"
8
13
 
data/Gemfile CHANGED
@@ -4,6 +4,13 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :test do
7
- gem 'rspec', '~> 2.5'
8
- gem 'simplecov'
7
+ gem 'rspec', '~> 2.13.0'
8
+ gem 'mocha', '0.14.0', require: false
9
+ gem 'simplecov', require: false
10
+ gem 'coveralls', require: false
11
+ end
12
+
13
+ group :development do
14
+ gem 'guard-rspec'
15
+ gem 'rspec-nc'
9
16
  end
data/Gemfile.lock ADDED
@@ -0,0 +1,127 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tkellem (0.9.2)
5
+ activerecord (~> 4.0.0.rc2)
6
+ eventmachine (~> 1.0.3)
7
+ rails-observers (~> 0.1.1)
8
+ sqlite3 (~> 1.3.3)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (4.0.0.rc2)
14
+ activesupport (= 4.0.0.rc2)
15
+ builder (~> 3.1.0)
16
+ erubis (~> 2.7.0)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ activemodel (4.0.0.rc2)
20
+ activesupport (= 4.0.0.rc2)
21
+ builder (~> 3.1.0)
22
+ activerecord (4.0.0.rc2)
23
+ activemodel (= 4.0.0.rc2)
24
+ activerecord-deprecated_finders (~> 1.0.2)
25
+ activesupport (= 4.0.0.rc2)
26
+ arel (~> 4.0.0)
27
+ activerecord-deprecated_finders (1.0.3)
28
+ activesupport (4.0.0.rc2)
29
+ i18n (~> 0.6, >= 0.6.4)
30
+ minitest (~> 4.2)
31
+ multi_json (~> 1.3)
32
+ thread_safe (~> 0.1)
33
+ tzinfo (~> 0.3.37)
34
+ arel (4.0.0)
35
+ atomic (1.1.9)
36
+ builder (3.1.4)
37
+ coderay (1.0.9)
38
+ colorize (0.5.8)
39
+ coveralls (0.6.7)
40
+ colorize
41
+ multi_json (~> 1.3)
42
+ rest-client
43
+ simplecov (>= 0.7)
44
+ thor
45
+ diff-lcs (1.2.4)
46
+ erubis (2.7.0)
47
+ eventmachine (1.0.3)
48
+ ffi (1.9.0)
49
+ formatador (0.2.4)
50
+ guard (1.8.1)
51
+ formatador (>= 0.2.4)
52
+ listen (>= 1.0.0)
53
+ lumberjack (>= 1.0.2)
54
+ pry (>= 0.9.10)
55
+ thor (>= 0.14.6)
56
+ guard-rspec (3.0.2)
57
+ guard (>= 1.8)
58
+ rspec (~> 2.13)
59
+ i18n (0.6.4)
60
+ listen (1.2.2)
61
+ rb-fsevent (>= 0.9.3)
62
+ rb-inotify (>= 0.9)
63
+ rb-kqueue (>= 0.2)
64
+ lumberjack (1.0.4)
65
+ metaclass (0.0.1)
66
+ method_source (0.8.1)
67
+ mime-types (1.23)
68
+ minitest (4.7.5)
69
+ mocha (0.14.0)
70
+ metaclass (~> 0.0.1)
71
+ multi_json (1.7.7)
72
+ pry (0.9.12.2)
73
+ coderay (~> 1.0.5)
74
+ method_source (~> 0.8)
75
+ slop (~> 3.4)
76
+ rack (1.5.2)
77
+ rack-test (0.6.2)
78
+ rack (>= 1.0)
79
+ rails-observers (0.1.1)
80
+ railties (~> 4.0.0.beta)
81
+ railties (4.0.0.rc2)
82
+ actionpack (= 4.0.0.rc2)
83
+ activesupport (= 4.0.0.rc2)
84
+ rake (>= 0.8.7)
85
+ thor (>= 0.18.1, < 2.0)
86
+ rake (10.1.0)
87
+ rb-fsevent (0.9.3)
88
+ rb-inotify (0.9.0)
89
+ ffi (>= 0.5.0)
90
+ rb-kqueue (0.2.0)
91
+ ffi (>= 0.5.0)
92
+ rest-client (1.6.7)
93
+ mime-types (>= 1.16)
94
+ rspec (2.13.0)
95
+ rspec-core (~> 2.13.0)
96
+ rspec-expectations (~> 2.13.0)
97
+ rspec-mocks (~> 2.13.0)
98
+ rspec-core (2.13.1)
99
+ rspec-expectations (2.13.0)
100
+ diff-lcs (>= 1.1.3, < 2.0)
101
+ rspec-mocks (2.13.1)
102
+ rspec-nc (0.0.6)
103
+ rspec (~> 2.9)
104
+ terminal-notifier (~> 1.4.2)
105
+ simplecov (0.7.1)
106
+ multi_json (~> 1.0)
107
+ simplecov-html (~> 0.7.1)
108
+ simplecov-html (0.7.1)
109
+ slop (3.4.5)
110
+ sqlite3 (1.3.7)
111
+ terminal-notifier (1.4.2)
112
+ thor (0.18.1)
113
+ thread_safe (0.1.0)
114
+ atomic
115
+ tzinfo (0.3.37)
116
+
117
+ PLATFORMS
118
+ ruby
119
+
120
+ DEPENDENCIES
121
+ coveralls
122
+ guard-rspec
123
+ mocha (= 0.14.0)
124
+ rspec (~> 2.13.0)
125
+ rspec-nc
126
+ simplecov
127
+ tkellem!
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cli: '-f progress -f Nc', env: { 'NO_SIMPLECOV' => '1' } do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(tkellem/)?(.+)\.rb$}) { |m| "spec/#{m[2]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  [![Build
4
4
  Status](https://travis-ci.org/codekitchen/tkellem.png)](https://travis-ci.org/codekitchen/tkellem)
5
+ [![Code Climate](https://codeclimate.com/github/codekitchen/tkellem.png)](https://codeclimate.com/github/codekitchen/tkellem)
6
+ [![Coverage Status](https://coveralls.io/repos/codekitchen/tkellem/badge.png)](https://coveralls.io/r/codekitchen/tkellem)
7
+
5
8
 
6
9
  tkellem is an IRC bouncer, a proxy that keeps you permanently logged on to an
7
10
  IRC server and stores all messages so that when your client next connects, you
@@ -1,48 +1,40 @@
1
1
  class BackwardsFileReader
2
- def self.scan(stream)
3
- scanner = new(stream)
2
+ def self.scan(stream, *init_args)
3
+ scanner = new(stream, *init_args)
4
4
  while line = scanner.readline
5
5
  break unless yield(line)
6
6
  end
7
7
  scanner.sync
8
8
  end
9
9
 
10
- def initialize(stream)
10
+ DEFAULT_READ_SIZE = 4096
11
+
12
+ def initialize(stream, read_size = DEFAULT_READ_SIZE)
11
13
  @stream = stream
12
14
  @stream.seek 0, IO::SEEK_END
13
15
  @pos = @stream.pos
14
- @offset = 0
15
16
 
16
- @read_size = [4096, @pos].min
17
+ @read_size = [read_size, @pos].min
17
18
  @line_buffer = []
18
19
  end
19
20
 
20
21
  def readline
21
- if @line_buffer.size > 2 || @pos == 0
22
- line = @line_buffer.pop
23
- if line
24
- @offset += line.length
25
- end
26
- return line
27
- end
28
-
29
- @read_size = [@read_size, @pos].min
30
- @pos -= @read_size
31
- @stream.seek(@pos, IO::SEEK_SET)
32
- @offset = -@line_buffer.reduce(0) { |n,l| n + l.length }
22
+ while @line_buffer.size < 2 && @pos > 0
23
+ @read_size = [@read_size, @pos].min
24
+ @pos -= @read_size
25
+ @stream.seek(@pos, IO::SEEK_SET)
33
26
 
34
- @line_buffer[0] = "#{@stream.read(@read_size)}#{@line_buffer[0]}"
35
- @line_buffer[0] = @line_buffer[0].scan(%r{.*\n})
36
- @line_buffer.flatten!
27
+ @line_buffer[0] = "#{@stream.read(@read_size)}#{@line_buffer[0]}"
28
+ @line_buffer[0] = @line_buffer[0].scan(%r{.*\n})
29
+ @line_buffer.flatten!
30
+ end
37
31
 
38
- readline
32
+ @line_buffer.pop
39
33
  end
40
34
 
41
35
  def sync
42
- if @offset > 0
43
- @stream.seek(-@offset, IO::SEEK_CUR)
44
- end
45
- @offset = 0
36
+ offset = @read_size - @line_buffer.inject(0) { |n, l| n + l.size }
37
+ @stream.seek(-offset, IO::SEEK_CUR) if offset != 0
46
38
  @stream
47
39
  end
48
40
  end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'active_support/core_ext/class/attribute_accessors'
2
3
 
3
4
  require 'tkellem/irc_server'
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'active_support/core_ext/object/blank'
2
3
 
3
4
  require 'eventmachine'
@@ -91,6 +92,7 @@ module BouncerConnection
91
92
 
92
93
  def receive_line(line)
93
94
  failsafe("message: {#{line}}") do
95
+ line.force_encoding Encoding::UTF_8
94
96
  trace "from client: #{line}"
95
97
  return if line.blank?
96
98
  msg = IrcMessage.parse(line)
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'fileutils'
2
3
  require 'optparse'
3
4
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  module Tkellem
2
3
 
3
4
  class IrcMessage < Struct.new(:prefix, :command, :args, :ctcp)
@@ -50,10 +51,6 @@ class IrcMessage < Struct.new(:prefix, :command, :args, :ctcp)
50
51
  self.ctcp == 'ACTION'
51
52
  end
52
53
 
53
- def command?(cmd)
54
- @command.downcase == cmd.downcase
55
- end
56
-
57
54
  def replay
58
55
  line = []
59
56
  line << ":#{prefix}" unless prefix.nil?
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'eventmachine'
2
3
  require 'set'
3
4
  require 'socket'
@@ -39,6 +40,7 @@ module IrcServerConnection
39
40
 
40
41
  def receive_line(line)
41
42
  @bouncer.failsafe(:receive_line) do
43
+ line.force_encoding Encoding::UTF_8
42
44
  @bouncer.trace "from server: #{line}"
43
45
  return if line.blank?
44
46
  msg = IrcMessage.parse(line)
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'backwards_file_reader'
2
3
  require 'fileutils'
3
4
  require 'pathname'
@@ -94,7 +95,7 @@ class Backlog
94
95
  end
95
96
 
96
97
  def get_stream(ctx, for_reading = false)
97
- mode = for_reading ? 'rb' : 'ab'
98
+ mode = for_reading ? 'rb:utf-8' : 'ab:utf-8'
98
99
  ctx = ctx.gsub(%r{[\./\\]}, '')
99
100
  path = stream_path(ctx)
100
101
  return nil if !path.file? && for_reading
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'eventmachine'
2
3
 
3
4
  require 'tkellem/tkellem_bot'
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'shellwords'
2
3
  require 'yaml'
3
4
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'eventmachine'
2
3
  require 'active_record'
3
4
  require 'rails/observers/activerecord/active_record'
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  module Tkellem
2
- VERSION = "0.9.1"
3
+ VERSION = "0.9.2"
3
4
  end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe BackwardsFileReader do
4
+ let :testfile do
5
+ Tempfile.new("tkellem-test").tap do |tf|
6
+ tf.write <<-LINES
7
+ line1
8
+ line2
9
+ line3
10
+ LINES
11
+ tf.rewind
12
+ end
13
+ end
14
+
15
+ describe '.scan' do
16
+ it "should read all lines" do
17
+ results = mock('lines')
18
+ results.expects(:got).with("line3\n")
19
+ results.expects(:got).with("line2\n")
20
+ results.expects(:got).with("line1\n")
21
+
22
+ BackwardsFileReader.scan(testfile) { |line| results.got(line); true }
23
+ testfile.pos.should == 0
24
+ end
25
+
26
+ it "should abort if the block returns false" do
27
+ results = mock('lines')
28
+ results.expects(:got).with("line3\n")
29
+ results.expects(:got).with("line2\n")
30
+ BackwardsFileReader.scan(testfile) do |line|
31
+ results.got(line)
32
+ line != "line2\n"
33
+ end
34
+ testfile.pos.should == 6
35
+ end
36
+ end
37
+
38
+ describe "#readline" do
39
+ it "should read correctly with a buffer size smaller than one line" do
40
+ reader = BackwardsFileReader.new(testfile, 2)
41
+ reader.readline.should == "line3\n"
42
+ reader.readline.should == "line2\n"
43
+ reader.readline.should == "line1\n"
44
+ reader.readline.should == nil
45
+ end
46
+
47
+ it "should read correctly with a buffer size larger than one line" do
48
+ reader = BackwardsFileReader.new(testfile, 6)
49
+ reader.readline.should == "line3\n"
50
+ reader.readline.should == "line2\n"
51
+ reader.readline.should == "line1\n"
52
+ reader.readline.should == nil
53
+ end
54
+ end
55
+
56
+ describe "#sync" do
57
+ it "should reset the stream position to the current line" do
58
+ reader = BackwardsFileReader.new(testfile)
59
+ reader.readline
60
+ reader.sync.should == testfile
61
+ testfile.pos.should == testfile.size - 6
62
+
63
+ reader = BackwardsFileReader.new(testfile)
64
+ reader.readline
65
+ reader.readline
66
+ reader.sync.should == testfile
67
+ testfile.pos.should == testfile.size - 12
68
+ end
69
+
70
+ it "should reset correctly with a buffer size smaller than one line" do
71
+ reader = BackwardsFileReader.new(testfile, 2)
72
+ reader.readline
73
+ reader.sync.should == testfile
74
+ testfile.pos.should == testfile.size - 6
75
+
76
+ reader = BackwardsFileReader.new(testfile, 2)
77
+ reader.readline
78
+ reader.readline
79
+ reader.sync.should == testfile
80
+ testfile.pos.should == testfile.size - 12
81
+ end
82
+
83
+ it "should reset correctly with a buffer size larger than one line" do
84
+ reader = BackwardsFileReader.new(testfile, 7)
85
+ reader.readline
86
+ reader.sync.should == testfile
87
+ testfile.pos.should == testfile.size - 6
88
+
89
+ reader = BackwardsFileReader.new(testfile, 7)
90
+ reader.readline
91
+ reader.readline
92
+ reader.sync.should == testfile
93
+ testfile.pos.should == testfile.size - 12
94
+ end
95
+ end
96
+
97
+ it "should support resuming" do
98
+ reader = BackwardsFileReader.new(testfile, 2)
99
+ reader.readline.should == "line3\n"
100
+ reader.sync
101
+ testfile.pos.should == testfile.size - 6
102
+ reader.readline.should == "line2\n"
103
+ reader.sync
104
+ testfile.pos.should == testfile.size - 12
105
+ reader.readline.should == "line1\n"
106
+ reader.sync
107
+ testfile.pos.should == 0
108
+ end
109
+ end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'tkellem/irc_message'
3
+ require 'time'
3
4
 
4
5
  include Tkellem
5
6
 
@@ -41,12 +42,19 @@ end
41
42
  describe IrcMessage, "#with_timestamp" do
42
43
  it "should prefix a timestamp to the last arg" do
43
44
  line = IrcMessage.parse(":some_long_prefix COMMAND first second :long arg here")
44
- require 'time'
45
45
  timestamp = Time.parse("Thu Nov 29 14:33:20 2001")
46
46
  ts_line = line.with_timestamp(timestamp)
47
47
  ts_line.should be_a(IrcMessage)
48
48
  ts_line.to_s.should == ":some_long_prefix COMMAND first second :2001-11-29 14:33:20> long arg here"
49
49
  end
50
+
51
+ it "should not prefix the date if the message is < 24 hours old" do
52
+ line = IrcMessage.parse(":some_long_prefix COMMAND first second :long arg here")
53
+ timestamp = 3.hours.ago
54
+ ts_line = line.with_timestamp(timestamp)
55
+ ts_line.should be_a(IrcMessage)
56
+ ts_line.to_s.should == ":some_long_prefix COMMAND first second :#{timestamp.strftime("%H:%M:%S")}> long arg here"
57
+ end
50
58
  end
51
59
 
52
60
  describe IrcMessage do
@@ -59,6 +67,22 @@ describe IrcMessage do
59
67
  line2.args.should == %w(one two three)
60
68
  line2.args.last.should == "three"
61
69
  end
70
+
71
+ describe ".parse_client_command" do
72
+ it "should return nil for non-client commands" do
73
+ IrcMessage.parse_client_command("PRIVMSG a :b c d").should == nil
74
+ end
75
+
76
+ it "should turn /msg into a PRIVMSG command" do
77
+ IrcMessage.parse_client_command("/msg brian hai there").should ==
78
+ IrcMessage.new(nil, "PRIVMSG", ["brian", "hai there"])
79
+ end
80
+
81
+ it "should treat other commands literally" do
82
+ IrcMessage.parse_client_command("/join #tkellem").should ==
83
+ IrcMessage.new(nil, "JOIN", ["#tkellem"])
84
+ end
85
+ end
62
86
  end
63
87
 
64
88
  describe IrcMessage, "CTCP" do
data/spec/spec_helper.rb CHANGED
@@ -2,9 +2,19 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
4
  require 'rspec'
5
- require 'simplecov'
6
- SimpleCov.start do
7
- add_filter "/spec"
5
+ require 'mocha/api'
6
+
7
+ unless ENV['NO_SIMPLECOV']
8
+ require 'simplecov'
9
+ require 'coveralls'
10
+ SimpleCov.formatter = if ENV['TRAVIS']
11
+ Coveralls::SimpleCov::Formatter
12
+ else
13
+ SimpleCov::Formatter::HTMLFormatter
14
+ end
15
+ SimpleCov.start do
16
+ add_filter "/spec"
17
+ end
8
18
  end
9
19
 
10
20
  require 'tkellem'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tkellem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
12
+ date: 2013-06-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -83,9 +83,12 @@ executables:
83
83
  extensions: []
84
84
  extra_rdoc_files: []
85
85
  files:
86
+ - .coveralls.yml
86
87
  - .gitignore
87
88
  - .travis.yml
88
89
  - Gemfile
90
+ - Gemfile.lock
91
+ - Guardfile
89
92
  - LICENSE
90
93
  - README.md
91
94
  - Rakefile
@@ -101,7 +104,6 @@ files:
101
104
  - debian/rules
102
105
  - debian/source/format
103
106
  - debian/tkellem.1
104
- - examples/config.yml
105
107
  - lib/backwards_file_reader.rb
106
108
  - lib/tkellem.rb
107
109
  - lib/tkellem/bouncer.rb
@@ -129,6 +131,7 @@ files:
129
131
  - lib/tkellem/version.rb
130
132
  - resources/bot_command_descriptions.yml
131
133
  - resources/setting_descriptions.yml
134
+ - spec/backwards_file_reader_spec.rb
132
135
  - spec/bouncer_connection_spec.rb
133
136
  - spec/irc_message_spec.rb
134
137
  - spec/irc_server_spec.rb
@@ -148,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
151
  version: '0'
149
152
  segments:
150
153
  - 0
151
- hash: 4403450271075957014
154
+ hash: -1609570308087987502
152
155
  required_rubygems_version: !ruby/object:Gem::Requirement
153
156
  none: false
154
157
  requirements:
@@ -157,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
160
  version: '0'
158
161
  segments:
159
162
  - 0
160
- hash: 4403450271075957014
163
+ hash: -1609570308087987502
161
164
  requirements: []
162
165
  rubyforge_project:
163
166
  rubygems_version: 1.8.23
@@ -165,6 +168,7 @@ signing_key:
165
168
  specification_version: 3
166
169
  summary: IRC bouncer with multi-client support
167
170
  test_files:
171
+ - spec/backwards_file_reader_spec.rb
168
172
  - spec/bouncer_connection_spec.rb
169
173
  - spec/irc_message_spec.rb
170
174
  - spec/irc_server_spec.rb
data/examples/config.yml DELETED
@@ -1,2 +0,0 @@
1
- # this file is deprecated, settings are now stored in ~/.tkellem/tkellem.sqlite3
2
- # more help to come