rbitter 0.1.2-java

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.
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