tkellem 0.7.1 → 0.8.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/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README.md +28 -6
- data/Rakefile +14 -5
- data/bin/tkellem +2 -107
- data/debian/changelog +5 -0
- data/debian/compat +1 -0
- data/debian/control +18 -0
- data/debian/copyright +42 -0
- data/debian/docs +1 -0
- data/debian/examples +1 -0
- data/debian/install +3 -0
- data/debian/manpages +1 -0
- data/debian/rules +13 -0
- data/debian/source/format +1 -0
- data/debian/tkellem.1 +11 -0
- data/examples/config.yml +2 -29
- data/lib/tkellem/bouncer.rb +196 -31
- data/lib/tkellem/bouncer_connection.rb +90 -85
- data/lib/tkellem/daemon.rb +155 -0
- data/lib/tkellem/irc_message.rb +58 -0
- data/lib/tkellem/irc_server.rb +8 -121
- data/lib/tkellem/migrations/001_init_db.rb +33 -0
- data/lib/tkellem/models/host.rb +11 -0
- data/lib/tkellem/models/listen_address.rb +12 -0
- data/lib/tkellem/models/network.rb +15 -0
- data/lib/tkellem/models/network_user.rb +12 -0
- data/lib/tkellem/models/user.rb +56 -0
- data/lib/tkellem/plugins/backlog.rb +160 -0
- data/lib/tkellem/plugins/push_service.rb +152 -0
- data/lib/tkellem/socket_server.rb +29 -0
- data/lib/tkellem/tkellem_bot.rb +318 -0
- data/lib/tkellem/tkellem_server.rb +114 -0
- data/lib/tkellem/version.rb +3 -0
- data/lib/tkellem.rb +7 -10
- data/resources/bot_command_descriptions.yml +36 -0
- data/spec/irc_message_spec.rb +47 -0
- data/spec/irc_server_spec.rb +60 -0
- data/spec/spec_helper.rb +0 -2
- data/tkellem.gemspec +20 -47
- metadata +118 -22
- data/VERSION +0 -1
- data/lib/tkellem/backlog.rb +0 -85
- data/lib/tkellem/irc_line.rb +0 -58
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -4,14 +4,36 @@ tkellem is an IRC bouncer, a proxy that keeps you permanently logged on to an
|
|
4
4
|
IRC server and stores all messages so that when your client next connects, you
|
5
5
|
can see the backlog of what happened while you were gone.
|
6
6
|
|
7
|
-
tkellem supports multiple device-independent backlogs
|
8
|
-
multiple IRC servers all from the same
|
7
|
+
tkellem supports multiple users, multiple device-independent backlogs
|
8
|
+
per-user, and connecting to multiple IRC servers all from the same
|
9
|
+
process.
|
9
10
|
|
10
11
|
## IMPORTANT
|
11
12
|
|
12
|
-
This is a
|
13
|
-
|
13
|
+
This is still a pretty early alpha. Expect bugs and missing
|
14
|
+
functionality.
|
14
15
|
|
15
|
-
##
|
16
|
+
## Getting Started
|
16
17
|
|
17
|
-
|
18
|
+
This will have to do as a quickstart guide, for now:
|
19
|
+
|
20
|
+
$ git clone git://github.com/codekitchen/tkellem.git
|
21
|
+
$ cd tkellem
|
22
|
+
$ bundle install
|
23
|
+
$ bundle exec bin/tkellem start
|
24
|
+
$ bundle exec bin/tkellem admin
|
25
|
+
> help
|
26
|
+
> listen ircs://0.0.0.0:8765
|
27
|
+
> user --add <my-name> --admin
|
28
|
+
> password --user <my-name> <my-new-password>
|
29
|
+
> network --add --public freenode ircs://irc.freenode.org:7000
|
30
|
+
|
31
|
+
Then connect to tkellem with an irc client:
|
32
|
+
|
33
|
+
server: localhost
|
34
|
+
port: 8765
|
35
|
+
ssl: yes
|
36
|
+
|
37
|
+
nickname: <my-name>
|
38
|
+
login: <my-name>@freenode
|
39
|
+
server password: <my-new-password>
|
data/Rakefile
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
require 'rspec/core/rake_task'
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
5
3
|
|
6
4
|
task :default => :spec
|
7
5
|
|
6
|
+
require 'rspec/core/rake_task'
|
8
7
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
-
spec.pattern = 'spec
|
8
|
+
spec.pattern = 'spec/*_spec.rb'
|
9
|
+
end
|
10
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
11
|
+
t.rcov = true
|
12
|
+
t.rcov_opts = ["--exclude", "spec,gems/,rubygems/"]
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'yard'
|
16
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
17
|
+
version = Tkellem::VERSION
|
18
|
+
t.options = ["--title", "tkellem #{version}", "--files", "LICENSE,README.md"]
|
10
19
|
end
|
11
20
|
|
12
21
|
begin
|
data/bin/tkellem
CHANGED
@@ -1,110 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
require 'yaml'
|
8
|
-
require 'optparse'
|
3
|
+
require 'tkellem/daemon'
|
9
4
|
|
10
|
-
|
11
|
-
opts.banner = <<BANNER
|
12
|
-
Usage: #{opts.program_name} PATH_TO_CONFIG
|
13
|
-
|
14
|
-
Start a tkellem instance using the specified configuration file (or ~/.tkellem/config.yml if none given)
|
15
|
-
BANNER
|
16
|
-
|
17
|
-
opts.on_tail("-h", "--help") { puts opts; exit }
|
18
|
-
|
19
|
-
rest = opts.parse(ARGV)
|
20
|
-
config_filename = rest.first || File.expand_path(ENV["HOME"]+'/.tkellem/config.yml')
|
21
|
-
|
22
|
-
config = YAML.load_file(config_filename)
|
23
|
-
|
24
|
-
$LOAD_PATH.push(File.expand_path(File.dirname(__FILE__)+'/../lib'))
|
25
|
-
require 'tkellem'
|
26
|
-
|
27
|
-
EM.run do
|
28
|
-
bouncer =
|
29
|
-
Tkellem::Bouncer.new(config['listen'] || '0.0.0.0',
|
30
|
-
config['port'] || 10001,
|
31
|
-
config['ssl'])
|
32
|
-
|
33
|
-
bouncer.max_backlog = config['max_backlog'].to_i
|
34
|
-
|
35
|
-
bouncer.on_authenticate do |username, password, irc_server|
|
36
|
-
server_config = config['connections'][irc_server.name]
|
37
|
-
if server_config && password_sha1 = server_config['password_sha1']
|
38
|
-
require 'openssl'
|
39
|
-
password_sha1 == OpenSSL::Digest::SHA1.hexdigest(password)
|
40
|
-
else
|
41
|
-
true
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def add_irc_server(bouncer, name, conn)
|
46
|
-
server = bouncer.add_irc_server(name,
|
47
|
-
conn['host'], conn['port'], conn['ssl'],
|
48
|
-
conn['nick'])
|
49
|
-
|
50
|
-
(conn['rooms'] || []).each { |room| server.join_room(room['name']) }
|
51
|
-
conn['clients'].each { |client| server.add_client(client['name']) }
|
52
|
-
end
|
53
|
-
|
54
|
-
config['connections'].each do |name, conn|
|
55
|
-
Tkellem::EasyLogger.logger.info("adding new connection #{name}")
|
56
|
-
add_irc_server(bouncer, name, conn)
|
57
|
-
end
|
58
|
-
|
59
|
-
Signal.trap('HUP') do
|
60
|
-
Tkellem::EasyLogger.logger.warn("got HUP, reloading #{config_filename}")
|
61
|
-
new_config = YAML.load_file(config_filename)
|
62
|
-
|
63
|
-
bouncer.max_backlog = new_config['max_backlog'].to_i
|
64
|
-
|
65
|
-
# find changed connections
|
66
|
-
to_delete = config['connections'].keys
|
67
|
-
|
68
|
-
new_config['connections'].each do |name, new_conn|
|
69
|
-
to_delete.delete(name)
|
70
|
-
conn = config['connections'][name]
|
71
|
-
if !conn
|
72
|
-
Tkellem::EasyLogger.logger.info("adding new connection #{name}")
|
73
|
-
add_irc_server(bouncer, name, new_conn)
|
74
|
-
else
|
75
|
-
if new_conn['host'] != conn['host'] || new_conn['port'] != conn['port'] || new_conn['ssl'] != conn['ssl']
|
76
|
-
Tkellem::EasyLogger.logger.info("server settings changed for #{name}, dropping clients and reconnecting")
|
77
|
-
bouncer.remove_irc_server(name)
|
78
|
-
add_irc_server(bouncer, name, new_conn)
|
79
|
-
elsif conn['clients'] != new_conn['clients']
|
80
|
-
irc_server = bouncer.get_irc_server(name)
|
81
|
-
|
82
|
-
# we don't have to reconnect, but maybe clients changed. we ignore
|
83
|
-
# changes to nick and rooms on HUP, since those are dynamic once tkellem
|
84
|
-
# connects. password change will be caught on the next client
|
85
|
-
# connect.
|
86
|
-
clients_to_delete = conn['clients'].map { |c| c['name'] }
|
87
|
-
new_conn['clients'].each do |new_client|
|
88
|
-
clients_to_delete.delete(new_client['name'])
|
89
|
-
# add -- if already exists, this is a no-op. this may change in the
|
90
|
-
# future though...
|
91
|
-
Tkellem::EasyLogger.logger.info("adding client #{new_client['name']} to server #{name}")
|
92
|
-
irc_server.add_client(new_client['name'])
|
93
|
-
end
|
94
|
-
clients_to_delete.each do |client_name|
|
95
|
-
Tkellem::EasyLogger.logger.info("removing client #{client_name} from server #{name}")
|
96
|
-
irc_server.remove_client(client_name) if irc_server
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
to_delete.each do |name|
|
103
|
-
Tkellem::EasyLogger.logger.info("deleting connection #{name}")
|
104
|
-
bouncer.remove_irc_server(name)
|
105
|
-
end
|
106
|
-
|
107
|
-
config = new_config
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
5
|
+
Tkellem::Daemon.new(ARGV).run()
|
data/debian/changelog
ADDED
data/debian/compat
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
7
|
data/debian/control
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Source: tkellem
|
2
|
+
Section: net
|
3
|
+
Priority: extra
|
4
|
+
Maintainer: paul cannon <pik@debian.org>
|
5
|
+
Build-Depends: debhelper (>= 7.0.50~)
|
6
|
+
Standards-Version: 3.9.1
|
7
|
+
Homepage: https://github.com/codekitchen/tkellem
|
8
|
+
|
9
|
+
Package: tkellem
|
10
|
+
Architecture: all
|
11
|
+
Depends: ${misc:Depends}, ruby, rubygems, libeventmachine-ruby
|
12
|
+
Description: IRC bouncer with multi-client support
|
13
|
+
tkellem is an IRC bouncer, a proxy that keeps you permanently logged on to an
|
14
|
+
IRC server and stores all messages so that when your client next connects, you
|
15
|
+
can see the backlog of what happened while you were gone.
|
16
|
+
.
|
17
|
+
tkellem supports multiple device-independent backlogs, and connecting to
|
18
|
+
multiple IRC servers all from the same process.
|
data/debian/copyright
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
This work was packaged for Debian by:
|
2
|
+
|
3
|
+
paul cannon <pik@debian.org> on Thu, 16 Dec 2010 11:58:18 -0600
|
4
|
+
|
5
|
+
It was downloaded from:
|
6
|
+
|
7
|
+
https://github.com/codekitchen/tkellem
|
8
|
+
|
9
|
+
Upstream Author(s):
|
10
|
+
|
11
|
+
Brian Palmer
|
12
|
+
|
13
|
+
Copyright:
|
14
|
+
|
15
|
+
Copyright (c) 2010 Brian Palmer <brian@codekitchen.net>
|
16
|
+
|
17
|
+
License:
|
18
|
+
|
19
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
20
|
+
copy of this software and associated documentation files (the "Software"),
|
21
|
+
to deal in the Software without restriction, including without limitation
|
22
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
23
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
24
|
+
Software is furnished to do so, subject to the following conditions:
|
25
|
+
|
26
|
+
The above copyright notice and this permission notice shall be included in
|
27
|
+
all copies or substantial portions of the Software.
|
28
|
+
|
29
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
30
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
31
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
32
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
33
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
34
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
35
|
+
DEALINGS IN THE SOFTWARE.
|
36
|
+
|
37
|
+
The Debian packaging is:
|
38
|
+
|
39
|
+
Copyright (C) 2010 paul cannon <pik@debian.org>
|
40
|
+
|
41
|
+
and may be distributed and used under the same terms as the underlying work
|
42
|
+
(see above).
|
data/debian/docs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
README.md
|
data/debian/examples
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
examples/config.yml
|
data/debian/install
ADDED
data/debian/manpages
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
debian/tkellem.1
|
data/debian/rules
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/make -f
|
2
|
+
# -*- makefile -*-
|
3
|
+
# Sample debian/rules that uses debhelper.
|
4
|
+
# This file was originally written by Joey Hess and Craig Small.
|
5
|
+
# As a special exception, when this file is copied by dh-make into a
|
6
|
+
# dh-make output file, you may use that output file without restriction.
|
7
|
+
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
8
|
+
|
9
|
+
# Uncomment this to turn on verbose mode.
|
10
|
+
#export DH_VERBOSE=1
|
11
|
+
|
12
|
+
%:
|
13
|
+
dh $@
|
@@ -0,0 +1 @@
|
|
1
|
+
3.0 (quilt)
|
data/debian/tkellem.1
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.38.2.
|
2
|
+
.TH TKELLEM "1" "December 2010" "Brian Palmer" "User Commands"
|
3
|
+
.SH NAME
|
4
|
+
tkellem \- tkellem
|
5
|
+
.SH SYNOPSIS
|
6
|
+
.B tkellem
|
7
|
+
\fIPATH_TO_CONFIG\fR
|
8
|
+
.SH DESCRIPTION
|
9
|
+
Start a tkellem instance using the specified configuration file (or ~/.tkellem/config.yml if none given)
|
10
|
+
.HP
|
11
|
+
\fB\-h\fR, \fB\-\-help\fR
|
data/examples/config.yml
CHANGED
@@ -1,29 +1,2 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# to connect: connect to localhost port 10001, ssl enabled, "real name" set to
|
4
|
-
#
|
5
|
-
# <connection_name> <client_name>
|
6
|
-
#
|
7
|
-
# e.g.:
|
8
|
-
#
|
9
|
-
# freenode laptop
|
10
|
-
---
|
11
|
-
listen: 0.0.0.0
|
12
|
-
port: 10001
|
13
|
-
ssl: true
|
14
|
-
# max_backlog: 500
|
15
|
-
connections:
|
16
|
-
freenode:
|
17
|
-
host: irc.freenode.org
|
18
|
-
port: 6667
|
19
|
-
ssl: false
|
20
|
-
nick: tkellem_r0ck
|
21
|
-
# Uncomment to enable password auth (there's no auth by default, which
|
22
|
-
# means anybody can connect). You can generate a password_sha1 like so:
|
23
|
-
# echo -n 'tkellem_r0ck' | openssl sha1
|
24
|
-
# password_sha1: a4f4a3b97c7b8a028d4e3f3fee85d6e5626baba5
|
25
|
-
rooms:
|
26
|
-
- name: "#tkellem_test"
|
27
|
-
clients:
|
28
|
-
- name: laptop
|
29
|
-
- name: iphone
|
1
|
+
# this file is deprecated, settings are now stored in ~/.tkellem/tkellem.sqlite3
|
2
|
+
# more help to come
|
data/lib/tkellem/bouncer.rb
CHANGED
@@ -1,52 +1,217 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
2
2
|
|
3
3
|
require 'tkellem/irc_server'
|
4
|
+
require 'tkellem/bouncer_connection'
|
4
5
|
|
5
6
|
module Tkellem
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
|
8
|
+
class Bouncer
|
9
|
+
include Tkellem::EasyLogger
|
10
|
+
|
11
|
+
attr_reader :user, :network, :nick
|
12
|
+
cattr_accessor :plugins
|
13
|
+
self.plugins = []
|
14
|
+
|
15
|
+
def initialize(network_user)
|
16
|
+
@network_user = network_user
|
17
|
+
@user = network_user.user
|
18
|
+
@network = network_user.network
|
19
|
+
|
20
|
+
@nick = network_user.nick
|
21
|
+
# maps { client_conn => state_hash }
|
22
|
+
@active_conns = {}
|
23
|
+
@welcomes = []
|
24
|
+
@rooms = ['#tk']
|
25
|
+
# maps { client_conn => away_status_or_nil }
|
26
|
+
@away = {}
|
27
|
+
# plugin data
|
28
|
+
@data = {}
|
29
|
+
# clients waiting for us to connect to the irc server
|
30
|
+
@waiting_clients = []
|
31
|
+
|
32
|
+
connect!
|
33
|
+
end
|
34
|
+
|
35
|
+
def data(key)
|
36
|
+
@data[key] ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def active_conns
|
40
|
+
@active_conns.keys
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.add_plugin(plugin)
|
44
|
+
self.plugins << plugin
|
45
|
+
end
|
46
|
+
|
47
|
+
def connected?
|
48
|
+
!!@connected
|
49
|
+
end
|
50
|
+
|
51
|
+
def connect_client(client)
|
52
|
+
@active_conns[client] = {}
|
53
|
+
@away[client] = nil
|
54
|
+
|
55
|
+
if !connected?
|
56
|
+
@waiting_clients << client
|
57
|
+
client.say_as_tkellem("Connecting you to the IRC server. Please wait...")
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
send_welcome(client)
|
62
|
+
# make the client join all the rooms that we're in
|
63
|
+
@rooms.each { |room| client.simulate_join(room) }
|
64
|
+
|
65
|
+
plugins.each { |plugin| plugin.new_client_connected(self, client) }
|
66
|
+
check_away_status
|
67
|
+
end
|
68
|
+
|
69
|
+
def disconnect_client(client)
|
70
|
+
@away.delete(client)
|
71
|
+
check_away_status
|
72
|
+
@active_conns.delete(client)
|
73
|
+
end
|
74
|
+
|
75
|
+
def client_msg(client, msg)
|
76
|
+
return if plugins.any? do |plugin|
|
77
|
+
!plugin.client_msg(self, client, msg)
|
78
|
+
end
|
79
|
+
|
80
|
+
forward = case msg.command
|
81
|
+
when 'PING'
|
82
|
+
client.send_msg(":tkellem!tkellem PONG tkellem :#{msg.args.last}")
|
83
|
+
false
|
84
|
+
when 'AWAY'
|
85
|
+
@away[client] = msg.args.last
|
86
|
+
check_away_status
|
87
|
+
false
|
88
|
+
else
|
89
|
+
true
|
12
90
|
end
|
13
91
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
server.set_max_backlog(@max_backlog) if @max_backlog
|
18
|
-
server
|
92
|
+
if forward
|
93
|
+
# send to server
|
94
|
+
send_msg(msg)
|
19
95
|
end
|
96
|
+
end
|
20
97
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
server.close_connection(true)
|
25
|
-
end
|
98
|
+
def server_msg(msg)
|
99
|
+
return if plugins.any? do |plugin|
|
100
|
+
!plugin.server_msg(self, msg)
|
26
101
|
end
|
27
102
|
|
28
|
-
|
29
|
-
|
103
|
+
forward = case msg.command
|
104
|
+
when /0\d\d/, /2[56]\d/, /37[256]/
|
105
|
+
@welcomes << msg
|
106
|
+
ready! if msg.command == "376" # end of MOTD
|
107
|
+
false
|
108
|
+
when 'JOIN'
|
109
|
+
debug "#{msg.target_user} joined #{msg.args.last}"
|
110
|
+
@rooms << msg.args.last if msg.target_user == @nick
|
111
|
+
true
|
112
|
+
when 'PART'
|
113
|
+
debug "#{msg.target_user} left #{msg.args.last}"
|
114
|
+
@rooms.delete(msg.args.last) if msg.target_user == @nick
|
115
|
+
true
|
116
|
+
when 'PING'
|
117
|
+
send_msg("PONG tkellem!tkellem :#{msg.args.last}")
|
118
|
+
false
|
119
|
+
when 'PONG'
|
120
|
+
# swallow it, we handle ping-pong from clients separately, in
|
121
|
+
# BouncerConnection
|
122
|
+
false
|
123
|
+
else
|
124
|
+
true
|
30
125
|
end
|
31
126
|
|
32
|
-
|
33
|
-
|
34
|
-
@
|
127
|
+
if forward
|
128
|
+
# send to clients
|
129
|
+
@active_conns.each { |c,s| c.send_msg(msg) }
|
35
130
|
end
|
131
|
+
end
|
36
132
|
|
133
|
+
## Away Statuses
|
37
134
|
|
38
|
-
|
135
|
+
def check_away_status
|
136
|
+
# for now we pretty much randomly pick an away status if multiple are set
|
137
|
+
# by clients
|
138
|
+
if @away.any? { |k,v| !v }
|
139
|
+
# we have a client who isn't away
|
140
|
+
send_msg("AWAY")
|
141
|
+
else
|
142
|
+
message = @away.values.first || "Away"
|
143
|
+
send_msg("AWAY :#{message}")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def name
|
149
|
+
"#{user.name}-#{network.name}"
|
150
|
+
end
|
151
|
+
alias_method :log_name, :name
|
152
|
+
|
153
|
+
def send_msg(msg)
|
154
|
+
trace "to server: #{msg}"
|
155
|
+
@conn.send_data("#{msg}\r\n")
|
156
|
+
end
|
157
|
+
|
158
|
+
def connection_established
|
159
|
+
# TODO: support sending a real username, realname, etc
|
160
|
+
send_msg("USER #{@nick} localhost blah :#{@nick}")
|
161
|
+
change_nick(@nick, true)
|
162
|
+
check_away_status
|
163
|
+
end
|
164
|
+
|
165
|
+
def disconnected!
|
166
|
+
debug "OMG we got disconnected."
|
167
|
+
@conn = nil
|
168
|
+
@connected = false
|
169
|
+
@active_conns.each { |c,s| c.unbind }
|
170
|
+
connect!
|
171
|
+
end
|
39
172
|
|
40
|
-
|
41
|
-
|
173
|
+
protected
|
174
|
+
|
175
|
+
def change_nick(new_nick, force = false)
|
176
|
+
return if !force && new_nick == @nick
|
177
|
+
@nick = new_nick
|
178
|
+
send_msg("NICK #{new_nick}")
|
179
|
+
end
|
180
|
+
|
181
|
+
def send_welcome(bouncer_conn)
|
182
|
+
@welcomes.each { |msg| bouncer_conn.send_msg(msg) }
|
183
|
+
end
|
184
|
+
|
185
|
+
def connect!
|
186
|
+
span = @last_connect ? Time.now - @last_connect : 1000
|
187
|
+
hosts = @network.hosts(true).map { |h| h }
|
188
|
+
|
189
|
+
if span < 5 || hosts.length < 1
|
190
|
+
EM.add_timer(5) { connect! }
|
191
|
+
return
|
192
|
+
end
|
193
|
+
@last_connect = Time.now
|
194
|
+
@cur_host = (@cur_host || 0) % hosts.length
|
195
|
+
host = hosts[@cur_host]
|
196
|
+
@conn = EM.connect(host.address, host.port, IrcServerConnection, self, host.ssl)
|
197
|
+
end
|
198
|
+
|
199
|
+
def ready!
|
200
|
+
return if @joined_rooms
|
201
|
+
@joined_rooms = true
|
202
|
+
@rooms.each do |room|
|
203
|
+
send_msg("JOIN #{room}")
|
42
204
|
end
|
43
205
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
206
|
+
# We're all initialized, allow connections
|
207
|
+
@connected = true
|
208
|
+
@waiting_clients.each do |client|
|
209
|
+
client.say_as_tkellem("Now connected.")
|
210
|
+
connect_client(client)
|
50
211
|
end
|
212
|
+
@waiting_clients.clear
|
51
213
|
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
52
217
|
end
|