jacha 0.0.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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +49 -0
- data/Rakefile +1 -0
- data/config.ru +12 -0
- data/jacha.gemspec +21 -0
- data/lib/jacha/connection.rb +96 -0
- data/lib/jacha/connection_pool.rb +71 -0
- data/lib/jacha/server.rb +18 -0
- data/lib/jacha/version.rb +3 -0
- data/lib/jacha.rb +9 -0
- data/lib/xmpp4r_monkeypatch.rb +29 -0
- metadata +74 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
## What is this?
|
2
|
+
|
3
|
+
Jacha is a xmpp4r based bot. Currently, it only handles XMPP connection pool and checks whether given JID is online.
|
4
|
+
Also, it can be started as a dedicated service.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
gem 'jacha'
|
9
|
+
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
Put somewhere in your initializers the following code:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
Jacha.configure do |config|
|
16
|
+
config.jid = 'jid@example.com'
|
17
|
+
config.password = 'password'
|
18
|
+
config.size = 3
|
19
|
+
# uncomment to apply charset related xmpp4r monkeypatch
|
20
|
+
# config.fix_charset!
|
21
|
+
end
|
22
|
+
|
23
|
+
if some_environment_specific_condition
|
24
|
+
Jacha::ConnectionPool.spawn
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
Then you anytime can get a random connection from the pool and perform some actions.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
jacha_connection = Jacha::ConnectionPool.get_connection
|
32
|
+
jacha_connection.jabber # here is wrapped Jabber::Client from xmpp4r
|
33
|
+
jacha_connection.online? 'someone@example.com'
|
34
|
+
jacha_connection.online? 'another@example.com', optional_timeout_in_seconds
|
35
|
+
```
|
36
|
+
|
37
|
+
Credits
|
38
|
+
-------
|
39
|
+
|
40
|
+
<img src="http://roundlake.ru/assets/logo.png" align="right" />
|
41
|
+
|
42
|
+
* Alexander Pavlenko ([@alerticus](http://twitter.com/#!/alerticus))
|
43
|
+
|
44
|
+
<br/>
|
45
|
+
|
46
|
+
LICENSE
|
47
|
+
-------
|
48
|
+
|
49
|
+
It is free software, and may be redistributed under the terms of MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/config.ru
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + '/lib')
|
3
|
+
require 'jacha'
|
4
|
+
require 'jacha/server'
|
5
|
+
|
6
|
+
config = ::File.expand_path(ENV['JACHACONFIG'] || 'jacha.rb')
|
7
|
+
if ::File.exists?(config)
|
8
|
+
load config
|
9
|
+
end
|
10
|
+
|
11
|
+
use Rack::ShowExceptions
|
12
|
+
run Jacha::Server.new
|
data/jacha.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "jacha/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "jacha"
|
7
|
+
s.version = Jacha::VERSION
|
8
|
+
s.authors = ["AlexanderPavlenko"]
|
9
|
+
s.email = ["a.pavlenko@roundlake.ru"]
|
10
|
+
s.homepage = "http://github.com/roundlake/jacha"
|
11
|
+
s.summary = %q{Simple xmpp4r bot}
|
12
|
+
s.description = %q{xmpp4r bot that can be included to project as well as started as a standalone service}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
# s.add_development_dependency "rspec"
|
20
|
+
s.add_runtime_dependency "xmpp4r"
|
21
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'xmpp4r'
|
2
|
+
|
3
|
+
module Jacha
|
4
|
+
class Connection
|
5
|
+
|
6
|
+
attr_reader :jabber
|
7
|
+
attr_accessor :pool
|
8
|
+
|
9
|
+
def initialize(jid, password)
|
10
|
+
@password = password
|
11
|
+
@jabber = Jabber::Client.new "#{jid}/#{Time.now.to_f}"
|
12
|
+
@jabber.on_exception do
|
13
|
+
unless broken?
|
14
|
+
broken!
|
15
|
+
logger.warn "#{Time.now}: broken XmppConnection: #{self}"
|
16
|
+
destroy
|
17
|
+
pool.respawn
|
18
|
+
end
|
19
|
+
end
|
20
|
+
connect!
|
21
|
+
@pinger = Thread.new do
|
22
|
+
while true
|
23
|
+
if connected?
|
24
|
+
sleep 180
|
25
|
+
online!
|
26
|
+
else
|
27
|
+
connect!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def connect!
|
34
|
+
@jabber.connect
|
35
|
+
@jabber.auth @password
|
36
|
+
online!
|
37
|
+
end
|
38
|
+
|
39
|
+
def online!(&block)
|
40
|
+
packet = Jabber::Presence.new
|
41
|
+
packet.from = @jabber.jid
|
42
|
+
@jabber.send packet, &block
|
43
|
+
end
|
44
|
+
|
45
|
+
def connected?
|
46
|
+
@jabber.is_connected?
|
47
|
+
end
|
48
|
+
|
49
|
+
def online?(jid, timeout=1.5)
|
50
|
+
# Only works if our bot is authorized by the given JID
|
51
|
+
# see Presence with type :subscribe for more details
|
52
|
+
# Also, bot should be online by itself
|
53
|
+
jid = Jabber::JID.new(jid)
|
54
|
+
pinger = Thread.new do
|
55
|
+
pinger[:online] = nil
|
56
|
+
packet = Jabber::Presence.new
|
57
|
+
packet.to = jid
|
58
|
+
packet.from = @jabber.jid
|
59
|
+
packet.type = :probe
|
60
|
+
@jabber.send(packet) do |presence|
|
61
|
+
from = Jabber::JID.new presence.from
|
62
|
+
if from.node == jid.node && from.domain == jid.domain
|
63
|
+
if presence.type.nil?
|
64
|
+
pinger[:online] = true
|
65
|
+
pinger.stop
|
66
|
+
elsif presence.type == :error
|
67
|
+
pinger.stop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
pinger.join timeout
|
73
|
+
result = pinger[:online]
|
74
|
+
pinger.kill
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy
|
79
|
+
broken!
|
80
|
+
@pinger.kill
|
81
|
+
@jabber.close
|
82
|
+
end
|
83
|
+
|
84
|
+
def broken!
|
85
|
+
@broken = true
|
86
|
+
end
|
87
|
+
|
88
|
+
def broken?
|
89
|
+
@broken
|
90
|
+
end
|
91
|
+
|
92
|
+
def logger
|
93
|
+
pool.logger
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Jacha
|
2
|
+
class ConnectionPool
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
attr_accessor :jid, :password, :size, :logger
|
6
|
+
|
7
|
+
def pool
|
8
|
+
@connections ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def size
|
12
|
+
@size ||= 3
|
13
|
+
end
|
14
|
+
|
15
|
+
def logger
|
16
|
+
@logger ||= Logger.new(STDOUT)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_connection
|
20
|
+
pool.sample
|
21
|
+
end
|
22
|
+
|
23
|
+
def spawn(number=nil)
|
24
|
+
(number || size).times do
|
25
|
+
logger.warn "#{Time.now}: Spawning XmppConnection"
|
26
|
+
spawner = Thread.new do
|
27
|
+
begin
|
28
|
+
connection = Connection.new @jid, @password
|
29
|
+
spawner[:connection] = connection
|
30
|
+
rescue => ex
|
31
|
+
logger.warn "#{Time.now}: Error on XmppConnection spawn: #{ex}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
spawner.join 7
|
35
|
+
connection = spawner[:connection]
|
36
|
+
spawner.kill
|
37
|
+
if connection && connection.connected?
|
38
|
+
connection.pool = self
|
39
|
+
pool << connection
|
40
|
+
logger.warn "#{Time.now}: XmppConnection spawned: #{connection}"
|
41
|
+
else
|
42
|
+
logger.warn "#{Time.now}: XmppConnection spawn failed. Retrying in 7 seconds."
|
43
|
+
sleep 7
|
44
|
+
spawn 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def respawn
|
50
|
+
pool.delete_if &:broken?
|
51
|
+
spawn @size - pool.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy
|
55
|
+
pool.map &:destroy
|
56
|
+
pool.clear
|
57
|
+
end
|
58
|
+
|
59
|
+
def fix_charset!
|
60
|
+
require_relative '../xmpp4r_monkeypatch'
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.method_missing(sym, *args, &block)
|
64
|
+
if instance.respond_to? sym
|
65
|
+
instance.send(sym, *args, &block)
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/jacha/server.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
module Jacha
|
5
|
+
class Server < Sinatra::Application
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
ConnectionPool.instance.spawn
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/check' do
|
13
|
+
checker = ConnectionPool.instance.get_connection
|
14
|
+
result = checker.online? params['jid']
|
15
|
+
"#{!!result}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/jacha.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
if RUBY_VERSION >= '1.9'
|
2
|
+
# Encoding patch
|
3
|
+
# see https://github.com/ln/xmpp4r/issues/3#issuecomment-1739952
|
4
|
+
require 'socket'
|
5
|
+
class TCPSocket
|
6
|
+
def external_encoding
|
7
|
+
Encoding::BINARY
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rexml/source'
|
12
|
+
class REXML::IOSource
|
13
|
+
alias_method :encoding_assign, :encoding=
|
14
|
+
def encoding=(value)
|
15
|
+
encoding_assign(value) if value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
begin
|
20
|
+
# OpenSSL is optional and can be missing
|
21
|
+
require 'openssl'
|
22
|
+
class OpenSSL::SSL::SSLSocket
|
23
|
+
def external_encoding
|
24
|
+
Encoding::BINARY
|
25
|
+
end
|
26
|
+
end
|
27
|
+
rescue
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jacha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- AlexanderPavlenko
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: xmpp4r
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: xmpp4r bot that can be included to project as well as started as a standalone
|
31
|
+
service
|
32
|
+
email:
|
33
|
+
- a.pavlenko@roundlake.ru
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- Gemfile
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- config.ru
|
43
|
+
- jacha.gemspec
|
44
|
+
- lib/jacha.rb
|
45
|
+
- lib/jacha/connection.rb
|
46
|
+
- lib/jacha/connection_pool.rb
|
47
|
+
- lib/jacha/server.rb
|
48
|
+
- lib/jacha/version.rb
|
49
|
+
- lib/xmpp4r_monkeypatch.rb
|
50
|
+
homepage: http://github.com/roundlake/jacha
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.8.18
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Simple xmpp4r bot
|
74
|
+
test_files: []
|