rbitter 0.1.2-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/Gemfile +12 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +72 -0
  8. data/Rakefile +8 -0
  9. data/XMLRPC.md +19 -0
  10. data/bin/rbitter +20 -0
  11. data/lib/rbitter.rb +86 -0
  12. data/lib/rbitter/arcserver.rb +130 -0
  13. data/lib/rbitter/console.rb +93 -0
  14. data/lib/rbitter/default/config_json.rb +37 -0
  15. data/lib/rbitter/dlthread.rb +63 -0
  16. data/lib/rbitter/env.rb +62 -0
  17. data/lib/rbitter/libtwitter_connection_override.rb +46 -0
  18. data/lib/rbitter/records.rb +121 -0
  19. data/lib/rbitter/records_migrate/.keep +0 -0
  20. data/lib/rbitter/records_migrate/20150327_add_index.rb +12 -0
  21. data/lib/rbitter/records_migrate/20150504_add_replyto_column.rb +12 -0
  22. data/lib/rbitter/streaming.rb +105 -0
  23. data/lib/rbitter/version.rb +20 -0
  24. data/lib/rbitter/xmlrpc.rb +4 -0
  25. data/lib/rbitter/xmlrpcd/base.rb +25 -0
  26. data/lib/rbitter/xmlrpcd/rpchandles.rb +12 -0
  27. data/lib/rbitter/xmlrpcd/xmlrpc_auth_server.rb +83 -0
  28. data/lib/rbitter/xmlrpcd/xmlrpcd.rb +69 -0
  29. data/rbitter.gemspec +46 -0
  30. data/spec/config/.keep +0 -0
  31. data/spec/config/default.json +33 -0
  32. data/spec/rbitter/arcserver_spec.rb +30 -0
  33. data/spec/rbitter/console_spec.rb +9 -0
  34. data/spec/rbitter/default/config_json_spec.rb +3 -0
  35. data/spec/rbitter/dlthread_spec.rb +8 -0
  36. data/spec/rbitter/env_spec.rb +62 -0
  37. data/spec/rbitter/libtwitter_connection_override_spec.rb +8 -0
  38. data/spec/rbitter/records_spec.rb +13 -0
  39. data/spec/rbitter/streaming_spec.rb +9 -0
  40. data/spec/rbitter/version_spec.rb +8 -0
  41. data/spec/rbitter/xmlrpc_spec.rb +8 -0
  42. data/spec/rbitter/xmlrpcd/base_spec.rb +29 -0
  43. data/spec/rbitter/xmlrpcd/rpchandles_spec.rb +10 -0
  44. data/spec/rbitter/xmlrpcd/xmlrpc_auth_server_spec.rb +8 -0
  45. data/spec/rbitter/xmlrpcd/xmlrpcd_spec.rb +9 -0
  46. data/spec/rbitter_spec.rb +42 -0
  47. data/spec/sample_data/.keep +0 -0
  48. data/spec/spec_helper.rb +39 -0
  49. metadata +265 -0
