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 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: []