meshchat 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -0
  3. data/README.md +7 -0
  4. data/lib/meshchat.rb +73 -0
  5. data/lib/meshchat/cli.rb +164 -0
  6. data/lib/meshchat/cli/command.rb +63 -0
  7. data/lib/meshchat/cli/config.rb +30 -0
  8. data/lib/meshchat/cli/exit.rb +9 -0
  9. data/lib/meshchat/cli/identity.rb +9 -0
  10. data/lib/meshchat/cli/import.rb +37 -0
  11. data/lib/meshchat/cli/init.rb +34 -0
  12. data/lib/meshchat/cli/input.rb +60 -0
  13. data/lib/meshchat/cli/irb.rb +18 -0
  14. data/lib/meshchat/cli/listen.rb +9 -0
  15. data/lib/meshchat/cli/ping.rb +61 -0
  16. data/lib/meshchat/cli/ping_all.rb +11 -0
  17. data/lib/meshchat/cli/server.rb +16 -0
  18. data/lib/meshchat/cli/share.rb +9 -0
  19. data/lib/meshchat/cli/stop_listening.rb +9 -0
  20. data/lib/meshchat/cli/whisper.rb +34 -0
  21. data/lib/meshchat/cli/who.rb +9 -0
  22. data/lib/meshchat/config/hash_file.rb +75 -0
  23. data/lib/meshchat/config/settings.rb +112 -0
  24. data/lib/meshchat/database.rb +30 -0
  25. data/lib/meshchat/display.rb +32 -0
  26. data/lib/meshchat/display/base.rb +53 -0
  27. data/lib/meshchat/display/manager.rb +51 -0
  28. data/lib/meshchat/encryption.rb +27 -0
  29. data/lib/meshchat/encryption/aes_rsa.rb +65 -0
  30. data/lib/meshchat/encryption/passthrough.rb +17 -0
  31. data/lib/meshchat/instance.rb +34 -0
  32. data/lib/meshchat/message.rb +38 -0
  33. data/lib/meshchat/message/base.rb +93 -0
  34. data/lib/meshchat/message/chat.rb +14 -0
  35. data/lib/meshchat/message/disconnection.rb +13 -0
  36. data/lib/meshchat/message/node_list.rb +41 -0
  37. data/lib/meshchat/message/node_list_diff.rb +15 -0
  38. data/lib/meshchat/message/node_list_hash.rb +29 -0
  39. data/lib/meshchat/message/ping.rb +32 -0
  40. data/lib/meshchat/message/ping_reply.rb +9 -0
  41. data/lib/meshchat/message/relay.rb +43 -0
  42. data/lib/meshchat/message/whisper.rb +36 -0
  43. data/lib/meshchat/models/entry.rb +104 -0
  44. data/lib/meshchat/net/client.rb +60 -0
  45. data/lib/meshchat/net/listener/request.rb +48 -0
  46. data/lib/meshchat/net/listener/request_processor.rb +45 -0
  47. data/lib/meshchat/net/listener/server.rb +61 -0
  48. data/lib/meshchat/net/request.rb +29 -0
  49. data/lib/meshchat/notifier/base.rb +50 -0
  50. data/lib/meshchat/version.rb +3 -0
  51. metadata +288 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01c4f397703dbfd3299712e33207dffb16edfdea