@@ -0,0 +1,20 @@
1
+ module Rbitter
2
+ PRODUCT_NAME = "Rbitter"
3
+ VERSION = "0.1.2"
4
+
5
+ def major
6
+ VERSION.match(/^([0-9]+)\./)[1]
7
+ end
8
+
9
+ def minor
10
+ VERSION.match(/\.([0-9]+)\./)[1]
11
+ end
12
+
13
+ def patchlv
14
+ VERSION.match(/\.([0-9]+)$/)[1]
15
+ end
16
+
17
+ def version_string
18
+ "#{PRODUCT_NAME} #{VERSION}"
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ #
3
+
4
+ require "rbitter/xmlrpcd/xmlrpcd"
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module RPCHandles
4
+ RH_INFO = Struct.new("RPCHANDLE_INFO", :name, :version, :author, :description) {
5
+ def digest
6
+ "<rpchandle: #{name}-#{version} (written by #{author}, #{description})>"
7
+ end
8
+ }
9
+
10
+ module BaseHandle
11
+ # If a handler doesn't require an authorization, please inherit below class
12
+ class NoAuth < Object
13
+ def self.auth?
14
+ false
15
+ end
16
+ end
17
+
18
+ # If a handler does require an authorization, please inherit below class
19
+ class Auth < Object
20
+ def self.auth?
21
+ true
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ module RPCHandles
4
+ # Override this function will activate authentication feature.
5
+ # You can write and add RPCHandle. See 'rpc' folder.
6
+
7
+ @@auth_pool = nil
8
+ module_function
9
+ def auth
10
+ @@auth_pool
11
+ end
12
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbitter/xmlrpcd/rpchandles"
4
+ require "rbitter/xmlrpcd/base"
5
+ require "xmlrpc/server"
6
+ require "webrick"
7
+
8
+ module XMLRPC
9
+ class HTTPAuthXMLRPCServer < XMLRPC::WEBrickServlet
10
+ def extract_method(methodname, *args)
11
+ for name, obj in @handler
12
+ if obj.kind_of? Proc
13
+ next unless methodname == name
14
+ else
15
+ next unless methodname =~ /^#{name}(.+)$/
16
+ next unless obj.respond_to? $1
17
+ return obj.method($1)
18
+ end
19
+ end
20
+ nil
21
+ end
22
+
23
+ def service(request, response)
24
+ # Taken from xmlrpc/server.rb
25
+ if @valid_ip
26
+ raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip }
27
+ end
28
+
29
+ if request.request_method != "POST"
30
+ raise WEBrick::HTTPStatus::MethodNotAllowed,
31
+ "unsupported method `#{request.request_method}'."
32
+ end
33
+
34
+ if parse_content_type(request['Content-type']).first != "text/xml"
35
+ raise WEBrick::HTTPStatus::BadRequest
36
+ end
37
+
38
+ length = (request['Content-length'] || 0).to_i
39
+
40
+ raise WEBrick::HTTPStatus::LengthRequired unless length > 0
41
+
42
+ data = request.body
43
+
44
+ if data.nil? or data.bytesize != length
45
+ raise WEBrick::HTTPStatus::BadRequest
46
+ end
47
+
48
+ # Originally, process(data) was here.
49
+ # We need to check whether a method requires authorization.
50
+ rpc_method_name, rpc_params = parser().parseMethodCall(data)
51
+ rpc_method = extract_method(rpc_method_name)
52
+
53
+ if RPCHandles.auth.nil?
54
+ resp = handle(rpc_method_name, *rpc_params)
55
+ else
56
+ if rpc_method.owner.ancestors.include?(RPCHandles::BaseHandle::Auth)
57
+ # Check cookie and check it's valid
58
+ if request.cookies.size == 1 \
59
+ and request.cookies[0].name == "auth_key" \
60
+ and RPCHandles.auth.include?(request.cookies[0].value)
61
+ resp = handle(rpc_method_name, *rpc_params)
62
+ else
63
+ # Permission required
64
+ raise WEBrick::HTTPStatus::Forbidden
65
+ end
66
+ elsif rpc_method.owner.ancestors.include?(RPCHandles::BaseHandle::NoAuth)
67
+ resp = handle(rpc_method_name, *rpc_params)
68
+ else
69
+ raise WEBrick::HTTPStatus::Forbidden
70
+ end
71
+ end
72
+
73
+ if resp.nil? or resp.bytesize <= 0
74
+ raise WEBrick::HTTPStatus::InternalServerError
75
+ end
76
+
77
+ response.status = 200
78
+ response['Content-Length'] = resp.bytesize
79
+ response['Content-Type'] = "text/xml; charset=utf-8"
80
+ response.body = resp
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbitter/xmlrpcd/rpchandles"
4
+ require "rbitter/xmlrpcd/xmlrpc_auth_server"
5
+ require "webrick"
6
+
7
+ module Rbitter
8
+ RPC_PREFIX="rbitter"
9
+
10
+ class RPCServer
11
+ def initialize bind_host, bind_port
12
+ @server = WEBrick::HTTPServer.new(:Port => bind_port.to_i, :BindAddress => bind_host.to_s, :MaxClients => 4, :Logger => WEBrick::Log.new($stdout))
13
+ @core = XMLRPC::HTTPAuthXMLRPCServer.new
14
+ @core.set_default_handler { |name, *args|
15
+ "NO_COMMAND: #{name} with args #{args.inspect}"
16
+ }
17
+ end
18
+
19
+ def load_all_handles
20
+ Rbitter["xmlrpc"]["handles"].each { |path|
21
+ puts "[xmlrpc] Scanning handles from (#{path})"
22
+ Dir.entries(path).each { |fname|
23
+ fname = File.join(path, fname)
24
+ if File.exist?(fname) and File.file?(fname)
25
+ if fname.match(/rh_\w+\.rb$/)
26
+ begin
27
+ load fname
28
+ rescue Exception => e
29
+ # stub
30
+ puts "Exception while loading #{fname}"
31
+ puts e.inspect
32
+ end
33
+ else
34
+ puts "Ignored: #{fname}"
35
+ end
36
+ end
37
+ }
38
+ }
39
+
40
+ puts "[xmlrpc] found #{RPCHandles.constants.length} constants."
41
+ RPCHandles.constants.each { |handler|
42
+ if RPCHandles.const_get(handler).is_a?(Class)
43
+ @core.add_handler(RPC_PREFIX, RPCHandles.const_get(handler).new)
44
+ end
45
+ }
46
+ end
47
+
48
+ def main_loop
49
+ load_all_handles
50
+
51
+ @server.mount("/", @core)
52
+ @server.start
53
+
54
+ puts "[xmlrpc] XMLRPC started"
55
+ end
56
+ end
57
+
58
+ class DummyRPCServer
59
+ def initialize bind_host, bind_port; end
60
+
61
+ def load_all_handles; end
62
+
63
+ def main_loop
64
+ puts "[xmlrpc] DummyRPCServer started"
65
+ end
66
+ end
67
+
68
+ class NullRPCServer; end
69
+ end
data/rbitter.gemspec ADDED
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rbitter/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rbitter"
9
+ spec.version = Rbitter::VERSION
10
+ spec.authors = ["Nidev Plontra"]
11
+ spec.email = ["nidev.plontra@gmail.com"]
12
+ spec.summary = %q{Rbitter is a Twitter client specialized in archiving}
13
+ spec.description = %q{Rbitter archives all tweets appeared on user streaming using ActiveRecord. XMLRPC is used to serve archived tweets and useful features}
14
+ spec.homepage = "https://github.com/nidev/rbitter"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+
23
+ spec.add_dependency 'twitter', '~> 5.14'
24
+ spec.add_dependency 'json', '~> 1.7'
25
+ spec.add_dependency 'ripl', '~> 0.7'
26
+ spec.add_dependency 'activerecord', '~> 4.0'
27
+
28
+ if RUBY_PLATFORM == 'java'
29
+ spec.platform = 'java'
30
+
31
+ spec.add_dependency 'activerecord-jdbc-adapter', '~> 1.3'
32
+ spec.add_dependency 'jdbc-sqlite3', '~> 3.8'
33
+ spec.add_dependency 'jdbc-mysql', '~> 5.1'
34
+ spec.add_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.3'
35
+ spec.add_dependency 'activerecord-jdbcmysql-adapter', '~> 1.3'
36
+ else
37
+ spec.platform = 'ruby'
38
+
39
+ spec.add_dependency 'sqlite3', '~> 1.3'
40
+ spec.add_dependency 'mysql2', '~> 0.3'
41
+ spec.add_dependency 'activerecord-mysql2-adapter', '~> 0.0.3'
42
+ end
43
+
44
+ spec.add_development_dependency "bundler", "~> 1.6"
45
+ spec.add_development_dependency "rake", "~> 10.0"
46
+ end
data/spec/config/.keep ADDED
File without changes
@@ -0,0 +1,33 @@
1
+ {
2
+ "twitter": {
3
+ "consumer_key": "",
4
+ "consumer_secret": "",
5
+ "access_token": "",
6
+ "access_token_secret": ""
7
+ },
8
+ "activerecord": "sqlite3",
9
+ "sqlite3": {
10
+ "dbfile": "rbitter.sqlite"
11
+ },
12
+ "mysql2": {
13
+ "host": "localhost",
14
+ "port": 3306,
15
+ "dbname": "archive",
16
+ "username": "",
17
+ "password": ""
18
+ },
19
+ "media_downloader": {
20
+ "cacert_path": "/cacerts/cacert.pem",
21
+ "download_dir": "imgs/"
22
+ },
23
+ "xmlrpc": {
24
+ "enable": true,
25
+ "bind_host": "0.0.0.0",
26
+ "bind_port": 1400,
27
+ "auth": {
28
+ "username": "username",
29
+ "password": "password"
30
+ },
31
+ "handles": ["/path/to/handles"]
32
+ }
33
+ }
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbitter/arcserver"
4
+ require "rbitter/streaming"
5
+ require "rbitter/xmlrpcd/xmlrpcd"
6
+
7
+ describe Rbitter::ArcServer do
8
+ it 'is presented' do
9
+ expect(Rbitter::ArcServer).to be_a(Class)
10
+ end
11
+
12
+ context 'With dummy implementations, ' do
13
+ before(:all) do
14
+ Rbitter.bootstrap(['configure'])
15
+ expect(File.file?('config.json')).to be(true)
16
+ end
17
+
18
+ it 'successfully returns from main_loop' do
19
+ Rbitter.config_initialize
20
+
21
+ arcserver = Rbitter::ArcServer.new(Rbitter::DummyRPCServer)
22
+ arcserver.main_loop(Rbitter::DummyStreamClient)
23
+ end
24
+
25
+ after(:all) do
26
+ File.delete('config.json') if File.exist?('config.json')
27
+ File.delete('rbitter.sqlite') if File.exist?('rbitter.sqlite')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ require "rbitter/console"
3
+
4
+ describe Rbitter::Console do
5
+ # TODO: Perform test...
6
+ it 'is presented' do
7
+ expect(Rbitter::Console).to be_a(Class)
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbitter/default/config_json"
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require "rbitter/dlthread"
3
+
4
+ describe Rbitter::DLThread do
5
+ it 'is presented' do
6
+ expect(Rbitter::DLThread).to be_a(Class)
7
+ end
8
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ require "rbitter"
4
+
5
+ describe Rbitter do
6
+ it 'has env_reset function and clears Rbitter.env,' do
7
+ Rbitter.env_reset
8
+ expect(Rbitter.env).to be_a(Hash)
9
+ expect(Rbitter.env.length).to be(0)
10
+ end
11
+
12
+ context 'when config.json is not installed,' do
13
+ it 'fails on loading' do
14
+ expect{Rbitter.config_initialize}.to raise_error(Rbitter::ConfigFileError)
15
+ end
16
+ end
17
+
18
+ context 'when path to config.json is invalid,' do
19
+ it 'fals on loading' do
20
+ expect{Rbitter.config_initialize("/silly/dummy/.")}.to raise_error(Rbitter::ConfigFileError)
21
+ end
22
+ end
23
+
24
+
25
+ context 'when default config.json is installed,' do
26
+ before(:all) do
27
+ Rbitter.bootstrap(['configure'])
28
+ expect(File.file?('config.json')).to be(true)
29
+ end
30
+
31
+ it 'loads configuration successfully with autodetection' do
32
+ expect{Rbitter.config_initialize}.to_not raise_error
33
+ expect(Rbitter.env.length > 0).to be(true)
34
+ end
35
+
36
+ it 'loads configuration successfully with given config.json path' do
37
+ expect{Rbitter.config_initialize('config.json')}.to_not raise_error
38
+ expect(Rbitter.env.length > 0).to be(true)
39
+ end
40
+
41
+ it 'checks that Rbitter.env returns Hash' do
42
+ expect{Rbitter.config_initialize}.to_not raise_error
43
+ expect(Rbitter.env).to be_a(Hash)
44
+ end
45
+
46
+ it 'checks that Rbitter[] works' do
47
+ expect{Rbitter.config_initialize}.to_not raise_error
48
+ expect(Rbitter["twitter"]).to be_a(Hash)
49
+ end
50
+
51
+ after(:all) do
52
+ File.delete('config.json')
53
+ end
54
+ end
55
+
56
+ context 'when env_validator validates loaded configuration' do
57
+ # TODO: Perform test with spec/config/default.json
58
+ # TODO: Adding configuration validator on env.rb
59
+ end
60
+
61
+ # TODO: Perform test with spec/config/default.json
62
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require "rbitter/libtwitter_connection_override"
3
+
4
+ describe Rbitter do
5
+ it 'overrides twitter gem' do
6
+ expect(Twitter::Streaming::Connection::MODIFIED).to be(true)
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ require "rbitter/records"
3
+
4
+ describe Rbitter::Record do
5
+ # TODO: Perform test...
6
+ it 'has ActiveRecord class named Record' do
7
+ expect(Rbitter::Record).to be_a(Class)
8
+ end
9
+
10
+ it 'has supportive module of ActiveRecord' do
11
+ expect(ARSupport).to be_a(Module)
12
+ end
13
+ end