mcjsonapi 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fe76057b271dd85eaaa0cb96984b526c1a3a3667
4
+ data.tar.gz: 3fc0de21bd28dac3e9bf9bced037c3dab98baa6b
5
+ SHA512:
6
+ metadata.gz: c11780a9132eed9cdae1da8241930071fd87835efb5d8411e4ce1d30dc2aba18793a5c69d978b9a0ba87448bd60681b7983ce4520ab9c8f7cf8f821573467cbb
7
+ data.tar.gz: fc3a4dd31508ccbe298e3f9328b45336b69cb57044b8e277ec685230ef1e726b9f2e56a19ae658213c5e9191e2c78c04a2dc091af05c5f759292bdd866470a54
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - 2.1.0
6
+ - 2.0.0
7
+ - 1.9.3
8
+
9
+ script: 'bundle exec rake'
10
+
11
+ notifications:
12
+ email:
13
+ recipients:
14
+ - elomatreb@googlemail.com
15
+
16
+ on_failure: change
17
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mcjsonapi.gemspec
4
+ gemspec
@@ -0,0 +1,9 @@
1
+ guard "rspec" do
2
+ watch(%r{^lib/(.+).rb$}) do |m|
3
+ "spec/#{m[1]}_spec.rb"
4
+ end
5
+
6
+ watch(%r{^spec/(.+).rb$}) do |m|
7
+ "spec/#{m[1]}.rb"
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ole B. <elomatreb@googlemail.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # mcjsonapi [![Build Status](https://api.travis-ci.org/elomatreb/mcjsonapi.svg?branch=dev)](https://travis-ci.org/elomatreb/mcjsonapi)
2
+
3
+ This rubygem provides an easy way to interact with a [Minecraft](https://minecraft.net) ([bukkit](https://bukkit.org/)) server running the [JSONAPI plugin](https://github.com/alecgorge/jsonapi). It uses the v2-API, so it has full support for permissions.
4
+
5
+ Calling multiple methods is not yet implemented, but is planned for the 1.0 release.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's `Gemfile`:
10
+ ```
11
+ gem 'mcjsonapi', '~> 0.9.0'
12
+ ```
13
+ (Don't forget to run `$ bundle install`)
14
+
15
+ Or install it manually:
16
+ ```
17
+ $ gem install mcjsonapi
18
+ ```
19
+ ## Usage
20
+ ```ruby
21
+ require "mcjsonapi"
22
+
23
+ # Create a new API instance
24
+ api = Mcjsonapi::API.new username: "username", password: "password", host: "localhost", port: 20059
25
+ # localhost:20059 is assumed as default host/port
26
+
27
+ # Call a single method
28
+ api.call "server.version"
29
+ # => "git-Bukkit-1.6.4-R2.0-b2918jnks (MC: 1.6.4)"
30
+
31
+ # Call a method with arguments
32
+ api.call { name: "players.online.send_message", arguments: ["Player", "Hello World"] }
33
+
34
+ # Generate a call key
35
+ api.generate_key("server.version")
36
+ # => "8433478ce05d331c743ff69cad00792039396d222d304545bd40f2ccecd714c9"
37
+
38
+ # Calling multiple methods at once is not yet implemented.
39
+ ```
40
+
41
+ ## License
42
+
43
+ This project is available under the permissive [MIT license](http://opensource.org/licenses/MIT). (See [LICENSE.md](LICENSE.md) for details).
44
+ Any type of contribution is appreciated.
@@ -0,0 +1,8 @@
1
+ require "rspec/core/rake_task"
2
+ require "bundler/gem_tasks"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |task|
5
+ task.rspec_opts = ['--color', '--format', 'documentation']
6
+ end
7
+
8
+ task :default => :spec
@@ -0,0 +1,9 @@
1
+ # Require files
2
+ ["api", "version"].each do |f|
3
+ require "mcjsonapi/#{f}"
4
+ end
5
+
6
+ # Require gems
7
+ ["digest/sha2", "net/http", "json"].each do |g|
8
+ require g
9
+ end
@@ -0,0 +1,56 @@
1
+ module Mcjsonapi
2
+ class API
3
+ attr_reader :host, :port, :username
4
+
5
+ def initialize(options = {})
6
+ raise ArgumentError, "Username and password must be given." if options[:username].nil? || options[:password].nil?
7
+
8
+ @host = options[:host] || "localhost"
9
+ @port = options[:port] || 20059
10
+
11
+ @username = options[:username]
12
+ @password = options[:password]
13
+ end
14
+
15
+ def generate_key(method)
16
+ Digest::SHA256.hexdigest @username+method+@password
17
+ end
18
+
19
+ def call(options = {})
20
+
21
+ if options.is_a? String
22
+ if options.empty?
23
+ raise ArgumentError, "A method must be given."
24
+ else
25
+ options = { name: options }
26
+ end
27
+ elsif options.is_a? Hash
28
+ if options.empty? || options[:name].nil?
29
+ raise ArgumentError, "A method must be given."
30
+ end
31
+ else
32
+ raise ArgumentError, "A method must be given."
33
+ end
34
+
35
+ options[:username] = @username
36
+ options[:key] = generate_key(options[:name])
37
+
38
+ data = URI::encode JSON.generate(options)
39
+
40
+ response = Net::HTTP.get_response URI("http://#{@host}:#{@port}/api/2/call?json=#{data}")
41
+
42
+ raise APIError, "The API responded with an HTTP error." unless response.is_a? Net::HTTPOK
43
+
44
+ response_data = JSON.parse(response.body)[0]
45
+
46
+ if response_data["is_success"]
47
+ return response_data["success"]
48
+ else
49
+ raise APIError, "The API raised an error: #{response_data["error"]["message"]} (Code #{response_data["error"]["code"]})"
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ class APIError < StandardError; end
56
+ end
@@ -0,0 +1,3 @@
1
+ module Mcjsonapi
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mcjsonapi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mcjsonapi"
8
+ spec.version = Mcjsonapi::VERSION
9
+ spec.authors = ["elomatreb"]
10
+ spec.email = ["elomatreb@googlemail.com"]
11
+ spec.summary = "A gem to interact with a Minecraft server running the JSONAPI plugin."
12
+ spec.description = <<-EOF
13
+ A gem to interact with a Minecraft (bukkit) server that has the
14
+ {JSONAPI plugin}[https://github.com/alecgorge/jsonapi] installed. It supports
15
+ calling single and multiple methods.
16
+ EOF
17
+ spec.homepage = "https://github.com/elomatreb/mcjsonapi"
18
+ spec.license = "MIT"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.6"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-rspec"
30
+ spec.add_development_dependency "webmock"
31
+ end
@@ -0,0 +1,161 @@
1
+ require "spec_helper"
2
+
3
+ describe "Mcjsonapi:" do
4
+ let(:username) { "username" }
5
+ let(:password) { "password" }
6
+ let(:version) { 'git-Bukkit-1.6.4-R2.0-b2918jnks (MC: 1.6.4)' }
7
+
8
+ describe "new instance" do
9
+ describe "with invalid information" do
10
+ describe "without any information" do
11
+ it "should raise an error" do
12
+ expect { Mcjsonapi::API.new }.to raise_error(ArgumentError)
13
+ end
14
+ end
15
+
16
+ describe "without password" do
17
+ it "should raise an error" do
18
+ expect { Mcjsonapi::API.new username: username }.to raise_error(ArgumentError)
19
+ end
20
+ end
21
+
22
+ describe "without username" do
23
+ it "should raise an error" do
24
+ expect { Mcjsonapi::API.new password: password }.to raise_error(ArgumentError)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "with valid information" do
30
+ let(:api) { Mcjsonapi::API.new username: username, password: password }
31
+
32
+ it "should use correct username" do
33
+ expect(api.username).to eq username
34
+ end
35
+
36
+ describe "with no host given" do
37
+ let(:api) { Mcjsonapi::API.new username: username, password: password }
38
+
39
+ it "should assume localhost as default" do
40
+ expect(api.host).to eq "localhost"
41
+ end
42
+ end
43
+
44
+ describe "with host given" do
45
+ let(:api) { Mcjsonapi::API.new host: "api.example.com", username: username, password: password }
46
+
47
+ it "should use the given host" do
48
+ expect(api.host).to eq "api.example.com"
49
+ end
50
+ end
51
+
52
+ describe "with no port given" do
53
+ let(:api) { Mcjsonapi::API.new username: username, password: password }
54
+
55
+ it "should assume 20059 as default" do
56
+ expect(api.port).to eq 20059
57
+ end
58
+ end
59
+
60
+ describe "with port given" do
61
+ let(:api) { Mcjsonapi::API.new port: 31337, username: username, password: password }
62
+
63
+ it "should use the given port" do
64
+ expect(api.port).to eq 31337
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "key generation" do
71
+ let(:api) { Mcjsonapi::API.new username: username, password: password }
72
+
73
+ describe "with no method parameter" do
74
+ it "should raise an error" do
75
+ expect { api.generate_key }.to raise_error(ArgumentError)
76
+ end
77
+ end
78
+
79
+ describe "with correct parameters" do
80
+ it "should return a valid key" do
81
+ expect(api.generate_key "server.version").to eq Digest::SHA256.hexdigest(username+"server.version"+password)
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "request" do
87
+ let(:api) { Mcjsonapi::API.new username: username, password: password }
88
+
89
+ describe "with no parameters" do
90
+ it "should raise an error" do
91
+ expect { api.call }.to raise_error(ArgumentError)
92
+ end
93
+ end
94
+
95
+ describe "with empty (string) parameters" do
96
+ it "should raise an error" do
97
+ expect { api.call "" }.to raise_error(ArgumentError)
98
+ end
99
+ end
100
+
101
+ describe "with empty (hash) parameters" do
102
+ it "should raise an error" do
103
+ expect { api.call {} }.to raise_error(ArgumentError)
104
+ end
105
+ end
106
+
107
+ describe "with single string parameter" do
108
+ describe "with no existing method" do
109
+ it "should raise an error" do
110
+ expect { api.call "server.ersion" }.to raise_error(Mcjsonapi::APIError)
111
+ end
112
+ end
113
+
114
+ describe "with an existing method" do
115
+ it "should return valid data" do
116
+ expect(api.call "server.version").to eq version
117
+ end
118
+ end
119
+ end
120
+
121
+ describe "with hash parameters" do
122
+ describe "with no existing method" do
123
+ it "should raise an error" do
124
+ expect { api.call name: "server.ersion" }.to raise_error(Mcjsonapi::APIError)
125
+ end
126
+ end
127
+
128
+ describe "with an existing method" do
129
+ describe "without arguments" do
130
+ it "should return valid data" do
131
+ expect(api.call name: "server.version").to eq version
132
+ end
133
+ end
134
+
135
+ describe "with invalid arguments" do
136
+ it "should raise an error" do
137
+ expect { api.call name: "chat.broadcast", arguments: [] }.to raise_error(Mcjsonapi::APIError)
138
+ end
139
+ end
140
+
141
+ describe "with valid arguments" do
142
+ it "should return valid data" do
143
+ expect(api.call name: "chat.broadcast", arguments: ["Hello World"]).to eq 1
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ describe "with host timeout" do
150
+ it "should raise an exception" do
151
+ expect { api.call "players.online.limit" }.to raise_error(Timeout::Error)
152
+ end
153
+ end
154
+
155
+ describe "with HTTP error from API" do
156
+ it "should raise an exception" do
157
+ expect { api.call "players.online" }.to raise_error(Mcjsonapi::APIError)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,27 @@
1
+ require "mcjsonapi"
2
+ require "digest/sha2"
3
+ require "webmock/rspec"
4
+
5
+ WebMock.disable_net_connect!
6
+
7
+ RSpec.configure do |config|
8
+ config.before :each do
9
+ stub_request(:any, "http://localhost:20059/api/2/call?json=%7B%22name%22:%22server.version%22,%22username%22:%22username%22,%22key%22:%228433478ce05d331c743ff69cad00792039396d222d304545bd40f2ccecd714c9%22%7D").
10
+ to_return(status: 200, body: '[{"result":"success","is_success":true,"source":"server.version","success":"git-Bukkit-1.6.4-R2.0-b2918jnks (MC: 1.6.4)"}]', headers: {})
11
+
12
+ stub_request(:any, 'http://localhost:20059/api/2/call?json=%7B%22name%22:%22server.ersion%22,%22username%22:%22username%22,%22key%22:%2280e215e432f1712033c05f19d1aa25809f076f33e109459d74c3638f2054f9dd%22%7D').
13
+ to_return(status: 200, body: '[{"result":"error","is_success":false,"error":{"message":"The method \'server.ersion\' does not exist!","code":7},"source":"server.ersion"}]', headers: {})
14
+
15
+ stub_request(:any, 'http://localhost:20059/api/2/call?json=%7B%22name%22:%22players.online%22,%22username%22:%22username%22,%22key%22:%22a512138b40aa90e62577a05b22e0a8ef1e3642603766c5f175a91b491143ec0a%22%7D').
16
+ to_return(status: 500, body: "")
17
+
18
+ stub_request(:any, 'http://localhost:20059/api/2/call?json=%7B%22name%22:%22players.online.limit%22,%22username%22:%22username%22,%22key%22:%229e13123716483673352415a76bc891649148043111cbffa3374ee192d26e8e34%22%7D').
19
+ to_timeout
20
+
21
+ stub_request(:any, 'http://localhost:20059/api/2/call?json=%7B%22name%22:%22chat.broadcast%22,%22arguments%22:%5B%5D,%22username%22:%22username%22,%22key%22:%2209cb37400a6951f6f69ac62c736c62e8646292a100585bf4412a836b4c507407%22%7D').
22
+ to_return(status: 200, body: '[{"result":"error","is_success":false,"error":{"message":"Caught exception: java.lang.Exception: Incorrect number of args: gave 0 ([]), expected 1 for method chat.broadcast\n\tat com.alecgorge.minecraft.jsonapi.dynamic.Caller.call(Caller.java:64)\n\tat com.alecgorge.minecraft.jsonapi.api.v2.JSONResponse.serveAPICall(JSONResponse.java:130)\n\tat com.alecgorge.minecraft.jsonapi.api.v2.JSONResponse.getJSONObject(JSONResponse.java:73)\n\tat com.alecgorge.minecraft.jsonapi.api.v2.APIv2Handler.call(APIv2Handler.java:83)\n\tat com.alecgorge.minecraft.jsonapi.api.v2.APIv2Handler.serve(APIv2Handler.java:51)\n\tat com.alecgorge.minecraft.jsonapi.JSONServer.serve(JSONServer.java:257)\n\tat com.alecgorge.minecraft.jsonapi.NanoHTTPD$HTTPSession.run(NanoHTTPD.java:553)\n\tat java.lang.Thread.run(Thread.java:744)\n","code":6},"source":"chat.broadcast"}]') # This is ugly. Like, really ugly.
23
+
24
+ stub_request(:any, 'http://localhost:20059/api/2/call?json=%7B%22name%22:%22chat.broadcast%22,%22arguments%22:%5B%22Hello%20World%22%5D,%22username%22:%22username%22,%22key%22:%2209cb37400a6951f6f69ac62c736c62e8646292a100585bf4412a836b4c507407%22%7D').
25
+ to_return(status: 200, body: '[{"result":"success","is_success":true,"source":"chat.broadcast","success":1}]')
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mcjsonapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - elomatreb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: " A gem to interact with a Minecraft (bukkit) server that has the
98
+ \n {JSONAPI plugin}[https://github.com/alecgorge/jsonapi] installed. It supports\n
99
+ \ calling single and multiple methods.\n"
100
+ email:
101
+ - elomatreb@googlemail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - Guardfile
110
+ - LICENSE.md
111
+ - README.md
112
+ - Rakefile
113
+ - lib/mcjsonapi.rb
114
+ - lib/mcjsonapi/api.rb
115
+ - lib/mcjsonapi/version.rb
116
+ - mcjsonapi.gemspec
117
+ - spec/mcjsonapi_spec.rb
118
+ - spec/spec_helper.rb
119
+ homepage: https://github.com/elomatreb/mcjsonapi
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.2.2
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: A gem to interact with a Minecraft server running the JSONAPI plugin.
143
+ test_files:
144
+ - spec/mcjsonapi_spec.rb
145
+ - spec/spec_helper.rb