4
+ data.tar.gz: 2679cafaa50569456444ab222dfd976db1dc724c
5
+ SHA512:
6
+ metadata.gz: f660b1820794d8b40657ae757ae54730ed5c605128781d8f6aa49fd57dc6746a3ac6cd3668e6cddef905f76380a1791da6e072117bdc38d08232f9d697c5dc52
7
+ data.tar.gz: 923524a79e5fd5f858d48d8a2fb8b6cb53d5b770150f88accc5d2a92132c34f3459952258fb1e8652a0dbea0984bef4b02e78dc9f25a255a12e1242bca80d044
@@ -0,0 +1 @@
1
+ * Extract meshchat from spiced gracken (spiced gracken may be receiving a rename soon)
@@ -0,0 +1,7 @@
1
+ #MeshChat (Ruby) [![Build Status](https://travis-ci.org/NullVoxPopuli/meshchat.svg)](https://travis-ci.org/NullVoxPopuli/meshchat) [![Code Climate](https://codeclimate.com/github/NullVoxPopuli/meshchat/badges/gpa.svg)](https://codeclimate.com/github/NullVoxPopuli/meshchat) [![Test Coverage](https://codeclimate.com/github/NullVoxPopuli/meshchat/badges/coverage.svg)](https://codeclimate.com/github/NullVoxPopuli/meshchat/coverage)
2
+
3
+ This is the core functionality for implementing a [mesh-chat](https://github.com/neuravion/mesh-chat) compatible client in ruby
4
+
5
+ #Usage
6
+
7
+ See [Spiced Gracken](https://github.com/NullVoxPopuli/spiced_gracken)
@@ -0,0 +1,73 @@
1
+ # required standard libs
2
+ require 'openssl'
3
+ require 'socket'
4
+ require 'json'
5
+ require 'date'
6
+ require 'colorize'
7
+ require 'curses'
8
+ require 'io/console'
9
+ require "readline"
10
+
11
+ require 'logger'
12
+
13
+ # required gems
14
+ require 'awesome_print'
15
+ require 'sqlite3'
16
+ require 'active_record'
17
+ require 'curb'
18
+ require 'thin'
19
+ require 'libnotify'
20
+
21
+ # active support extensions
22
+ require 'active_support/core_ext/module/delegation'
23
+ require 'active_support/core_ext/object/blank'
24
+ require 'active_support/core_ext/object/try'
25
+
26
+ # local files for meshchat
27
+ require 'meshchat/version'
28
+ require 'meshchat/database'
29
+ require 'meshchat/instance'
30
+ require 'meshchat/encryption'
31
+ require 'meshchat/display'
32
+ require 'meshchat/display/manager'
33
+ require 'meshchat/notifier/base'
34
+ require 'meshchat/models/entry'
35
+ require 'meshchat/config/hash_file'
36
+ require 'meshchat/config/settings'
37
+ require 'meshchat/net/request'
38
+ require 'meshchat/net/client'
39
+ require 'meshchat/net/listener/request'
40
+ require 'meshchat/net/listener/request_processor'
41
+ require 'meshchat/net/listener/server'
42
+ require 'meshchat/cli'
43
+ require 'meshchat/message'
44
+
45
+ module MeshChat
46
+ NAME = 'MeshChat'
47
+ Settings = Config::Settings
48
+ Node = Models::Entry
49
+ Cipher = Encryption
50
+ Notify = Notifier::Base
51
+
52
+ module_function
53
+
54
+ # @param [Hash] overrides
55
+ # @option overrides [Proc] on_display_start what to do upon start of the display manager
56
+ # @option overrides [class] display the display ui to use inherited from Display::Base
57
+ def start(overrides = {})
58
+ defaults = {
59
+ display: Display::Base,
60
+ client_name: NAME,
61
+ client_version: VERSION
62
+ }
63
+ options = defaults.merge(overrides)
64
+
65
+ # before doing anything, ensure we have a place to store data
66
+ Database.setup_storage
67
+ # set the options / overrides!
68
+ Instance.start(options)
69
+ end
70
+
71
+ def name; Instance.client_name; end
72
+ def version; Instance.client_version; end
73
+ end
@@ -0,0 +1,164 @@
1
+ require 'meshchat/cli/input'
2
+ require 'meshchat/cli/command'
3
+ require 'meshchat/cli/identity'
4
+ require 'meshchat/cli/irb'
5
+ require 'meshchat/cli/config'
6
+ require 'meshchat/cli/ping'
7
+ require 'meshchat/cli/ping_all'
8
+ require 'meshchat/cli/server'
9
+ require 'meshchat/cli/whisper'
10
+ require 'meshchat/cli/exit'
11
+ require 'meshchat/cli/listen'
12
+ require 'meshchat/cli/stop_listening'
13
+ require 'meshchat/cli/who'
14
+ require 'meshchat/cli/init'
15
+ require 'meshchat/cli/share'
16
+ require 'meshchat/cli/import'
17
+
18
+ module MeshChat
19
+ # A user interface is responsible for for creating a client
20
+ # and sending messages to that client
21
+ class CLI
22
+ COMMAND_MAP = {
23
+ Command::CONFIG => CLI::Config,
24
+ Command::PING => CLI::Ping,
25
+ Command::PING_ALL => CLI::PingAll,
26
+ Command::STOP_LISTENING => CLI::StopListening,
27
+ Command::SERVERS => CLI::Server,
28
+ Command::SERVER => CLI::Server,
29
+ Command::EXIT => CLI::Exit,
30
+ Command::QUIT => CLI::Exit,
31
+ Command::LISTEN => CLI::Listen,
32
+ Command::WHO => CLI::Who,
33
+ Command::IDENTITY => CLI::Identity,
34
+ Command::IRB => CLI::IRB,
35
+ Command::INIT => CLI::Init,
36
+ Command::SHARE => CLI::Share,
37
+ Command::IMPORT => CLI::Import,
38
+ Command::EXPORT => CLI::Share
39
+ }
40
+
41
+
42
+ class << self
43
+
44
+ delegate :server_location, :listen_for_commands,
45
+ :shutdown, :start_server, :client, :server,
46
+ :check_startup_settings, :create_input, :close_server,
47
+ to: :instance
48
+
49
+ def instance
50
+ @instance ||= new
51
+ end
52
+
53
+ # TODO: extract this for sub commands
54
+ def autocompletes
55
+ commands = COMMAND_MAP.map{ |k, v| "/#{k}" }
56
+ aliases = MeshChat::Node.all.map{ |n| "#{n.alias_name}" }
57
+ commands + aliases
58
+ end
59
+
60
+ end
61
+
62
+
63
+ def initialize
64
+ # Set up auto complete
65
+ completion = proc{ |s| self.class.autocompletes.grep(/^#{Regexp.escape(s)}/) }
66
+ Readline.completion_proc = completion
67
+
68
+ # this will allow our listener / server to print exceptions,
69
+ # rather than silently fail
70
+ Thread.abort_on_exception = true
71
+ end
72
+
73
+ def listen_for_commands
74
+ process_input while true
75
+ end
76
+
77
+ def process_input
78
+ msg = get_input
79
+ create_input(msg)
80
+ rescue SystemExit, Interrupt
81
+ close_program
82
+ rescue Exception => e
83
+ Display.error e.class.name
84
+ Display.error e.message.colorize(:red)
85
+ Display.error e.backtrace.join("\n").colorize(:red)
86
+ end
87
+
88
+ def create_input(msg)
89
+ handler = Input.create(msg)
90
+ handler.handle
91
+ rescue => e
92
+ Display.error e.message
93
+ Display.error e.class.name
94
+ Display.error e.backtrace.join("\n").colorize(:red)
95
+ end
96
+
97
+
98
+ def get_input
99
+ Readline.readline('> ', true)
100
+ end
101
+
102
+ def start_server
103
+
104
+ unless Settings.valid?
105
+ Display.alert("settings not fully valid\n")
106
+ errors = Settings.errors
107
+ errors.each do |error|
108
+ Display.alert(" - #{error}")
109
+ end
110
+
111
+ if errors.present?
112
+ Display.info('set these with /config set <field> <value>')
113
+ end
114
+
115
+ return
116
+ end
117
+
118
+ Thread.abort_on_exception = false
119
+ Thin::Logging.silent = true
120
+
121
+ Thread.new do
122
+ MeshChat::Net::Listener::Server.run!(
123
+ port: MeshChat::Settings['port'],
124
+ # logger: MeshChat::Display,
125
+ show_exceptions: true,
126
+ server: :thin,
127
+ dump_errors: true,
128
+ threaded: true
129
+ )
130
+ end
131
+
132
+ end
133
+
134
+ def close_server
135
+ puts 'shutting down server'
136
+ if @server.present?
137
+ server = @server.pop
138
+ server.try(:server).try(:close)
139
+ end
140
+ puts 'no longer listening...'
141
+ end
142
+
143
+ def server_location
144
+ Settings.location
145
+ end
146
+
147
+ def check_startup_settings
148
+ start_server if Settings['autolisten']
149
+ end
150
+
151
+ def close_program
152
+ exit
153
+ end
154
+
155
+ # save config and exit
156
+ def shutdown
157
+ # close_server
158
+ Display.info 'saving config...'
159
+ Settings.save
160
+ Display.alert "\n\nGoodbye. \n\nThank you for using #{MeshChat.name}"
161
+ exit
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,63 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Command < CLI::Input
4
+ attr_accessor :_input
5
+
6
+ # Commands
7
+ SET = 'set'
8
+ CONFIG = 'config'
9
+ DISPLAY = 'display'
10
+ EXIT = 'exit'
11
+ QUIT = 'quit'
12
+ LISTEN = 'listen'
13
+ STOP_LISTENING = 'stoplistening'
14
+ CONNECT = 'connect'
15
+ CHAT = 'chat'
16
+ ADD = 'add'
17
+ REMOVE = 'remove'
18
+ RM = 'rm'
19
+ SERVERS = 'servers'
20
+ SERVER = 'server'
21
+ WHO = 'who'
22
+ PING = 'ping'
23
+ PING_ALL = 'pingall'
24
+ IDENTITY = 'identity'
25
+ IRB = 'c'
26
+ INIT = 'init'
27
+ SHARE = 'share'
28
+ IMPORT = 'import'
29
+ EXPORT = 'export'
30
+
31
+ def handle
32
+ klass = CLI::COMMAND_MAP[command]
33
+ if klass
34
+ klass.new(_input).handle
35
+ else
36
+ Display.alert 'not implemented...'
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def command_string
43
+ @command_string ||= _input[1, _input.length]
44
+ end
45
+
46
+ def command_args
47
+ @command_args ||= command_string.split(' ')
48
+ end
49
+
50
+ def command
51
+ @command ||= command_args.first
52
+ end
53
+
54
+ def sub_command_args
55
+ @sub_command_args ||= command_args[2..3]
56
+ end
57
+
58
+ def sub_command
59
+ @sub_command ||= command_args[1]
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,30 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Config < CLI::Command
4
+ def handle
5
+ case sub_command
6
+ when SET
7
+ if is_valid_set_command?
8
+ key, value = config_set_args
9
+
10
+ Display.info Settings.set(key, with: value)
11
+ else
12
+ Display.alert 'set requires a key and a value'
13
+ end
14
+ when DISPLAY
15
+ Display.info Settings.display
16
+ else
17
+ Display.alert 'config command not implemented...'
18
+ end
19
+ end
20
+
21
+ def config_set_args
22
+ command_args[2..3]
23
+ end
24
+
25
+ def is_valid_set_command?
26
+ sub_command == SET && command_args.length == 4
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Exit < CLI::Command
4
+ def handle
5
+ CLI.shutdown
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Identity < CLI::Command
4
+ def handle
5
+ Display.success Settings.identity
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Import < CLI::Command
4
+ def handle
5
+ if command_valid?
6
+ node = Models::Entry.import_from_file(filename)
7
+ if node.valid? && node.persisted?
8
+ Display.success "#{node.alias_name} successfully imported"
9
+
10
+ # send the server list to this new node
11
+ Net::Client.send(
12
+ node: node,
13
+ message: Message::NodeList.new
14
+ )
15
+ else
16
+ Display.alert "#{node.alias_name} is invalid"
17
+ Display.alert node.errors.full_messages.join("\n")
18
+ end
19
+ else
20
+ Display.alert usage
21
+ end
22
+ end
23
+
24
+ def usage
25
+ 'Usage: /import {filename}'
26
+ end
27
+
28
+ def command_valid?
29
+ filename.present?
30
+ end
31
+
32
+ def filename
33
+ sub_command
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ module MeshChat
2
+ class CLI
3
+ class Init < CLI::Command
4
+ def handle
5
+ if Settings.uid_exists?
6
+ if confirm? 'uid exists, are you sure you want a new identity?'
7
+ Settings.generate_uid
8
+ else
9
+ Display.alert 'uid generation aborted'
10
+ end
11
+ else
12
+ Settings.generate_uid
13
+ end
14
+
15
+ if Settings.keys_exist?
16
+ if confirm? 'keys exist, overwrite?'
17
+ Settings.generate_keys
18
+ else
19
+ Display.alert 'key generation aborted'
20
+ end
21
+ else
22
+ Settings.generate_keys
23
+ end
24
+ end
25
+
26
+ def confirm?(msg)
27
+ Display.warning(msg + ' (Y/N)')
28
+ response = gets
29
+ response = response.chomp
30
+ ['yes', 'y'].include?(response.downcase)
31
+ end
32
+ end
33
+ end
34
+ end