weskit 0.0.2

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
+ .bundle
2
+ *.gem
3
+ .redcar/
4
+ Gemfile.lock
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/README ADDED
@@ -0,0 +1,2 @@
1
+ Pls do me a favor and do not look at sources if you dont have to. Thx!
2
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/weskit.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'weskit/lobby'
2
+ require 'weskit/version'
3
+ require 'weskit/wml'
@@ -0,0 +1,11 @@
1
+ module Weskit
2
+ module Lobby
3
+ end
4
+ end
5
+
6
+ directory = File.dirname __FILE__
7
+ files = File.join directory, 'lobby', '*.rb'
8
+
9
+ Dir[files].each do |file|
10
+ require file
11
+ end
@@ -0,0 +1,85 @@
1
+ require 'weskit/wml'
2
+
3
+ module Weskit::Lobby
4
+ require 'socket'
5
+ require 'stringio'
6
+ require 'zlib'
7
+
8
+ class Bot
9
+ def initialize nickname, options = {}
10
+ defaults = {
11
+ :debug => false,
12
+ :port => 15000,
13
+ :server => 'server.wesnoth.org',
14
+ :version => '1.10.0'
15
+ }
16
+ options = defaults.merge options
17
+
18
+ @server = options[:server]
19
+ @port = options[:port]
20
+ @version = options[:version]
21
+
22
+ @reader = Weskit::WML::Reader.new
23
+ @nickname = nickname
24
+ end
25
+
26
+ def connect_and &operations
27
+ @socket = TCPSocket.new @server, @port
28
+ basic_communication
29
+ response = read_wml
30
+ @socket.close
31
+
32
+ @socket = TCPSocket.new response.redirect[:host], response.redirect[:port]
33
+ basic_communication
34
+
35
+ raise "Server send node other than 'mustlogin'" if read_wml.mustlogin.nil?
36
+ send_wml 'login', :selective_ping => 1, :username => @nickname
37
+ raise "Server send node other than 'join_lobby'" if read_wml.join_lobby.nil?
38
+
39
+ result = yield self
40
+
41
+ sleep 3
42
+ @socket.close
43
+ result
44
+ end
45
+
46
+ def read_wml
47
+ wml = @reader.read_str read_str
48
+ puts "\e[0;33mRecieve MWL\e[0m:\n#{wml}" if @debug
49
+ wml
50
+ end
51
+
52
+ def send_wml node, contents = {}
53
+ wml = @reader.read_hsh({node => contents}).to_s
54
+ puts "\e[0;32mSend MWL\e[0m:\n#{wml}" if @debug
55
+ send_str wml
56
+ end
57
+
58
+ private
59
+
60
+ def basic_communication
61
+ handshake
62
+ raise "Server send node other than 'version'" if read_wml.version.empty?
63
+ send_wml 'version', :version => @version
64
+ end
65
+
66
+ def handshake
67
+ @socket.send "\x00" * 4, 0
68
+ @socket.read 4
69
+ end
70
+
71
+ def read_str
72
+ msg_size = @socket.read(4).unpack('N').first
73
+ msg_data = @socket.read(msg_size)
74
+ Zlib::GzipReader.new(StringIO.new(msg_data)).read
75
+ end
76
+
77
+ def send_str msg
78
+ gzw = Zlib::GzipWriter.new StringIO.new
79
+ gzw.write msg.to_s
80
+ gzm = gzw.close
81
+ size = [gzm.size].pack('N')
82
+ @socket.send(size + gzm.string, 0)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,3 @@
1
+ module Weskit::Lobby
2
+ class BotError < StandardError ; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Weskit
2
+ VERSION = "0.0.2"
3
+ end
data/lib/weskit/wml.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Weskit
2
+ module WML
3
+ end
4
+ end
5
+
6
+ directory = File.dirname __FILE__
7
+ files = File.join directory, 'wml', '*.rb'
8
+
9
+ Dir[files].each do |file|
10
+ require file
11
+ end
@@ -0,0 +1,76 @@
1
+ module Weskit::WML
2
+ class Node
3
+ FALSE_ATTR_VALS = ["no", "false", "off", "uninitialized"]
4
+ TRUE_ATTR_VALS = ["yes", "true", "on"]
5
+
6
+ attr_reader :name, :parent
7
+
8
+ def add element
9
+ return false unless element.kind_of? Node
10
+ @nodes << element ; true
11
+ end
12
+
13
+ def self.create name = '', parent = nil
14
+ new name, parent
15
+ end
16
+
17
+ def initialize name = '', parent = nil
18
+ name = normalize name
19
+ name = (name.empty?) ? 'root' : name
20
+ raise(NodeError, "Node name can consist only of '#{StringExtensions::VALID_CHARS}'") unless name =~ /^#{StringExtensions::VALID_CHARS}+$/
21
+ raise(NodeError, "Attempt to set inproper parent node") unless parent.kind_of? Node or parent == nil
22
+ @attributes, @name, @nodes, @parent = {}, name, [], parent
23
+ end
24
+
25
+ def method_missing method
26
+ nodes = @nodes.select {|node| node.name == normalize(method)}
27
+ NodeArray.new.replace nodes
28
+ end
29
+
30
+ def to_ary
31
+ end
32
+
33
+ def to_s indent_width = 1
34
+ indent_width -= 1 if @name == 'root'
35
+
36
+ base_indentation = " " * 4
37
+ contents_indentation = base_indentation * indent_width
38
+ closing_tag_indentation = base_indentation * (indent_width > 0 ? indent_width - 1 : 0)
39
+
40
+ attr_str = @attributes.keys.sort.inject('') {|string, key| string << "#{contents_indentation}#{key}=\"#{@attributes[key]}\"\n"}
41
+ node_str = @nodes.inject('') {|string, node| string << "#{contents_indentation}#{node.to_s(indent_width + 1)}\n"}
42
+
43
+ (@name == 'root') ? "#{attr_str}#{node_str}" : "[#{name}]\n#{attr_str}#{node_str}#{closing_tag_indentation}[/#{name}]"
44
+ end
45
+
46
+ def [] key
47
+ value = @attributes[normalize key]
48
+
49
+ if FALSE_ATTR_VALS.include? value then false
50
+ elsif TRUE_ATTR_VALS.include? value then true
51
+ else value
52
+ end
53
+ end
54
+
55
+ def []= key, value
56
+ key, value = normalize(key), value.to_s
57
+
58
+ # This one can cause problems as looks there is no escaping strategy on the server side
59
+ #unless value == '"'
60
+ # single_quotes, double_quotes = value.scan('"').size, value.scan('""').size
61
+ # if (single_quotes > 0) and ((double_quotes == 0) or (single_quotes.to_f % double_quotes.to_f > 0))
62
+ # raise(NodeError, "Found unescaped double quotes inside attribute value")
63
+ # end
64
+ # @attributes[key] = value.gsub('"', '""')
65
+ #end
66
+
67
+ @attributes[key] = value
68
+ end
69
+
70
+ private
71
+
72
+ def normalize name
73
+ name.to_s.strip
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,25 @@
1
+ module Weskit::WML
2
+ class NodeArray < Array
3
+ def [] key
4
+ unless key.is_a? Integer
5
+ return first[key] unless empty?
6
+ nil
7
+ else
8
+ super key
9
+ end
10
+ end
11
+
12
+ def []= key, value
13
+ (key.is_a? Integer) ? super(key, value) : (first[key] = value) unless empty?
14
+ end
15
+
16
+ def method_missing method
17
+ nodes = inject([]) {|array, element| array + element.send(method) if element.kind_of? Node}
18
+ NodeArray.new.replace nodes
19
+ end
20
+
21
+ def to_wml
22
+ inject('') {|string, item| string << "#{item}\n" if item.kind_of? Node}
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Weskit::WML
2
+ class NodeError < StandardError ; end
3
+ end
@@ -0,0 +1,67 @@
1
+ module Weskit::WML
2
+ class Reader
3
+ def read_hsh hash, name = '', parent = nil
4
+ current_node = Node.new name, parent
5
+ hash.each {|key,val| (val.kind_of? Hash) ? current_node.add(read_hsh(val, key, current_node)) : current_node[key] = val}
6
+ current_node
7
+ end
8
+
9
+ def read_str string
10
+ parse string
11
+ end
12
+
13
+ def read_uri uri
14
+ require 'open-uri'
15
+ require 'stringio'
16
+ require 'zlib'
17
+
18
+ begin
19
+ content = open(uri) {|u| u.read}
20
+ rescue
21
+ raise ReaderError, "Failed to open specified uri"
22
+ ensure
23
+ content = Zlib::GzipReader.new(StringIO.new(content)).read rescue content
24
+ end
25
+
26
+ parse content
27
+ end
28
+
29
+ private
30
+
31
+ def parse content
32
+ current_node, node_stack = Node.new, []
33
+ multiline_mode, multiline_name, multiline_value = false, '', []
34
+
35
+ content.strip.each_line do |line|
36
+ line = line.chomp.extend StringExtensions
37
+
38
+ if multiline_mode
39
+ if line.end_of_attr?
40
+ multiline_value << line.rstrip.chomp('"')
41
+ multiline_value = multiline_value.join("\n")
42
+ current_node[multiline_name] = multiline_value
43
+ multiline_mode, multiline_name, multiline_value = false, '', []
44
+ else
45
+ multiline_value << line
46
+ end
47
+ elsif line.attribute?
48
+ if line.multiline_attr?
49
+ multiline_mode, multiline_name = true, line.attribute_name
50
+ multiline_value << line.attribute_value
51
+ else
52
+ current_node[line.attribute_name] = line.attribute_value
53
+ end
54
+ elsif line.opening_tag?
55
+ node_stack.push current_node
56
+ current_node = Node.create line.tag_name, node_stack.last
57
+ elsif line.closing_tag?
58
+ raise(ReaderError, "Opening tag '#{current_node.name}' does not match closing tag '#{line.tag_name}'") if current_node.name != line.tag_name
59
+ node_stack.last.add current_node
60
+ current_node = node_stack.pop
61
+ end
62
+ end
63
+
64
+ current_node
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ module Weskit::WML
2
+ class ReaderError < StandardError ; end
3
+ end
@@ -0,0 +1,59 @@
1
+ module Weskit::WML
2
+ module StringExtensions
3
+ VALID_CHARS = '[A-Za-z0-9_]'
4
+
5
+ def attribute_name
6
+ @values[0]
7
+ end
8
+
9
+ def attribute_value
10
+ @values[1]
11
+ end
12
+
13
+ def multiline_attr?
14
+ return true if include?('="') and (last_character != '"')
15
+ false
16
+ end
17
+
18
+ def end_of_attr?
19
+ return true if (last_character == '"')
20
+ false
21
+ end
22
+
23
+ def last_character
24
+ rstrip[-1,1]
25
+ end
26
+
27
+ def tag_name
28
+ @values[0]
29
+ end
30
+
31
+ def opening_tag?
32
+ wml_check(/^\[(#{VALID_CHARS}+?)\]$/)
33
+ end
34
+
35
+ def closing_tag?
36
+ wml_check(/^\[\/(#{VALID_CHARS}+?)\]$/)
37
+ end
38
+
39
+ def attribute?
40
+ # If there is unallowed char in fron of '=' line wont be considereda as an attribute
41
+ # Multiline attributes need to have double quotes next to equal sign
42
+ wml_check(/^(#{VALID_CHARS}+?)="?(.+?)"?$/)
43
+ end
44
+
45
+ private
46
+
47
+ def wml_check expression
48
+ matches = self.strip.match expression
49
+
50
+ if matches
51
+ @values = [matches[1], matches[2]]
52
+ return true
53
+ else
54
+ @values = [nil, nil]
55
+ return false
56
+ end
57
+ end
58
+ end
59
+ end
data/weskit.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'weskit/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'weskit'
7
+ s.version = Weskit::VERSION
8
+ s.authors = ['f6p']
9
+ s.email = ['filip.pyda@gmail.com']
10
+ s.homepage = 'https://github.com/f6p/weskit'
11
+ s.summary = 'Ruby utilies for BfW'
12
+ s.description = 'Pls do me a favor and do not look at sources if you dont have to. Thx!'
13
+
14
+ # s.rubyforge_project = 'weskit'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency 'rspec'
23
+ # s.add_runtime_dependency 'rest-client'
24
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weskit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - f6p
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-15 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: Pls do me a favor and do not look at sources if you dont have to. Thx!
22
+ email:
23
+ - filip.pyda@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - README
34
+ - Rakefile
35
+ - lib/weskit.rb
36
+ - lib/weskit/lobby.rb
37
+ - lib/weskit/lobby/bot.rb
38
+ - lib/weskit/lobby/bot_error.rb
39
+ - lib/weskit/version.rb
40
+ - lib/weskit/wml.rb
41
+ - lib/weskit/wml/node.rb
42
+ - lib/weskit/wml/node_array.rb
43
+ - lib/weskit/wml/node_error.rb
44
+ - lib/weskit/wml/reader.rb
45
+ - lib/weskit/wml/reader_error.rb
46
+ - lib/weskit/wml/string_extensions.rb
47
+ - weskit.gemspec
48
+ homepage: https://github.com/f6p/weskit
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
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
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.11
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Ruby utilies for BfW
81
+ test_files: []
82
+