meshchat 0.5.0

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