beeline-rb 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eb82e60fd4d94693d41b751a344ce3ec7cbe88e2b8a9322f52ca7a987d0ca762
4
+ data.tar.gz: 5c3996593694fd9440f0f83ab248225c0b187cc5d86231ed975d218850107389
5
+ SHA512:
6
+ metadata.gz: 4467d4566ea3e550c4b6406fe6f3e8a44d0b5f1379a0a59b25c2c2008a656cf49863086f875bd75ee185f8f48ec5362946c39e3f64e4700433ee30d24c96aace
7
+ data.tar.gz: 94bc32b5c17add1a54073a622818b705210beca53b9ce94aaf93957f852e5e60af0b164426dfa90bc064c7028afc545846f4e45f14f0109fe3e989b02d5c79c5
@@ -0,0 +1,58 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
57
+ config.yml
58
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,41 @@
1
+ CC0 1.0 Universal (CC0 1.0)
2
+ Public Domain Dedication
3
+ https://creativecommons.org/publicdomain/zero/1.0/
4
+
5
+ This is a human-readable summary of the Legal Code:
6
+ https://creativecommons.org/publicdomain/zero/1.0/legalcode
7
+
8
+ Disclaimer
9
+
10
+ The Commons Deed is not a legal instrument. It is simply a handy reference for
11
+ understanding the CC0 Legal Code, a human-readable expression of some of its key
12
+ terms. Think of it as the user-friendly interface to the CC0 Legal Code beneath.
13
+ This Deed itself has no legal value, and its contents do not appear in CC0.
14
+ Creative Commons is not a law firm and does not provide legal services.
15
+ Distributing, displaying, or linking to this Commons Deed does not create an
16
+ attorney-client relationship.
17
+
18
+ Creative Commons has not verified the copyright status of any work to which CC0
19
+ has been applied. CC makes no warranties about any work or its copyright status
20
+ in any jurisdiction, and disclaims all liability for all uses of any work.
21
+
22
+ No Copyright
23
+
24
+ The person who associated a work with this deed has dedicated the work to the
25
+ public domain by waiving all of his or her rights to the work worldwide under
26
+ copyright law, including all related and neighboring rights, to the extent
27
+ allowed by law.
28
+
29
+ You can copy, modify, distribute and perform the work, even for commercial
30
+ purposes, all without asking permission. See Other Information below.
31
+
32
+ Other Information
33
+
34
+ * In no way are the patent or trademark rights of any person affected by CC0,
35
+ nor are the rights that other persons may have in the work or in how the work
36
+ is used, such as publicity or privacy rights.
37
+ * Unless expressly stated otherwise, the person who associated a work with this
38
+ deed makes no warranties about the work, and disclaims liability for all uses
39
+ of the work, to the fullest extent permitted by applicable law.
40
+ * When using or citing the work, you should not imply endorsement by the author
41
+ or the affirmer.
@@ -0,0 +1,93 @@
1
+ beeline
2
+ =======
3
+
4
+ BeeLine is a BeeChat Client Framework for Ruby.
5
+
6
+ #### Installation
7
+
8
+ Add to your `Gemspec`
9
+
10
+ ```ruby
11
+ gem 'beeline-rb', require 'beeline'
12
+ ```
13
+
14
+ ```bash
15
+ bundle install
16
+ ```
17
+
18
+ **--or--**
19
+
20
+ In your project ...
21
+
22
+ ```bash
23
+ gem install beeline-rb
24
+ ```
25
+
26
+ ```ruby
27
+ require 'beeline'
28
+ ```
29
+
30
+ #### Usage
31
+
32
+ From the root of your project, add a file called `config.yml` containing (using your own account information):
33
+
34
+ ```yaml
35
+ # Example config.yml
36
+
37
+ :chain:
38
+ :hive_account: social
39
+ :hive_public_key: STM5ctejUsoZ9FwfCaVbNvWYYgNMBo9TVsHSE8wHrqAmNJi6sDctt
40
+ :hive_posting_wif: 5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC
41
+ :hive_api_url: https://api.openhive.network
42
+ ```
43
+
44
+ In your project, access the session:
45
+
46
+ ```ruby
47
+ require 'beeline'
48
+
49
+ bot = Beeline::Bot.new(prefix: '$')
50
+
51
+ # Just match on a message.
52
+ bot.message('Ping!') do
53
+ 'Pong!'
54
+ end
55
+
56
+ # Match on a pattern.
57
+ bot.message(/\d+/) do
58
+ 'Yes, those are numbers.'
59
+ end
60
+
61
+ # Respond to `$time` with current time.
62
+ bot.command(:time) do
63
+ Time.now.to_s
64
+ end
65
+
66
+ # Respond to `$say` with reply.
67
+ bot.command(:say) do |args|
68
+ if args.nil?
69
+ 'What do you want me to say?'
70
+ else
71
+ "You wanted me to say: #{args}"
72
+ end
73
+ end
74
+
75
+ # Start the bot run loop.
76
+ bot.run
77
+ ```
78
+
79
+ ---
80
+
81
+ <center>
82
+ <img src="https://i.imgur.com/h26ye3w.png" />
83
+ </center>
84
+
85
+ See some of my previous Ruby How To posts in: [#radiator](https://hive.blog/created/radiator) [#ruby](https://hive.blog/created/ruby)
86
+
87
+ ## Get in touch!
88
+
89
+ If you're using Tender, I'd love to hear from you. Drop me a line and tell me what you think! I'm @inertia on Hive.
90
+
91
+ ## License
92
+
93
+ I don't believe in intellectual "property". If you do, consider BeeLine as licensed under a Creative Commons [![CC0](http://i.creativecommons.org/p/zero/1.0/80x15.png)](http://creativecommons.org/publicdomain/zero/1.0/) License.
@@ -0,0 +1,39 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'yard'
4
+ require 'beeline'
5
+
6
+ Encoding.default_external = Encoding::UTF_8
7
+ Encoding.default_internal = Encoding::UTF_8
8
+
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'test'
11
+ t.libs << 'lib'
12
+ t.test_files = FileList['test/**/*_test.rb']
13
+ t.ruby_opts << if ENV['HELL_ENABLED']
14
+ '-W2'
15
+ else
16
+ '-W1'
17
+ end
18
+ end
19
+
20
+ task default: :test
21
+
22
+ task :console do
23
+ exec "irb -r beeline -I ./lib"
24
+ end
25
+
26
+ task :build do
27
+ exec 'gem build beeline-rb.gemspec'
28
+ end
29
+
30
+ task :push do
31
+ exec "gem push beeline-rb-#{Beeline::VERSION}.gem"
32
+ end
33
+
34
+ # We're not going to yank on a regular basis, but this is how it's done if you
35
+ # really want a task for that for some reason.
36
+
37
+ # task :yank do
38
+ # exec "gem yank beeline-rb -v #{Beeline::VERSION}"
39
+ # end
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'beeline/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'beeline-rb'
8
+ spec.version = Beeline::VERSION
9
+ spec.authors = ['Anthony Martin']
10
+ spec.email = ['beeline@martin-studio.com']
11
+
12
+ spec.summary = %q{Bot Framework for BeeChat}
13
+ spec.description = %q{HIVE centric BeeChat bot Framework.}
14
+ spec.homepage = 'https://github.com/inertia186/beeline-rb'
15
+ spec.license = 'CC0 1.0'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test)/}) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 2.0', '>= 2.0.1'
21
+ spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
22
+ spec.add_development_dependency 'minitest', '~> 5.14', '= 5.14.2'
23
+ spec.add_development_dependency 'minitest-line', '~> 0.6', '= 0.6.5'
24
+ spec.add_development_dependency 'webmock', '~> 3.9', '= 3.9.1'
25
+ spec.add_development_dependency 'vcr', '~> 6.0', '= 6.0.0'
26
+ spec.add_development_dependency 'simplecov', '~> 0.19', '= 0.19.0'
27
+ spec.add_development_dependency 'yard', '~> 0.9', '= 0.9.25'
28
+ spec.add_development_dependency 'byebug', '~> 11.1', '= 11.1.3'
29
+ spec.add_development_dependency 'pry', '~> 0.13', '= 0.13.1'
30
+ spec.add_development_dependency 'pry-coolline', '~> 0.2', '= 0.2.5'
31
+ spec.add_development_dependency 'awesome_print', '~> 1.8', '= 1.8.0'
32
+ spec.add_development_dependency 'irb', '~> 1.2', '= 1.2.7'
33
+ spec.add_development_dependency 'rb-readline', '~> 0.5', '= 0.5.5'
34
+
35
+ spec.add_dependency 'hive-ruby', '~> 1.0', '= 1.0.0'
36
+ spec.add_dependency 'faye-websocket', '~> 0.11', '= 0.11.0'
37
+ spec.add_dependency 'permessage_deflate', '~> 0.1', '= 0.1.4'
38
+ end
@@ -0,0 +1,7 @@
1
+ # Example config.yml
2
+
3
+ :chain:
4
+ :hive_account: social
5
+ :hive_public_key: STM5ctejUsoZ9FwfCaVbNvWYYgNMBo9TVsHSE8wHrqAmNJi6sDctt
6
+ :hive_posting_wif: 5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC
7
+ :hive_api_url: https://api.openhive.network
@@ -0,0 +1,19 @@
1
+ require 'pry'
2
+
3
+ Bundler.require
4
+
5
+ defined? Thread.report_on_exception and Thread.report_on_exception = true
6
+
7
+ require 'beeline/config'
8
+ require 'beeline/client'
9
+ require 'beeline/session'
10
+ require 'beeline/bot'
11
+
12
+ module Beeline
13
+ PWD = Dir.pwd.freeze
14
+ BEE_BASE_URL = 'https://beechat.hive-engine.com/api'.freeze
15
+ BEE_WS_URL = 'wss://ws.beechat.hive-engine.com'.freeze
16
+ WS_KEEPALIVE_TIME = 30.freeze
17
+
18
+ extend self
19
+ end
@@ -0,0 +1,43 @@
1
+ module Beeline
2
+ class Bot < Client
3
+ attr_reader :prefix
4
+
5
+ def command name, options = {}, &block
6
+ commands[name] = {options: options, block: block}
7
+ end
8
+
9
+ def message pattern, options = {}, &block
10
+ messages[pattern] = {options: options, block: block}
11
+ end
12
+
13
+ def process_status(payload)
14
+ if payload['authenticated']
15
+ puts 'Got acknowledge authenticated.'
16
+ else
17
+ abort 'Unable to authenticate.'
18
+ end
19
+ end
20
+
21
+ def process_chat_message(payload)
22
+ from = payload['from']
23
+ content = payload['content'].to_s
24
+ command_key = content.split(' ').first.split(prefix).last.to_sym
25
+ reply = if commands.keys.include? command_key
26
+ args = (content.split(' ') - ["#{prefix}#{command_key}"]).join(' ')
27
+ args = args.empty? ? nil : args
28
+
29
+ commands[command_key][:block].call(args, from)
30
+ elsif (matching_messages = messages.select{|k| Regexp.new(k).match?(content)}).any?
31
+ message = matching_messages.values.first # match in order of declaration
32
+
33
+ message[:block].call(content, from)
34
+ end
35
+
36
+ if !!reply
37
+ conversation_id = payload['conversation_id']
38
+
39
+ chat_message(conversation_id, from, reply)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,196 @@
1
+ require 'faye/websocket'
2
+ require 'eventmachine'
3
+ require 'permessage_deflate'
4
+
5
+ module Beeline
6
+ class Client
7
+ include Beeline::Config
8
+
9
+ attr_reader :commands, :messages
10
+
11
+ INITIAL_LATCH = 0.01
12
+ MAX_LATCH = 3.0
13
+
14
+ def initialize(options = {})
15
+ @session = options[:session]
16
+ @url = options[:url] || BEE_WS_URL
17
+ @commands = options[:commands] || {}
18
+ @messages = options[:messages] || {}
19
+ @prefix = options[:prefix] || '$'
20
+ @latch = INITIAL_LATCH
21
+ @socket = nil
22
+ @thread_running = false
23
+ end
24
+
25
+ def reset_session
26
+ @session = nil
27
+ end
28
+
29
+ def run(options = {async: false})
30
+ async = !!options[:async]
31
+ start_thread(async) unless !!@thread_running
32
+
33
+ socket
34
+ end
35
+
36
+ def run_loop
37
+ loop do
38
+ start_thread(false) unless !!@thread_running
39
+
40
+ sleep [@latch *= 2, MAX_LATCH].min
41
+ end
42
+ end
43
+
44
+ def ping
45
+ start = Time.now
46
+
47
+ puts 'Ping ... '
48
+
49
+ socket.ping('Ping!') do
50
+ puts "Pong! (#{Time.now - start})"
51
+ end
52
+ end
53
+ private
54
+ def session
55
+ @session ||= Session.new
56
+ end
57
+
58
+ def socket
59
+ @socket ||= Faye::WebSocket::Client.new(BEE_WS_URL, [],
60
+ extensions: [PermessageDeflate],
61
+ headers: {
62
+ 'User-Agent' => AGENT_ID,
63
+ 'Cookie' => session.tokens
64
+ },
65
+ ping: WS_KEEPALIVE_TIME
66
+ )
67
+ end
68
+
69
+ def authenticate
70
+ if result = socket.send({type: 'authenticate', payload: {username: hive_account, token: session.ws_token}}.to_json)
71
+ puts "Authentication sent: #{session.inspect}"
72
+
73
+ ping
74
+ else
75
+ puts "Could not authenticate."
76
+ end
77
+ end
78
+
79
+ def chat_message(conversation_id, to, message)
80
+ socket.send({type: 'chat-message', payload: {conversation_id: conversation_id, to: to, message: message}}.to_json)
81
+ end
82
+
83
+ # @private
84
+ def start_thread(async = false)
85
+ thread = Thread.new do
86
+ EM.run {
87
+ socket.on :open do |event|
88
+ p [:ws, [:open]]
89
+ authenticate
90
+ @thread_running = true
91
+ end
92
+
93
+ socket.on :message do |event|
94
+ data = JSON[event.data] rescue nil
95
+
96
+ if !!data && !!data['type'] && !!data['payload']
97
+ payload = data['payload']
98
+
99
+ case data['type']
100
+ when 'status' then process_status(payload)
101
+ when 'reauthentication-required' then session.refresh_token
102
+ when 'chat-message' then process_chat_message(payload)
103
+ when 'message-deleted' then process_message_deleted(payload)
104
+ when 'conversation-created' then process_conversation_created(payload)
105
+ when 'conversation-renamed' then process_conversation_renamed(payload)
106
+ when 'conversation-removed' then process_conversation_removed(payload)
107
+ when 'acknowledged' then process_acknowledged(payload)
108
+ when 'member-added' then process_member_added(payload)
109
+ when 'member-removed' then process_member_removed(payload)
110
+ when 'moderator-added' then process_moderator_added(payload)
111
+ when 'moderator-removed' then process_moderator_removed(payload)
112
+ when 'friendship-accepted' then process_friendship_accepted(payload)
113
+ when 'friendship-removed' then process_friendship_removed(payload)
114
+ when 'friendship-requested' then process_friendship_requested(payload)
115
+ when 'friendship-rejected' then process_friendship_rejected(payload)
116
+ when 'user-blocked' then process_user_blocked(payload)
117
+ when 'user-unblocked' then process_user_unblocked(payload)
118
+ else
119
+ p [:beechat_message, data['type'], data['payload']]
120
+ end
121
+ else
122
+ p [:ws, [:message, event.data]]
123
+ end
124
+ end
125
+
126
+ socket.on :close do |event|
127
+ p [:ws, [:close, event.code, event.reason]]
128
+ @thread_running = false
129
+ @socket = nil
130
+ EM.stop
131
+ end
132
+
133
+ socket.on :error do |event|
134
+ p [:ws, [:error, event.message.inspect]]
135
+ @thread_running = false
136
+ @socket = nil
137
+ EM.stop
138
+ end
139
+ }
140
+ end
141
+
142
+ thread.join unless !!async
143
+ end
144
+
145
+ # Override to procsss.
146
+ def process_status(payload); end
147
+
148
+ # Override to procsss.
149
+ def process_chat_message(payload); end
150
+
151
+ # Override to procsss.
152
+ def process_message_deleted(payload); end
153
+
154
+ # Override to procsss.
155
+ def process_conversation_created(payload); end
156
+
157
+ # Override to procsss.
158
+ def process_conversation_renamed(payload); end
159
+
160
+ # Override to procsss.
161
+ def process_conversation_removed(payload); end
162
+
163
+ # Override to procsss.
164
+ def process_acknowledged(payload); end
165
+
166
+ # Override to procsss.
167
+ def process_member_added(payload); end
168
+
169
+ # Override to procsss.
170
+ def process_member_removed(payload); end
171
+
172
+ # Override to procsss.
173
+ def process_moderator_added(payload); end
174
+
175
+ # Override to procsss.
176
+ def process_moderator_removed(payload); end
177
+
178
+ # Override to procsss.
179
+ def process_friendship_accepted(payload); end
180
+
181
+ # Override to procsss.
182
+ def process_friendship_removed(payload); end
183
+
184
+ # Override to procsss.
185
+ def process_friendship_requested(payload); end
186
+
187
+ # Override to procsss.
188
+ def process_friendship_rejected(payload); end
189
+
190
+ # Override to procsss.
191
+ def process_user_blocked(payload); end
192
+
193
+ # Override to procsss.
194
+ def process_user_unblocked(payload); end
195
+ end
196
+ end
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+
3
+ module Beeline
4
+ module Config
5
+ def hive_account
6
+ chain[:hive_account]
7
+ end
8
+
9
+ def hive_posting_wif
10
+ chain[:hive_posting_wif]
11
+ end
12
+
13
+ def hive_public_key
14
+ chain[:hive_public_key]
15
+ end
16
+ private
17
+ def chain
18
+ @chain_hash ||= yml[:chain]
19
+ end
20
+
21
+ def yml
22
+ return @yml if !!@yml
23
+
24
+ config_yaml_path = "#{Beeline::PWD}/config.yml"
25
+
26
+ @yml = if File.exist?(config_yaml_path)
27
+ YAML.load_file(config_yaml_path)
28
+ else
29
+ raise "Create a file: #{config_yaml_path}"
30
+ end
31
+
32
+ @yml
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,230 @@
1
+ require 'hive'
2
+ require 'json'
3
+ require 'bitcoin'
4
+ require 'net/http'
5
+ require 'digest/sha2'
6
+
7
+ module Beeline
8
+ class Session
9
+ include Config
10
+ include Hive::Utils
11
+
12
+ attr_reader :ws_session, :cookies
13
+
14
+ def initialize
15
+ @base_uri = nil
16
+ @ws_uri = nil
17
+ @cookies = nil
18
+ @ws_session = nil
19
+ @http = nil
20
+ end
21
+
22
+ def base_uri
23
+ @base_uri ||= URI.parse(BEE_BASE_URL)
24
+ end
25
+
26
+ def ws_uri
27
+ @ws_uri ||= URI.parse(BEE_WS_URL)
28
+ end
29
+
30
+ def tokens
31
+ login if @cookies.nil?
32
+
33
+ return if @cookies.nil?
34
+
35
+ [
36
+ @cookies.split('; ').select{|t| t.start_with? 'token='}.first,
37
+ @cookies.split('; ').select{|t| t.start_with? 'refresh_token='}.first
38
+ ].join('; ')
39
+ end
40
+
41
+ def ws_token
42
+ login if @ws_session.nil?
43
+
44
+ return if @ws_session.nil?
45
+
46
+ @ws_session['ws_token']
47
+ end
48
+
49
+ def http(&block)
50
+ Net::HTTP.start(base_uri.host, base_uri.port, use_ssl: base_uri.scheme == 'https') do |http|
51
+ yield http
52
+ end
53
+ end
54
+
55
+ def login
56
+ return @ws_session if !!@ws_session
57
+
58
+ timestamp = (Time.now.to_f * 1000).to_i
59
+ message = "#{hive_account}#{timestamp}"
60
+ signature = hexlify sign_message message
61
+ resource = "#{base_uri.path}/users/login?username=#{hive_account}&ts=#{timestamp}&sig=#{signature}"
62
+
63
+ http do |http|
64
+ request = Net::HTTP::Get.new resource
65
+ request['User-Agent'] = AGENT_ID
66
+ response = http.request request
67
+
68
+ if response.code == '200'
69
+ @cookies = response['Set-Cookie']
70
+ @ws_session = JSON[response.body]
71
+ else
72
+ JSON[response.body]
73
+ end
74
+ end
75
+ end
76
+
77
+ def verify
78
+ raise "Unable to verify before logging in" unless !!@ws_session
79
+
80
+ resource = "#{base_uri.path}/users/verify"
81
+
82
+ http do |http|
83
+ request = Net::HTTP::Get.new resource
84
+ request['User-Agent'] = AGENT_ID
85
+ request['Cookie'] = tokens
86
+ response = http.request request
87
+
88
+ JSON[response.body]
89
+ end
90
+ end
91
+
92
+ def refresh_token
93
+ raise "Unable to refresh token before logging in" unless !!@ws_session
94
+
95
+ resource = "#{base_uri.path}/refresh-token"
96
+
97
+ http do |http|
98
+ request = Net::HTTP::Get.new resource
99
+ request['User-Agent'] = AGENT_ID
100
+ request['Cookie'] = tokens
101
+ response = http.request request
102
+
103
+ if response.code == '200'
104
+ @cookies = response['Set-Cookie']
105
+ @ws_session = JSON[response.body]
106
+ else
107
+ JSON[response.body]
108
+ end
109
+ end
110
+ end
111
+
112
+ def get(resource)
113
+ raise "Unable to request #{resource} before logging in" unless !!@ws_session
114
+
115
+ resource = "#{base_uri.path}#{resource}"
116
+
117
+ http do |http|
118
+ request = Net::HTTP::Get.new resource
119
+ request['User-Agent'] = AGENT_ID
120
+ request['Cookie'] = tokens
121
+ response = http.request request
122
+
123
+ JSON[response.body]
124
+ end
125
+ end
126
+
127
+ def friends; get('/users/friends'); end
128
+ def settings; get('/users/settings'); end
129
+
130
+ def settings=(new_settings)
131
+ raise "Unable to post settings before logging in" unless !!@ws_session
132
+
133
+ resource = "#{base_uri.path}/users/settings"
134
+
135
+ http do |http|
136
+ request = Net::HTTP::Post.new resource
137
+ request.body = new_settings.to_json
138
+ request['Content-Type'] = 'application/json; charset=UTF-8'
139
+ request['User-Agent'] = AGENT_ID
140
+ request['Cookie'] = tokens
141
+ response = http.request request
142
+
143
+ JSON[response.body]
144
+ end
145
+ end
146
+
147
+ def channels; get('/users/channels'); end
148
+
149
+ def channels=(new_channels)
150
+ raise "Unable to post channels before logging in" unless !!@ws_session
151
+
152
+ resource = "#{base_uri.path}/users/channels"
153
+
154
+ http do |http|
155
+ request = Net::HTTP::Post.new resource
156
+ request.body = new_channels.to_json
157
+ request['Content-Type'] = 'application/json; charset=UTF-8'
158
+ request['User-Agent'] = AGENT_ID
159
+ request['Cookie'] = tokens
160
+ response = http.request request
161
+
162
+ JSON[response.body]
163
+ end
164
+ end
165
+
166
+ def logout; get('/users/logout'); end
167
+ def conversations; get('/messages/conversations'); end
168
+
169
+ def conversation(*id)
170
+ raise "Unable to get conversation before logging in" unless !!@ws_session
171
+
172
+ id = [id].flatten
173
+ resource = "#{base_uri.path}/messages/conversation?ids=#{id.join(',')}"
174
+
175
+ http do |http|
176
+ request = Net::HTTP::Get.new resource
177
+ request['User-Agent'] = AGENT_ID
178
+ request['Cookie'] = tokens
179
+ response = http.request request
180
+
181
+ JSON[response.body]
182
+ end
183
+ end
184
+
185
+ def new_conversations; get('/messages/new'); end
186
+
187
+ def chats(id, before = nil, limit = nil)
188
+ raise "Unable to get conversation before logging in" unless !!@ws_session
189
+
190
+ resource = "#{base_uri.path}/messages/chats?conversation_id=#{id}"
191
+ resource += "&before=#{before.utc.iso8601}" if !!before
192
+ resource += "&limit=#{limit}" if !!limit
193
+
194
+ http do |http|
195
+ request = Net::HTTP::Get.new resource
196
+ request['User-Agent'] = AGENT_ID
197
+ request['Cookie'] = tokens
198
+ response = http.request request
199
+
200
+ JSON[response.body]
201
+ end
202
+ end
203
+
204
+ def dump_conversations
205
+ new_conversations.map{|c| "#{c['timestamp']} :: #{c['conversation_id']} :: #{c['from']}: #{c['content']}"}
206
+ end
207
+
208
+ def inspect
209
+ properties = %w(base_uri ws_uri ws_session).map do |prop|
210
+ if !!(v = instance_variable_get("@#{prop}"))
211
+ case v
212
+ when Array then "@#{prop}=<#{v.size} #{v.size == 1 ? 'element' : 'elements'}>"
213
+ else; "@#{prop}=#{v}"
214
+ end
215
+ end
216
+ end.compact.join(', ')
217
+
218
+ "#<#{self.class} [#{properties}]>"
219
+ end
220
+ private
221
+ # @private
222
+ def sign_message(message)
223
+ digest_hex = Digest::SHA256.digest(message)
224
+ private_key = Bitcoin::Key.from_base58 hive_posting_wif
225
+ public_key = Bitcoin.decode_base58(hive_public_key[3..-1])[0..65]
226
+
227
+ Bitcoin::OpenSSL_EC.sign_compact(digest_hex, private_key.priv, public_key, true)
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,4 @@
1
+ module Beeline
2
+ VERSION = '0.0.1'
3
+ AGENT_ID = "beeline/#{VERSION}"
4
+ end
metadata ADDED
@@ -0,0 +1,399 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beeline-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anthony Martin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-08 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: '2.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '13.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 13.0.1
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '13.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 13.0.1
53
+ - !ruby/object:Gem::Dependency
54
+ name: minitest
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '5.14'
60
+ - - '='
61
+ - !ruby/object:Gem::Version
62
+ version: 5.14.2
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '5.14'
70
+ - - '='
71
+ - !ruby/object:Gem::Version
72
+ version: 5.14.2
73
+ - !ruby/object:Gem::Dependency
74
+ name: minitest-line
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '0.6'
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.6.5
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.6'
90
+ - - '='
91
+ - !ruby/object:Gem::Version
92
+ version: 0.6.5
93
+ - !ruby/object:Gem::Dependency
94
+ name: webmock
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '3.9'
100
+ - - '='
101
+ - !ruby/object:Gem::Version
102
+ version: 3.9.1
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.9'
110
+ - - '='
111
+ - !ruby/object:Gem::Version
112
+ version: 3.9.1
113
+ - !ruby/object:Gem::Dependency
114
+ name: vcr
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - '='
118
+ - !ruby/object:Gem::Version
119
+ version: 6.0.0
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '6.0'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '='
128
+ - !ruby/object:Gem::Version
129
+ version: 6.0.0
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '6.0'
133
+ - !ruby/object:Gem::Dependency
134
+ name: simplecov
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '='
138
+ - !ruby/object:Gem::Version
139
+ version: 0.19.0
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '0.19'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - '='
148
+ - !ruby/object:Gem::Version
149
+ version: 0.19.0
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.19'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.9'
160
+ - - '='
161
+ - !ruby/object:Gem::Version
162
+ version: 0.9.25
163
+ type: :development
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: '0.9'
170
+ - - '='
171
+ - !ruby/object:Gem::Version
172
+ version: 0.9.25
173
+ - !ruby/object:Gem::Dependency
174
+ name: byebug
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '11.1'
180
+ - - '='
181
+ - !ruby/object:Gem::Version
182
+ version: 11.1.3
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: '11.1'
190
+ - - '='
191
+ - !ruby/object:Gem::Version
192
+ version: 11.1.3
193
+ - !ruby/object:Gem::Dependency
194
+ name: pry
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: '0.13'
200
+ - - '='
201
+ - !ruby/object:Gem::Version
202
+ version: 0.13.1
203
+ type: :development
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - "~>"
208
+ - !ruby/object:Gem::Version
209
+ version: '0.13'
210
+ - - '='
211
+ - !ruby/object:Gem::Version
212
+ version: 0.13.1
213
+ - !ruby/object:Gem::Dependency
214
+ name: pry-coolline
215
+ requirement: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - "~>"
218
+ - !ruby/object:Gem::Version
219
+ version: '0.2'
220
+ - - '='
221
+ - !ruby/object:Gem::Version
222
+ version: 0.2.5
223
+ type: :development
224
+ prerelease: false
225
+ version_requirements: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '0.2'
230
+ - - '='
231
+ - !ruby/object:Gem::Version
232
+ version: 0.2.5
233
+ - !ruby/object:Gem::Dependency
234
+ name: awesome_print
235
+ requirement: !ruby/object:Gem::Requirement
236
+ requirements:
237
+ - - '='
238
+ - !ruby/object:Gem::Version
239
+ version: 1.8.0
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: '1.8'
243
+ type: :development
244
+ prerelease: false
245
+ version_requirements: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - '='
248
+ - !ruby/object:Gem::Version
249
+ version: 1.8.0
250
+ - - "~>"
251
+ - !ruby/object:Gem::Version
252
+ version: '1.8'
253
+ - !ruby/object:Gem::Dependency
254
+ name: irb
255
+ requirement: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - "~>"
258
+ - !ruby/object:Gem::Version
259
+ version: '1.2'
260
+ - - '='
261
+ - !ruby/object:Gem::Version
262
+ version: 1.2.7
263
+ type: :development
264
+ prerelease: false
265
+ version_requirements: !ruby/object:Gem::Requirement
266
+ requirements:
267
+ - - "~>"
268
+ - !ruby/object:Gem::Version
269
+ version: '1.2'
270
+ - - '='
271
+ - !ruby/object:Gem::Version
272
+ version: 1.2.7
273
+ - !ruby/object:Gem::Dependency
274
+ name: rb-readline
275
+ requirement: !ruby/object:Gem::Requirement
276
+ requirements:
277
+ - - "~>"
278
+ - !ruby/object:Gem::Version
279
+ version: '0.5'
280
+ - - '='
281
+ - !ruby/object:Gem::Version
282
+ version: 0.5.5
283
+ type: :development
284
+ prerelease: false
285
+ version_requirements: !ruby/object:Gem::Requirement
286
+ requirements:
287
+ - - "~>"
288
+ - !ruby/object:Gem::Version
289
+ version: '0.5'
290
+ - - '='
291
+ - !ruby/object:Gem::Version
292
+ version: 0.5.5
293
+ - !ruby/object:Gem::Dependency
294
+ name: hive-ruby
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - '='
298
+ - !ruby/object:Gem::Version
299
+ version: 1.0.0
300
+ - - "~>"
301
+ - !ruby/object:Gem::Version
302
+ version: '1.0'
303
+ type: :runtime
304
+ prerelease: false
305
+ version_requirements: !ruby/object:Gem::Requirement
306
+ requirements:
307
+ - - '='
308
+ - !ruby/object:Gem::Version
309
+ version: 1.0.0
310
+ - - "~>"
311
+ - !ruby/object:Gem::Version
312
+ version: '1.0'
313
+ - !ruby/object:Gem::Dependency
314
+ name: faye-websocket
315
+ requirement: !ruby/object:Gem::Requirement
316
+ requirements:
317
+ - - '='
318
+ - !ruby/object:Gem::Version
319
+ version: 0.11.0
320
+ - - "~>"
321
+ - !ruby/object:Gem::Version
322
+ version: '0.11'
323
+ type: :runtime
324
+ prerelease: false
325
+ version_requirements: !ruby/object:Gem::Requirement
326
+ requirements:
327
+ - - '='
328
+ - !ruby/object:Gem::Version
329
+ version: 0.11.0
330
+ - - "~>"
331
+ - !ruby/object:Gem::Version
332
+ version: '0.11'
333
+ - !ruby/object:Gem::Dependency
334
+ name: permessage_deflate
335
+ requirement: !ruby/object:Gem::Requirement
336
+ requirements:
337
+ - - "~>"
338
+ - !ruby/object:Gem::Version
339
+ version: '0.1'
340
+ - - '='
341
+ - !ruby/object:Gem::Version
342
+ version: 0.1.4
343
+ type: :runtime
344
+ prerelease: false
345
+ version_requirements: !ruby/object:Gem::Requirement
346
+ requirements:
347
+ - - "~>"
348
+ - !ruby/object:Gem::Version
349
+ version: '0.1'
350
+ - - '='
351
+ - !ruby/object:Gem::Version
352
+ version: 0.1.4
353
+ description: HIVE centric BeeChat bot Framework.
354
+ email:
355
+ - beeline@martin-studio.com
356
+ executables: []
357
+ extensions: []
358
+ extra_rdoc_files: []
359
+ files:
360
+ - ".gitignore"
361
+ - Gemfile
362
+ - LICENSE
363
+ - README.md
364
+ - Rakefile
365
+ - beeline-rb.gemspec
366
+ - example-config.yml
367
+ - lib/beeline.rb
368
+ - lib/beeline/bot.rb
369
+ - lib/beeline/client.rb
370
+ - lib/beeline/config.rb
371
+ - lib/beeline/session.rb
372
+ - lib/beeline/version.rb
373
+ - support/320-logo-2020-10-08 14-08.png
374
+ - support/logo-2020-10-08 14-08.png
375
+ - support/logo-2020-10-08 14-08.xcf
376
+ homepage: https://github.com/inertia186/beeline-rb
377
+ licenses:
378
+ - CC0 1.0
379
+ metadata: {}
380
+ post_install_message:
381
+ rdoc_options: []
382
+ require_paths:
383
+ - lib
384
+ required_ruby_version: !ruby/object:Gem::Requirement
385
+ requirements:
386
+ - - ">="
387
+ - !ruby/object:Gem::Version
388
+ version: '0'
389
+ required_rubygems_version: !ruby/object:Gem::Requirement
390
+ requirements:
391
+ - - ">="
392
+ - !ruby/object:Gem::Version
393
+ version: '0'
394
+ requirements: []
395
+ rubygems_version: 3.0.8
396
+ signing_key:
397
+ specification_version: 4
398
+ summary: Bot Framework for BeeChat
399
+ test_files: []