lib/whatup/server/server.rb in whatup-0.2.5 vs lib/whatup/server/server.rb in whatup-0.3.0
- old
+ new
@@ -24,10 +24,14 @@
Client = Whatup::Server::Client
attr_reader *%i[ip port address clients pid pid_file rooms]
+ # @param ip [String] The ip address to run the server on
+ # @param port [Integer] The port to run the server on
+ #
+ # @return [Whatup::Server::Server] The created server
def initialize ip: 'localhost', port:
@ip = ip
@port = port
@address = "#{@ip}:#{@port}"
@@ -51,40 +55,40 @@
connect_to_socket!
write_pid!
# Listen for connections, then accept each in a separate thread
loop do
- Thread.new(@socket.accept) do |client|
- case handle_client client
- when :exit
- client.puts 'bye!'
- Thread.kill Thread.current
- end
- end
+ Thread.new(@socket.accept) { |client| handle_client client }
end
rescue SignalException # In case of ^c
kill
end
- def find_client_by name:
- @clients.select { |c| c.name == name }&.first
- end
-
+ # @param client [Whatup::Server::Client] The client to not retrieve
+ #
+ # @return [Array<Whatup::Server::Client>] All currently connected clients
+ # except for `client`
def clients_except client
@clients.reject { |c| c == client }
end
+ # @param clients [Array<Whatup::Server::Client>] Room's inital clients
+ # @param name [String] The room's name
+ #
+ # @return [Whatup::Server::Room] The created room
def new_room! clients: [], name:
room = Room.create! name: name, clients: clients
@rooms << room
room
end
private
# Receives a new client, then continuously gets input from that client
#
+ # @param client [Whatup::Server::Client] The client
+ #
# rubocop:disable Metrics/MethodLength
def handle_client client
client = create_new_client_if_not_existing! client
# Loop forever to maintain the connection
@@ -123,10 +127,14 @@
msg = nil
end
end
# rubocop:enable Metrics/MethodLength
+ # Handles inputing direct messages
+ #
+ # @param client [Whatup::Server::Client] `client` is the sender of
+ # the message, and `client.composing_dm` is the recipient.
def handle_dm client
msg = StringIO.new
loop do
input = client.input!
puts "#{client.name}> #{input}"
@@ -142,10 +150,14 @@
content: msg.string
)
client.composing_dm = nil
end
+ # Handles chatting.
+ #
+ # @param client [Whatup::Server::Client] The client. `client` is assumed
+ # to already belong to a room
def handle_chatting client
loop do
input = client.input!
room = client.room
puts "#{client.name}> #{input}"
@@ -164,10 +176,14 @@
# client with that username already exists.
#
# If no username is provided (i.e, blank), it assigns a random, anonymous
# username in the format `ANON-xxx`, where `xxx` is a random number upto
# 100, left-padded with zeros.
+ #
+ # @param client [TCPSocket] The client connection
+ #
+ # @return [Whatup::Server::Client] The created client
def create_new_client_if_not_existing! client
name = client.gets.chomp
rand_num = SecureRandom.random_number(100).to_s.rjust 3, '0'
name = name == '' ? "ANON-#{rand_num}" : name
@@ -192,26 +208,30 @@
To get started, type `help`.
MSG
client
end
+ # Initialize a new cli class using the initial command and options,
+ # and then set any instance variables, since Thor will create a new
+ # class instance when it's invoked.
+ #
+ # This achieve the same effect as
+ # `Whatup::CLI::Interactive.start(args)`, but allows us to set
+ # instance variables on the cli class.
+ #
+ # @param client [Whatup::Server::Client]
def run_thor_command! client:, msg:
- # Initialize a new cli class using the initial command and options,
- # and then set any instance variables, since Thor will create a new
- # class instance when it's invoked.
cmds, opts = Whatup::CLI::Interactive.parse_input msg
- Whatup::CLI::Interactive.new(cmds, opts).tap do |c|
- c.server = self
- c.current_user = client
-
- # This _should_ achieve the same effect as
- # `Whatup::CLI::Interactive.start(args)`, but allows us to set
- # instance variables on the cli class.
- c.invoke c.args.first, c.args.drop(1)
- end
+ cli = Whatup::CLI::Interactive.new(
+ cmds,
+ opts,
+ locals: {server: self, current_user: client} # config
+ )
+ cli.invoke cli.args.first, cli.args.drop(1)
end
+ # Kills the server if a PID for this app exists
def exit_if_pid_exists!
return unless running?
say <<~EXIT, :cyan
A server appears to already be running!
@@ -219,24 +239,29 @@
EXIT
kill
end
+ # Connect a new socket for this server to start listening on the specified
+ # address and port.
def connect_to_socket!
- @socket = TCPServer.open @port
+ @socket = TCPServer.open @ip, @port
rescue Errno::EADDRINUSE
puts 'Address already in use!'
kill
end
+ # Write this process's PID to the PID file
def write_pid!
File.open(@pid_file, 'w') { |f| f.puts Process.pid }
end
+ # @return [Bool] Whether or not a PID for this app exists
def running?
File.file? @pid_file
end
+ # Kills the server and removes the PID file
def kill
say "Killing the server with PID:#{Process.pid} ...", :red
FileUtils.rm_rf @pid_file
exit
end