whatup 0.2.4 → 0.2.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 391ddb29c708ee7cf37769dc7aa3723d65e420fe08a268862bff6ec7ff5e659f
4
- data.tar.gz: b7e349838c88b72f3fbb04258afa114b124f460af40b99d64654bb5b941c04f3
3
+ metadata.gz: 0ace83a0aa8e24fb44a1f6900f8cdcaf201e7d8d9661883d1bb0ec8fdadf7fd6
4
+ data.tar.gz: 56b91c405097272ca64cbf9d78b4c6c02fd8749ce883838369b933b618c53552
5
5
  SHA512:
6
- metadata.gz: 6f8458ee475df4aa40d81cd3c126cea7d0153ba3ab2c3d56ec7ff92e130ae1b2765b5594a7a780584498a74d2808779d7024e412d724acad919665b8b339acf3
7
- data.tar.gz: e84e5379f28eec45311b4ab0aeea6ec67b45dadea2240f06f3c7dcc33a4094784ad081e6fc1bffa8e57d0c4cbc30248c7a55e663923d95e73b1de89698355316
6
+ metadata.gz: 1664ad2e6d346c84d4509fe166744e2f863889d59a968f21db9188989eabf87e4e927045530926a51dc80e2ffdd6734f252642fb0b645139b177319399eb97c6
7
+ data.tar.gz: 4ee3b633248639ff80215487a2d2820fc7e01a5b6b8923574f464b9255de77443febae039cb9e6cfa8444a2c2e649c7a3597ad82de66127039c6e373a2158168
data/.gitignore CHANGED
@@ -16,3 +16,6 @@ vagrant/*
16
16
 
17
17
  # Since this is a gem, don't include the lock file
18
18
  Gemfile.lock
19
+
20
+ # Ignore the database
21
+ db/*.db
data/README.md CHANGED
@@ -7,6 +7,9 @@ whatup is a simple server-based instant messaging application
7
7
  Check it out on [rubygems.org](https://rubygems.org/gems/whatup).
8
8
 
9
9
  [![Build Status](https://travis-ci.com/jethrodaniel/whatup.svg?branch=dev)](https://travis-ci.com/jethrodaniel/whatup)
10
+ [![Maintainability](https://api.codeclimate.com/v1/badges/e5356174302d82cf67cb/maintainability)](https://codeclimate.com/github/jethrodaniel/whatup/maintainability)
11
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/test_coverage)](https://codeclimate.com/github/codeclimate/codeclimate/test_coverage)
12
+ [![Gem Version](https://badge.fury.io/rb/whatup.svg)](https://badge.fury.io/rb/whatup)
10
13
 
11
14
  ## Installation
12
15
 
data/db/.keep ADDED
File without changes
@@ -8,7 +8,13 @@ module Whatup
8
8
  module CLI
9
9
  # Any methods of class `Whatup::CLI::Interactive` that rely on instance
10
10
  # variables should be included here
11
- COMMANDS = %i[room list exit].freeze
11
+ COMMANDS = %i[
12
+ room
13
+ list
14
+ exit
15
+ dmlist
16
+ dm
17
+ ].freeze
12
18
 
13
19
  require 'whatup/cli/commands/interactive/setup'
14
20
 
@@ -18,6 +24,9 @@ module Whatup
18
24
  class Interactive < Thor
19
25
  prepend InteractiveSetup
20
26
 
27
+ Room = Whatup::Server::Room
28
+ Client = Whatup::Server::Client
29
+
21
30
  attr_accessor *%i[server current_user]
22
31
 
23
32
  no_commands do
@@ -57,12 +66,13 @@ module Whatup
57
66
  desc 'list', 'Show all connected clients'
58
67
  def list
59
68
  say 'All connected clients:'
60
- @server.clients.each { |c| say c.status }
69
+ @server.clients_except(@current_user).each { |c| say " #{c.status}" }
70
+ say "* #{@current_user.status}"
61
71
  end
62
72
 
63
73
  desc 'room [NAME]', 'Create and enter chatroom [NAME]'
64
74
  def room name
65
- if room = @server.rooms.select { |r| r.name == name }&.first
75
+ if room = Room.find_by(name: name)
66
76
  @current_user.puts <<~MSG
67
77
  Entering #{room.name}... enjoy your stay!
68
78
 
@@ -73,7 +83,7 @@ module Whatup
73
83
  "- #{client.name}\n"
74
84
  end.join}
75
85
  MSG
76
- @current_user.room = room
86
+ @current_user.update! room: room
77
87
 
78
88
  room.broadcast except: @current_user do
79
89
  <<~MSG
@@ -94,17 +104,35 @@ module Whatup
94
104
  MSG
95
105
  end
96
106
 
97
- # desc 'dm [NAME]', 'Send a direct message to [NAME]'
98
- # def dm name
99
- # client = @server.find_client_by name: name
107
+ desc 'dmlist', 'List your received messages'
108
+ def dmlist
109
+ say 'Your direct messages:'
110
+ msgs = @current_user.received_messages.map do |msg|
111
+ <<~MSG
112
+ From: #{msg.sender.name}
113
+
114
+ #{msg.content}
115
+ MSG
116
+ end.join('-' * 10)
117
+ say msgs
118
+ end
119
+
120
+ desc 'dm [NAME]', 'Send a direct message to [NAME]'
121
+ def dm name
122
+ if recepient = Client.find_by(name: name)
123
+ say <<~MSG
124
+ Sending a direct message to #{name}...
100
125
 
101
- # if client.nil?
102
- # @current_user.puts "No client named `#{name}` found!"
103
- # return
104
- # end
126
+ The message can span multiple lines.
105
127
 
106
- # client.send_message
107
- # end
128
+ Type `.exit` when you're ready to send it.
129
+ MSG
130
+ @current_user.composing_dm = recepient
131
+ return
132
+ end
133
+
134
+ say "That user doesn't exist!"
135
+ end
108
136
 
109
137
  desc 'exit', 'Closes your connection with the server'
110
138
  def exit
@@ -37,7 +37,8 @@ module Whatup
37
37
  Thread.new do
38
38
  loop do
39
39
  input = Readline.readline '~> ', true
40
- exit if input.nil?
40
+ next if input.nil?
41
+
41
42
  @socket.puts input
42
43
  end
43
44
  end
@@ -52,7 +53,11 @@ module Whatup
52
53
  loop do
53
54
  response = @socket.gets&.chomp
54
55
 
55
- exit if response == 'END'
56
+ if response == 'END'
57
+ puts
58
+ kill_all_but_current_thread!
59
+ exit
60
+ end
56
61
 
57
62
  puts response # unless response.nil?
58
63
  end
@@ -61,6 +66,12 @@ module Whatup
61
66
  puts e.message
62
67
  @socket.close
63
68
  end
69
+
70
+ def kill_all_but_current_thread!
71
+ Thread.list.each do |thread|
72
+ thread.exit unless thread == Thread.current
73
+ end
74
+ end
64
75
  end
65
76
  end
66
77
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'whatup'
4
+ require 'whatup/server/redirection'
5
+
6
+ module Whatup
7
+ module Server
8
+ module DbInit
9
+ extend Redirection
10
+
11
+ class << self
12
+ def setup_db!
13
+ db = "#{Whatup.root}/db/whatup.db"
14
+ SQLite3::Database.new(db) unless File.exist?(db)
15
+
16
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3',
17
+ database: db
18
+
19
+ ActiveRecord::Base.connection.execute <<~SQL
20
+ DROP TABLE IF EXISTS clients_rooms;
21
+ DROP TABLE IF EXISTS clients;
22
+ DROP TABLE IF EXISTS messages;
23
+ DROP TABLE IF EXISTS rooms;
24
+ SQL
25
+
26
+ redirect(stdout: StringIO.new) { create_tables! }
27
+ end
28
+
29
+ private
30
+
31
+ def create_tables!
32
+ ActiveRecord::Schema.define do
33
+ create_table :clients, force: true do |t|
34
+ t.string :name
35
+ t.references :room
36
+ end
37
+ create_table :messages, force: true do |t|
38
+ t.string :content
39
+ t.references :sender
40
+ t.references :recipient
41
+ end
42
+ create_table :rooms, force: true do |t|
43
+ t.string :name
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'whatup/server/models/application_record'
4
+
5
+ module Whatup
6
+ module Server
7
+ class Client < ApplicationRecord
8
+ has_many :sent_messages, class_name: 'Message',
9
+ foreign_key: 'sender_id'
10
+ has_many :received_messages, class_name: 'Message',
11
+ foreign_key: 'recipient_id'
12
+
13
+ belongs_to :room, optional: true
14
+
15
+ validates_uniqueness_of :name
16
+
17
+ attr_accessor *%i[socket composing_dm deleted]
18
+
19
+ def puts msg
20
+ socket.puts msg
21
+ end
22
+
23
+ def gets
24
+ socket.gets
25
+ end
26
+
27
+ def input!
28
+ loop while (msg = gets).blank?
29
+ msg.chomp
30
+ end
31
+
32
+ def chatting?
33
+ !room_id.nil?
34
+ end
35
+
36
+ def composing_dm?
37
+ !composing_dm.nil?
38
+ end
39
+
40
+ def status
41
+ "#{name}#{chatting? ? " (#{room.name})" : ''}"
42
+ end
43
+
44
+ def broadcast msg
45
+ room.broadcast(except: self) { "#{name}> #{msg}" }
46
+ end
47
+
48
+ def leave_room!
49
+ broadcast 'LEFT'
50
+ room.drop_client! self
51
+ end
52
+
53
+ def exit!
54
+ puts 'END'
55
+ socket.close
56
+ @deleted = true
57
+ destroy!
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'whatup/server/models/application_record'
4
+
5
+ module Whatup
6
+ module Server
7
+ class Message < ApplicationRecord
8
+ belongs_to :recipient, class_name: 'Client'
9
+ belongs_to :sender, class_name: 'Client', foreign_key: 'sender_id'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'whatup/server/models/application_record'
4
+
5
+ module Whatup
6
+ module Server
7
+ class Room < ApplicationRecord
8
+ has_many :clients
9
+
10
+ validates :name, uniqueness: true
11
+
12
+ def drop_client! client
13
+ client.update! room_id: nil
14
+ end
15
+
16
+ def broadcast except: nil
17
+ if except
18
+ clients.where.not id: except.id
19
+ else
20
+ clients
21
+ end.each { |c| c.puts yield }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whatup
4
+ module Server
5
+ module Redirection
6
+ # Reroutes stdin and stdout inside a block
7
+ def redirect stdin: $stdin, stdout: $stdout
8
+ original_stdin = $stdin
9
+ original_stdout = $stdout
10
+ $stdin = stdin
11
+ $stdout = stdout
12
+ yield
13
+ ensure
14
+ $stdin = original_stdin
15
+ $stdout = original_stdout
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,33 +4,40 @@ require 'socket'
4
4
  require 'fileutils'
5
5
  require 'securerandom'
6
6
 
7
+ require 'sqlite3'
8
+ require 'active_record'
7
9
  require 'active_support/core_ext/object/blank'
8
10
 
9
- require 'whatup/server/client'
10
- require 'whatup/server/room'
11
+ require 'whatup/server/db_init'
12
+ require 'whatup/server/redirection'
13
+ require 'whatup/server/models/client'
14
+ require 'whatup/server/models/message'
15
+ require 'whatup/server/models/room'
11
16
  require 'whatup/cli/commands/interactive/interactive'
12
17
 
13
18
  module Whatup
14
19
  module Server
15
- class Server
20
+ class Server # rubocop:disable Metrics/ClassLength
16
21
  include Thor::Shell
22
+ include DbInit
23
+ include Redirection
17
24
 
18
25
  Client = Whatup::Server::Client
19
26
 
20
- # Used by the interactive client cli
21
- attr_reader *%i[ip port address clients max_id pid pid_file rooms]
27
+ attr_reader *%i[ip port address clients pid pid_file rooms]
22
28
 
23
- def initialize port:
24
- @ip = 'localhost'
29
+ def initialize ip: 'localhost', port:
30
+ @ip = ip
25
31
  @port = port
26
32
  @address = "#{@ip}:#{@port}"
27
33
 
28
34
  @clients = []
29
35
  @rooms = []
30
- @max_id = 1
31
36
 
32
37
  @pid = Process.pid
33
38
  @pid_file = "#{Dir.home}/.whatup.pid"
39
+
40
+ DbInit.setup_db!
34
41
  end
35
42
 
36
43
  # Starts the server.
@@ -62,8 +69,12 @@ module Whatup
62
69
  @clients.select { |c| c.name == name }&.first
63
70
  end
64
71
 
72
+ def clients_except client
73
+ @clients.reject { |c| c == client }
74
+ end
75
+
65
76
  def new_room! clients: [], name:
66
- room = Room.new name: name, clients: clients
77
+ room = Room.create! name: name, clients: clients
67
78
  @rooms << room
68
79
  room
69
80
  end
@@ -72,13 +83,21 @@ module Whatup
72
83
 
73
84
  # Receives a new client, then continuously gets input from that client
74
85
  #
75
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
86
+ # rubocop:disable Metrics/MethodLength
76
87
  def handle_client client
77
88
  client = create_new_client_if_not_existing! client
78
89
 
79
90
  # Loop forever to maintain the connection
80
91
  loop do
81
- handle_chatting(client) if client.chatting?
92
+ @clients.reject! &:deleted
93
+
94
+ Thread.current.exit if client.deleted
95
+
96
+ if client.composing_dm?
97
+ handle_dm client
98
+ elsif client.chatting?
99
+ handle_chatting client
100
+ end
82
101
 
83
102
  # Wait until we get a valid command. This takes as long as the client
84
103
  # takes.
@@ -86,24 +105,11 @@ module Whatup
86
105
 
87
106
  puts "#{client.name}> #{msg}"
88
107
 
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
108
  begin
99
109
  # Send the output to the client
100
110
  redirect stdin: client.socket, stdout: client.socket do
101
111
  # 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]
112
+ run_thor_command! client: client, msg: msg
107
113
  end
108
114
  rescue RuntimeError,
109
115
  Thor::InvocationError,
@@ -114,10 +120,29 @@ module Whatup
114
120
  puts e.message
115
121
  client.puts e.message
116
122
  end
117
- msg = nil # rubocop:disable Lint/UselessAssignment
123
+ msg = nil
118
124
  end
119
125
  end
120
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
126
+ # rubocop:enable Metrics/MethodLength
127
+
128
+ def handle_dm client
129
+ msg = StringIO.new
130
+ loop do
131
+ input = client.input!
132
+ puts "#{client.name}> #{input}"
133
+ if input == '.exit'
134
+ client.puts "Finished dm to `#{client.composing_dm.name}`."
135
+ break
136
+ end
137
+ msg.puts input
138
+ end
139
+ client.composing_dm
140
+ .received_messages << Message.new(
141
+ sender: client,
142
+ content: msg.string
143
+ )
144
+ client.composing_dm = nil
145
+ end
121
146
 
122
147
  def handle_chatting client
123
148
  loop do
@@ -126,6 +151,7 @@ module Whatup
126
151
  puts "#{client.name}> #{input}"
127
152
  if input == '.exit'
128
153
  client.leave_room!
154
+ client.puts "Exited `#{room.name}`."
129
155
  break
130
156
  end
131
157
  room.broadcast except: client do
@@ -147,35 +173,41 @@ module Whatup
147
173
 
148
174
  if @clients.any? { |c| c.name == name }
149
175
  client.puts 'That name is taken! Goodbye.'
150
- client.exit!
176
+ client.puts 'END'
177
+ client.close
178
+ Thread.current.exit
151
179
  end
152
180
 
153
- @clients << client = Client.new(
154
- id: new_client_id,
181
+ @clients << client = Client.create!(
155
182
  name: name,
156
183
  socket: client
157
184
  )
158
185
 
159
186
  puts "#{client.name} just showed up!"
160
- client.puts "Hello, #{client.name}!"
161
- client
162
- end
187
+ client.puts <<~MSG
188
+ Hello, #{client.name}!
189
+
190
+ Welcome to whatup.
163
191
 
164
- # @return A new, unique client identification number
165
- def new_client_id
166
- @max_id += 1
192
+ To get started, type `help`.
193
+ MSG
194
+ client
167
195
  end
168
196
 
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
197
+ def run_thor_command! client:, msg:
198
+ # Initialize a new cli class using the initial command and options,
199
+ # and then set any instance variables, since Thor will create a new
200
+ # class instance when it's invoked.
201
+ cmds, opts = Whatup::CLI::Interactive.parse_input msg
202
+ Whatup::CLI::Interactive.new(cmds, opts).tap do |c|
203
+ c.server = self
204
+ c.current_user = client
205
+
206
+ # This _should_ achieve the same effect as
207
+ # `Whatup::CLI::Interactive.start(args)`, but allows us to set
208
+ # instance variables on the cli class.
209
+ c.invoke c.args.first, c.args.drop(1)
210
+ end
179
211
  end
180
212
 
181
213
  def exit_if_pid_exists!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Whatup
4
- VERSION = '0.2.4'
4
+ VERSION = '0.2.5'
5
5
  end
data/lib/whatup.rb CHANGED
@@ -7,4 +7,8 @@ module Whatup
7
7
  # Whatup-specific error class
8
8
  class Error < StandardError
9
9
  end
10
+
11
+ def self.root
12
+ Dir.pwd
13
+ end
10
14
  end
data/whatup.gemspec CHANGED
@@ -49,23 +49,27 @@ Gem::Specification.new do |spec|
49
49
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
50
50
  spec.require_paths = ['lib']
51
51
 
52
+ # rubocop:disable Layout/AlignHash
52
53
  {
53
- 'pry' => '~> 0.12.2',
54
+ 'pry' => '~> 0.12.2',
54
55
  'pry-byebug' => '~> 3.7',
55
- 'bundler' => '~> 2.0',
56
- 'rake' => '~> 12.3.2',
57
- 'rspec' => '~> 3.8',
58
- 'yard' => '~> 0.9.18',
59
- 'rubocop' => '~> 0.65.0',
60
- 'aruba' => '~> 0.14.9',
61
- 'activesupport' => '~> 5.2'
56
+ 'bundler' => '~> 2.0',
57
+ 'rake' => '~> 12.3.2',
58
+ 'rspec' => '~> 3.8',
59
+ 'yard' => '~> 0.9.18',
60
+ 'rubocop' => '~> 0.65.0',
61
+ 'aruba' => '~> 0.14.9'
62
62
  }.each do |gem, version|
63
63
  spec.add_development_dependency gem, version
64
64
  end
65
65
 
66
66
  {
67
- 'thor' => '~> 0.20.3'
67
+ 'activesupport' => '~> 5.2',
68
+ 'thor' => '~> 0.20.3',
69
+ 'sqlite3' => '~> 1.4',
70
+ 'activerecord' => '~> 5.2'
68
71
  }.each do |gem, version|
69
72
  spec.add_dependency gem, version
70
73
  end
74
+ # rubocop:enable Layout/AlignHash
71
75
  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
4
+ version: 0.2.5
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-04-04 00:00:00.000000000 Z
11
+ date: 2019-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -129,7 +129,7 @@ dependencies:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
131
  version: '5.2'
132
- type: :development
132
+ type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
@@ -150,6 +150,34 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.20.3
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.4'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.4'
167
+ - !ruby/object:Gem::Dependency
168
+ name: activerecord
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '5.2'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '5.2'
153
181
  description: |
154
182
  whatup is a simple server-based instant messaging application using TCP
155
183
  sockets.
@@ -178,6 +206,7 @@ files:
178
206
  - Rakefile
179
207
  - bin/console
180
208
  - bin/setup
209
+ - db/.keep
181
210
  - docs/hw/assignment.pdf
182
211
  - docs/hw/framework.pdf
183
212
  - docs/hw/inital_design.md
@@ -190,8 +219,12 @@ files:
190
219
  - lib/whatup/cli/commands/interactive/setup.rb
191
220
  - lib/whatup/cli/commands/server.rb
192
221
  - lib/whatup/client/client.rb
193
- - lib/whatup/server/client.rb
194
- - lib/whatup/server/room.rb
222
+ - lib/whatup/server/db_init.rb
223
+ - lib/whatup/server/models/application_record.rb
224
+ - lib/whatup/server/models/client.rb
225
+ - lib/whatup/server/models/message.rb
226
+ - lib/whatup/server/models/room.rb
227
+ - lib/whatup/server/redirection.rb
195
228
  - lib/whatup/server/server.rb
196
229
  - lib/whatup/version.rb
197
230
  - whatup.gemspec
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Whatup
4
- module Server
5
- class Client
6
- attr_reader :id, :name
7
- attr_accessor *%i[socket room]
8
-
9
- def initialize id:, name:, socket:
10
- @id = id
11
- @name = name
12
- @socket = socket
13
- @room = nil
14
- end
15
-
16
- def puts msg
17
- socket.puts msg
18
- end
19
-
20
- def gets
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
53
- end
54
- end
55
- end
56
- end
@@ -1,28 +0,0 @@
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