jacha 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ jacha.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in jacha.gemspec
4
+ gemspec
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Jacha
2
+ VERSION = "0.0.1"
3
+ end
data/lib/jacha.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'jacha/version'
2
+ require 'jacha/connection'
3
+ require 'jacha/connection_pool'
4
+
5
+ module Jacha
6
+ def self.configure
7
+ yield ConnectionPool.instance if block_given?
8
+ end
9
+ end
@@ -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: []