whatup 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rubocop.yml +22 -0
- data/README.md +2 -0
- data/Rakefile +1 -1
- data/docs/hw/framework.pdf +0 -0
- data/lib/whatup/cli/commands/interactive/interactive.rb +115 -0
- data/lib/whatup/cli/commands/interactive/setup.rb +24 -0
- data/lib/whatup/client/client.rb +10 -4
- data/lib/whatup/server/client.rb +35 -3
- data/lib/whatup/server/room.rb +28 -0
- data/lib/whatup/server/server.rb +128 -12
- data/lib/whatup/version.rb +1 -1
- data/whatup.gemspec +3 -1
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 391ddb29c708ee7cf37769dc7aa3723d65e420fe08a268862bff6ec7ff5e659f
|
4
|
+
data.tar.gz: b7e349838c88b72f3fbb04258afa114b124f460af40b99d64654bb5b941c04f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f8458ee475df4aa40d81cd3c126cea7d0153ba3ab2c3d56ec7ff92e130ae1b2765b5594a7a780584498a74d2808779d7024e412d724acad919665b8b339acf3
|
7
|
+
data.tar.gz: e84e5379f28eec45311b4ab0aeea6ec67b45dadea2240f06f3c7dcc33a4094784ad081e6fc1bffa8e57d0c4cbc30248c7a55e663923d95e73b1de89698355316
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -3,10 +3,32 @@
|
|
3
3
|
AllCops:
|
4
4
|
TargetRubyVersion: 2.4 # Modern Ruby
|
5
5
|
|
6
|
+
# attr_reader *%i[a b c]
|
7
|
+
Lint/UnneededSplatExpansion:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
# Needed for the server pid
|
11
|
+
Style/GlobalVars:
|
12
|
+
Exclude:
|
13
|
+
- 'spec/system_spec.rb'
|
14
|
+
|
15
|
+
# Aruba uses modifiable strings
|
16
|
+
Style/FrozenStringLiteralComment:
|
17
|
+
Exclude:
|
18
|
+
- 'spec/system_spec.rb'
|
19
|
+
|
6
20
|
# The default is a bit restrictive
|
7
21
|
Metrics/AbcSize:
|
8
22
|
Max: 30
|
9
23
|
|
24
|
+
# The default is a bit restrictive
|
25
|
+
Metrics/ClassLength:
|
26
|
+
Max: 145
|
27
|
+
|
28
|
+
# <<~OUTPUT.gsub /^\s+/, ''
|
29
|
+
Lint/AmbiguousRegexpLiteral:
|
30
|
+
Enabled: false
|
31
|
+
|
10
32
|
Metrics/BlockLength:
|
11
33
|
Exclude:
|
12
34
|
- 'whatup.gemspec'
|
data/README.md
CHANGED
@@ -6,6 +6,8 @@ whatup is a simple server-based instant messaging application
|
|
6
6
|
|
7
7
|
Check it out on [rubygems.org](https://rubygems.org/gems/whatup).
|
8
8
|
|
9
|
+
[![Build Status](https://travis-ci.com/jethrodaniel/whatup.svg?branch=dev)](https://travis-ci.com/jethrodaniel/whatup)
|
10
|
+
|
9
11
|
## Installation
|
10
12
|
|
11
13
|
Assuming you have Ruby 2.4 or greater installed,
|
data/Rakefile
CHANGED
Binary file
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
require 'whatup/client/client'
|
6
|
+
|
7
|
+
module Whatup
|
8
|
+
module CLI
|
9
|
+
# Any methods of class `Whatup::CLI::Interactive` that rely on instance
|
10
|
+
# variables should be included here
|
11
|
+
COMMANDS = %i[room list exit].freeze
|
12
|
+
|
13
|
+
require 'whatup/cli/commands/interactive/setup'
|
14
|
+
|
15
|
+
# Interactive client commands that are available after connecting
|
16
|
+
#
|
17
|
+
# This class is run on the server
|
18
|
+
class Interactive < Thor
|
19
|
+
prepend InteractiveSetup
|
20
|
+
|
21
|
+
attr_accessor *%i[server current_user]
|
22
|
+
|
23
|
+
no_commands do
|
24
|
+
# Checks whether a given input string is a valid command
|
25
|
+
def self.command? msg
|
26
|
+
cmds, opts = parse_input(msg)
|
27
|
+
parsed_args = new(cmds, opts).args
|
28
|
+
commands.key?(parsed_args.first) || parsed_args.first == 'help'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Parses a client's input into a format suitable for Thor commands
|
32
|
+
#
|
33
|
+
# @param [String] msg - the client's message
|
34
|
+
def self.parse_input msg
|
35
|
+
# Split user input at the first "option"
|
36
|
+
cmds, opts = msg&.split /-|--/, 2
|
37
|
+
|
38
|
+
# Then split each by whitespace
|
39
|
+
cmds = cmds&.split(/\s+/)
|
40
|
+
opts = opts&.split(/\s+/)
|
41
|
+
|
42
|
+
# `Whatup::CLI::Interactive.new(cmds, opts)` expects arrays, and
|
43
|
+
# a final options hash
|
44
|
+
cmds = [] if cmds.nil?
|
45
|
+
opts = [] if opts.nil?
|
46
|
+
|
47
|
+
[cmds, opts]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Don't show app name in command help, i.e, instead of
|
52
|
+
# `app command desc`, use `command desc`
|
53
|
+
def self.banner task, _namespace = false, subcommand = false
|
54
|
+
task.formatted_usage(self, false, subcommand).to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
desc 'list', 'Show all connected clients'
|
58
|
+
def list
|
59
|
+
say 'All connected clients:'
|
60
|
+
@server.clients.each { |c| say c.status }
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'room [NAME]', 'Create and enter chatroom [NAME]'
|
64
|
+
def room name
|
65
|
+
if room = @server.rooms.select { |r| r.name == name }&.first
|
66
|
+
@current_user.puts <<~MSG
|
67
|
+
Entering #{room.name}... enjoy your stay!
|
68
|
+
|
69
|
+
Type `.exit` to exit this chat room.
|
70
|
+
|
71
|
+
Currently in this room:
|
72
|
+
#{room.clients.map do |client|
|
73
|
+
"- #{client.name}\n"
|
74
|
+
end.join}
|
75
|
+
MSG
|
76
|
+
@current_user.room = room
|
77
|
+
|
78
|
+
room.broadcast except: @current_user do
|
79
|
+
<<~MSG
|
80
|
+
#{@current_user.name} has arrived! Play nice, kids.
|
81
|
+
MSG
|
82
|
+
end
|
83
|
+
|
84
|
+
room.clients << @current_user
|
85
|
+
return
|
86
|
+
end
|
87
|
+
|
88
|
+
room = @server.new_room! name: name, clients: [@current_user]
|
89
|
+
|
90
|
+
@current_user.puts <<~MSG
|
91
|
+
Created and entered #{room.name}... invite some people or something!
|
92
|
+
|
93
|
+
Type `.exit` to exit this chat room.
|
94
|
+
MSG
|
95
|
+
end
|
96
|
+
|
97
|
+
# desc 'dm [NAME]', 'Send a direct message to [NAME]'
|
98
|
+
# def dm name
|
99
|
+
# client = @server.find_client_by name: name
|
100
|
+
|
101
|
+
# if client.nil?
|
102
|
+
# @current_user.puts "No client named `#{name}` found!"
|
103
|
+
# return
|
104
|
+
# end
|
105
|
+
|
106
|
+
# client.send_message
|
107
|
+
# end
|
108
|
+
|
109
|
+
desc 'exit', 'Closes your connection with the server'
|
110
|
+
def exit
|
111
|
+
@current_user.exit!
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Whatup
|
4
|
+
module CLI
|
5
|
+
# Implements a `before` hook to set the correct instance variables
|
6
|
+
# before any command methods.
|
7
|
+
#
|
8
|
+
# This is needed, since Thor creates another cli class instance when it is
|
9
|
+
# called with `invoke`, and we need to reassign any variables to the new
|
10
|
+
# cli instance.
|
11
|
+
#
|
12
|
+
# TODO: grab commands dynamically
|
13
|
+
module InteractiveSetup
|
14
|
+
Whatup::CLI::COMMANDS.each do |cmd|
|
15
|
+
define_method cmd do |*args|
|
16
|
+
cli = instance_variable_get(:@_initializer).last[:shell].base
|
17
|
+
@server = cli.server
|
18
|
+
@current_user = cli.current_user
|
19
|
+
super *args
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/whatup/client/client.rb
CHANGED
@@ -20,6 +20,7 @@ module Whatup
|
|
20
20
|
|
21
21
|
@socket = TCPSocket.open @dest[:ip], @dest[:port]
|
22
22
|
|
23
|
+
puts 'Please enter your username to establish a connection...'
|
23
24
|
@request = request!
|
24
25
|
@response = listen!
|
25
26
|
|
@@ -29,12 +30,13 @@ module Whatup
|
|
29
30
|
exit
|
30
31
|
end
|
31
32
|
|
33
|
+
private
|
34
|
+
|
35
|
+
# Loop and send all input to the server
|
32
36
|
def request!
|
33
|
-
puts 'Please enter your username to establish a connection...'
|
34
37
|
Thread.new do
|
35
38
|
loop do
|
36
|
-
|
37
|
-
input = $stdin.gets&.chomp
|
39
|
+
input = Readline.readline '~> ', true
|
38
40
|
exit if input.nil?
|
39
41
|
@socket.puts input
|
40
42
|
end
|
@@ -44,11 +46,15 @@ module Whatup
|
|
44
46
|
@socket.close
|
45
47
|
end
|
46
48
|
|
49
|
+
# Continually listen to the server, and print anything received
|
47
50
|
def listen!
|
48
51
|
Thread.new do
|
49
52
|
loop do
|
50
53
|
response = @socket.gets&.chomp
|
51
|
-
|
54
|
+
|
55
|
+
exit if response == 'END'
|
56
|
+
|
57
|
+
puts response # unless response.nil?
|
52
58
|
end
|
53
59
|
end
|
54
60
|
rescue IOError => e
|
data/lib/whatup/server/client.rb
CHANGED
@@ -4,20 +4,52 @@ module Whatup
|
|
4
4
|
module Server
|
5
5
|
class Client
|
6
6
|
attr_reader :id, :name
|
7
|
-
attr_accessor
|
7
|
+
attr_accessor *%i[socket room]
|
8
8
|
|
9
9
|
def initialize id:, name:, socket:
|
10
10
|
@id = id
|
11
11
|
@name = name
|
12
12
|
@socket = socket
|
13
|
+
@room = nil
|
13
14
|
end
|
14
15
|
|
15
16
|
def puts msg
|
16
|
-
|
17
|
+
socket.puts msg
|
17
18
|
end
|
18
19
|
|
19
20
|
def gets
|
20
|
-
|
21
|
+
socket.gets
|
22
|
+
end
|
23
|
+
|
24
|
+
def input!
|
25
|
+
loop while (msg = gets).blank?
|
26
|
+
msg.chomp
|
27
|
+
end
|
28
|
+
|
29
|
+
def room?
|
30
|
+
!room.nil?
|
31
|
+
end
|
32
|
+
alias chatting? room?
|
33
|
+
|
34
|
+
def status
|
35
|
+
"#{name}" \
|
36
|
+
"#{chatting? ? " (#{@room.name})" : ''}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def broadcast msg
|
40
|
+
@room.clients.reject { |c| c == self }
|
41
|
+
.each { |c| c.puts "#{name}> #{msg}" }
|
42
|
+
end
|
43
|
+
|
44
|
+
def leave_room!
|
45
|
+
broadcast 'LEFT'
|
46
|
+
room.drop_client! self
|
47
|
+
@room = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def exit!
|
51
|
+
puts "END\n"
|
52
|
+
Thread.kill Thread.current
|
21
53
|
end
|
22
54
|
end
|
23
55
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Whatup
|
4
|
+
module Server
|
5
|
+
class Room
|
6
|
+
attr_accessor *%i[name clients]
|
7
|
+
|
8
|
+
def initialize name:, clients:
|
9
|
+
@name = name
|
10
|
+
@clients = clients
|
11
|
+
|
12
|
+
@clients.each { |c| c.room = self }
|
13
|
+
end
|
14
|
+
|
15
|
+
def drop_client! client
|
16
|
+
@clients = @clients.reject { |c| c == client }
|
17
|
+
end
|
18
|
+
|
19
|
+
def broadcast except: nil
|
20
|
+
clients = except \
|
21
|
+
? @clients.reject { |c| c == except }
|
22
|
+
: @clients
|
23
|
+
|
24
|
+
clients.each { |c| c.puts yield }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/whatup/server/server.rb
CHANGED
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'socket'
|
4
4
|
require 'fileutils'
|
5
|
+
require 'securerandom'
|
6
|
+
|
7
|
+
require 'active_support/core_ext/object/blank'
|
5
8
|
|
6
9
|
require 'whatup/server/client'
|
10
|
+
require 'whatup/server/room'
|
11
|
+
require 'whatup/cli/commands/interactive/interactive'
|
7
12
|
|
8
13
|
module Whatup
|
9
14
|
module Server
|
@@ -12,18 +17,26 @@ module Whatup
|
|
12
17
|
|
13
18
|
Client = Whatup::Server::Client
|
14
19
|
|
20
|
+
# Used by the interactive client cli
|
21
|
+
attr_reader *%i[ip port address clients max_id pid pid_file rooms]
|
22
|
+
|
15
23
|
def initialize port:
|
16
24
|
@ip = 'localhost'
|
17
25
|
@port = port
|
18
26
|
@address = "#{@ip}:#{@port}"
|
19
27
|
|
20
28
|
@clients = []
|
29
|
+
@rooms = []
|
21
30
|
@max_id = 1
|
22
31
|
|
23
32
|
@pid = Process.pid
|
24
33
|
@pid_file = "#{Dir.home}/.whatup.pid"
|
25
34
|
end
|
26
35
|
|
36
|
+
# Starts the server.
|
37
|
+
#
|
38
|
+
# The server continuously loops, and handle each new client in a separate
|
39
|
+
# thread.
|
27
40
|
def start
|
28
41
|
say "Starting a server with PID:#{@pid} @ #{@address} ... \n", :green
|
29
42
|
|
@@ -33,34 +46,136 @@ module Whatup
|
|
33
46
|
|
34
47
|
# Listen for connections, then accept each in a separate thread
|
35
48
|
loop do
|
36
|
-
Thread.new
|
37
|
-
handle_client client
|
49
|
+
Thread.new(@socket.accept) do |client|
|
50
|
+
case handle_client client
|
51
|
+
when :exit
|
52
|
+
client.puts 'bye!'
|
53
|
+
Thread.kill Thread.current
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
40
|
-
rescue SignalException
|
57
|
+
rescue SignalException # In case of ^c
|
41
58
|
kill
|
42
59
|
end
|
43
60
|
|
61
|
+
def find_client_by name:
|
62
|
+
@clients.select { |c| c.name == name }&.first
|
63
|
+
end
|
64
|
+
|
65
|
+
def new_room! clients: [], name:
|
66
|
+
room = Room.new name: name, clients: clients
|
67
|
+
@rooms << room
|
68
|
+
room
|
69
|
+
end
|
70
|
+
|
44
71
|
private
|
45
72
|
|
73
|
+
# Receives a new client, then continuously gets input from that client
|
74
|
+
#
|
75
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
46
76
|
def handle_client client
|
77
|
+
client = create_new_client_if_not_existing! client
|
78
|
+
|
79
|
+
# Loop forever to maintain the connection
|
80
|
+
loop do
|
81
|
+
handle_chatting(client) if client.chatting?
|
82
|
+
|
83
|
+
# Wait until we get a valid command. This takes as long as the client
|
84
|
+
# takes.
|
85
|
+
msg = client.input! unless Whatup::CLI::Interactive.command?(msg)
|
86
|
+
|
87
|
+
puts "#{client.name}> #{msg}"
|
88
|
+
|
89
|
+
# Initialize a new cli class using the initial command and options,
|
90
|
+
# and then set any instance variables, since Thor will create a new
|
91
|
+
# class instance when it's invoked.
|
92
|
+
cmds, opts = Whatup::CLI::Interactive.parse_input msg
|
93
|
+
cli = Whatup::CLI::Interactive.new(cmds, opts).tap do |c|
|
94
|
+
c.server = self
|
95
|
+
c.current_user = client
|
96
|
+
end
|
97
|
+
|
98
|
+
begin
|
99
|
+
# Send the output to the client
|
100
|
+
redirect stdin: client.socket, stdout: client.socket do
|
101
|
+
# Invoke the cli using the provided commands and options.
|
102
|
+
|
103
|
+
# This _should_ achieve the same effect as
|
104
|
+
# `Whatup::CLI::Interactive.start(args)`, but allows us to set
|
105
|
+
# instance variables on the cli class.
|
106
|
+
cli.invoke cli.args.first, cli.args[1..cli.args.size - 1]
|
107
|
+
end
|
108
|
+
rescue RuntimeError,
|
109
|
+
Thor::InvocationError,
|
110
|
+
Thor::UndefinedCommandError => e
|
111
|
+
puts e.message
|
112
|
+
client.puts 'Invalid input or unknown command'
|
113
|
+
rescue ArgumentError => e
|
114
|
+
puts e.message
|
115
|
+
client.puts e.message
|
116
|
+
end
|
117
|
+
msg = nil # rubocop:disable Lint/UselessAssignment
|
118
|
+
end
|
119
|
+
end
|
120
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
121
|
+
|
122
|
+
def handle_chatting client
|
123
|
+
loop do
|
124
|
+
input = client.input!
|
125
|
+
room = client.room
|
126
|
+
puts "#{client.name}> #{input}"
|
127
|
+
if input == '.exit'
|
128
|
+
client.leave_room!
|
129
|
+
break
|
130
|
+
end
|
131
|
+
room.broadcast except: client do
|
132
|
+
"#{client.name}> #{input}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Receives a username from a client, then creates a new client unless a
|
138
|
+
# client with that username already exists.
|
139
|
+
#
|
140
|
+
# If no username is provided (i.e, blank), it assigns a random, anonymous
|
141
|
+
# username in the format `ANON-xxx`, where `xxx` is a random number upto
|
142
|
+
# 100, left-padded with zeros.
|
143
|
+
def create_new_client_if_not_existing! client
|
144
|
+
name = client.gets.chomp
|
145
|
+
rand_num = SecureRandom.random_number(100).to_s.rjust 3, '0'
|
146
|
+
name = name == '' ? "ANON-#{rand_num}" : name
|
147
|
+
|
148
|
+
if @clients.any? { |c| c.name == name }
|
149
|
+
client.puts 'That name is taken! Goodbye.'
|
150
|
+
client.exit!
|
151
|
+
end
|
152
|
+
|
47
153
|
@clients << client = Client.new(
|
48
|
-
id:
|
49
|
-
name:
|
154
|
+
id: new_client_id,
|
155
|
+
name: name,
|
50
156
|
socket: client
|
51
157
|
)
|
52
158
|
|
53
159
|
puts "#{client.name} just showed up!"
|
54
160
|
client.puts "Hello, #{client.name}!"
|
161
|
+
client
|
162
|
+
end
|
55
163
|
|
56
|
-
|
57
|
-
|
58
|
-
|
164
|
+
# @return A new, unique client identification number
|
165
|
+
def new_client_id
|
166
|
+
@max_id += 1
|
167
|
+
end
|
59
168
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
169
|
+
# Reroutes stdin and stdout inside a block
|
170
|
+
def redirect stdin: $stdin, stdout: $stdout
|
171
|
+
original_stdin = $stdin
|
172
|
+
original_stdout = $stdout
|
173
|
+
$stdin = stdin
|
174
|
+
$stdout = stdout
|
175
|
+
yield
|
176
|
+
ensure
|
177
|
+
$stdin = original_stdin
|
178
|
+
$stdout = original_stdout
|
64
179
|
end
|
65
180
|
|
66
181
|
def exit_if_pid_exists!
|
@@ -92,6 +207,7 @@ module Whatup
|
|
92
207
|
def kill
|
93
208
|
say "Killing the server with PID:#{Process.pid} ...", :red
|
94
209
|
FileUtils.rm_rf @pid_file
|
210
|
+
exit
|
95
211
|
end
|
96
212
|
end
|
97
213
|
end
|
data/lib/whatup/version.rb
CHANGED
data/whatup.gemspec
CHANGED
@@ -56,7 +56,9 @@ Gem::Specification.new do |spec|
|
|
56
56
|
'rake' => '~> 12.3.2',
|
57
57
|
'rspec' => '~> 3.8',
|
58
58
|
'yard' => '~> 0.9.18',
|
59
|
-
'rubocop' => '~> 0.65.0'
|
59
|
+
'rubocop' => '~> 0.65.0',
|
60
|
+
'aruba' => '~> 0.14.9',
|
61
|
+
'activesupport' => '~> 5.2'
|
60
62
|
}.each do |gem, version|
|
61
63
|
spec.add_development_dependency gem, version
|
62
64
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whatup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Delk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 0.65.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: aruba
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.14.9
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.14.9
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activesupport
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '5.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '5.2'
|
111
139
|
- !ruby/object:Gem::Dependency
|
112
140
|
name: thor
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,15 +179,19 @@ files:
|
|
151
179
|
- bin/console
|
152
180
|
- bin/setup
|
153
181
|
- docs/hw/assignment.pdf
|
182
|
+
- docs/hw/framework.pdf
|
154
183
|
- docs/hw/inital_design.md
|
155
184
|
- docs/installing_ruby.md
|
156
185
|
- exe/whatup
|
157
186
|
- lib/whatup.rb
|
158
187
|
- lib/whatup/cli/cli.rb
|
159
188
|
- lib/whatup/cli/commands/client.rb
|
189
|
+
- lib/whatup/cli/commands/interactive/interactive.rb
|
190
|
+
- lib/whatup/cli/commands/interactive/setup.rb
|
160
191
|
- lib/whatup/cli/commands/server.rb
|
161
192
|
- lib/whatup/client/client.rb
|
162
193
|
- lib/whatup/server/client.rb
|
194
|
+
- lib/whatup/server/room.rb
|
163
195
|
- lib/whatup/server/server.rb
|
164
196
|
- lib/whatup/version.rb
|
165
197
|
- whatup.gemspec
|