beeline-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []