/nome SeuNome")Lembrando os bons velhos tempos do IRC, o metodo processa_comandos reconhece comandos iniciados pela barra /. Desta forma, caso um cliente envie para o servidor /horas, este retornara a hora atual do servidor. Implementamos tambem os comandos:/data que envia a data atual;/clientes que envia quantos clientes estao conectados ao servidor, /nome e /apenas que veremos mais adiante. Utilizamos o modulo shlex para simplificar o processamento dos comandos, uma vez que a funcao shlex.split permite processar uma linha de texto como uma linha de comandos do bash, reconhecendo valores entre aspas e retirando os espacos em branco entre os parametros. Caso o usuario envie uma mensagem que nao se inicia por uma barra, esta mensagem sera enviada a todos os outros usuarios conectados.Para melhorar nosso chat, utilizamos o comando /nome para configurar nosso nome. O servidor cuida para que apenas um usuario utilize cada nome, retornando uma mensagem de erro, caso o nome desejado ja esteja em uso. Este comando e processado pelo metodo altera_nome da classe Cliente: @asyncio.coroutine def altera_nome(self, comandos): if len(comandos)>1 and self.servidor.verifica_nome(comandos[1]): self.nome = comandos[1] yield from self.envia("Nome alterado com sucesso para {0}".format(self.nome)) else: yield from self.envia("Nome em uso ou invalido. Escolha um outro.")O metodo altera_nome simplesmente verifica se passamos um parametro depois do comando /nome, pois comandos e uma lista onde cada elemento e um parametro (mas o primeiro e o nome do comando em si). Usando o metodo verifica_nome do servidor, checamos se o nome e unico e enviamos uma mensagem de confirmacao ou de erro dependendo do resultado. O metodo verifica_nome da classe Servidor e apresentado abaixo: def verifica_nome(self, nome): for cliente in self.conectados: if cliente.nome and cliente.nome == nome: return False return TrueA verificacao percorre toda a lista com os clientes conectados e verifica se um nome igual ja foi registrado. Caso nao encontre o nome na lista dos clientes ja conectados, retorna True, permitindo o registro do nome pelo cliente que o solicitou.Um outro comando interessante e o /apenas que permite enviarmos uma mensagem apenas para determinado cliente. Vejamos a implementacao do metodo apenas_para no cliente: @asyncio.coroutine def apenas_para(self, comandos): if len(comandos)<3: yield from self.envia("Comando incorreto. /apenas Destinatario mensagem") return destinatario = comandos[1] mensagem = " ".join(comandos[2:]) enviado = yield from self.servidor.envia_a_destinatario(self, mensagem, destinatario) if not enviado: yield from self.envia("Destinatario {0} nao encontrado. Mensagem nao enviada.".format(destinatario))E do metodo que realiza o envio na classe Servidor: @asyncio.coroutine def envia_a_destinatario(self, origem, mensagem, destinatario): for cliente in self.conectados: if cliente.nome == destinatario and origem != cliente and cliente.conectado: print("Enviando de <{0}> para <{1}>: {2}".format(origem.nome, cliente.nome, mensagem)) yield from cliente.envia("PRIVADO de {0} >> {1}".format(origem.nome, mensagem)) return True return FalseUm outro metodo importante e o que envia uma mensagem a todos os clientes conectados: @asyncio.coroutine def envia_a_todos(self, origem, mensagem): print("Enviando a todos") for cliente in self.conectados: if origem != cliente and cliente.conectado: print("Enviando de <{0}> para <{1}>: {2}".format(origem.nome, cliente.nome, mensagem)) yield from cliente.envia("{0} >> {1}".format(origem.nome, mensagem))Veja que enviamos a mensagem a todos da lista, mas que tomamos o cuidado para nao enviar a mensagem ao mesmo cliente que a enviou, pois esta seria impressa uma segunda vez e