<commit_before>from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
import threading
import chatroom

class Chat(LineReceiver):

    lock = threading.Lock()
    rooms = {}
    MAX_USERNAME = 64

    def __init__(self, users):
        self.users = users
        self.name = None
        self.state = "INTRO"
        self.room = None

    def connectionMade(self):
        self.sendLine("Welcome to the fenfiresong chat server\nLogin Name?")

    def connectionLost(self, reason):
        if self.name in self.users:
            del self.users[self.name]

    def lineReceived(self, line):
        if self.state == "INTRO":
            self.handle_INTRO(line)
        else:
            self.handle_CHAT(line)

    def handle_INTRO(self, name):
        name = name.strip()
        if name in self.users:
            self.sendLine("Sorry, name taken.\nLogin Name?")
            return
        if name == "":
            self.sendLine("Your name can't be empty.\nLogin Name?")
            return
        if name.startswith("/"):
            self.sendLine("Don't start your name with /, that's used for commands.\nLogin Name?")
            return
        if len(name) > Chat.MAX_USERNAME:
            self.sendLine("Your name can't be longer than {} characters.\nLogin Name?".format(Chat.MAX_USERNAME))
            return
        self.sendLine("Welcome, {}!".format(name))
        self.name = name
        self.users[name] = self
        self.state = "CHAT"

    def handle_CHAT(self, message):
        if message.startswith("/rooms"):
            self.command_rooms()
        elif message.startswith("/join"):
            self.command_join(message)
        elif message.startswith("/leave"):
            self.command_leave()
        elif message.startswith("/quit"):
            self.command_quit()
        elif self.room == None:
            self.sendLine("You're not in any room! Use /rooms to list active rooms and use /join <room> to enter or create a room.")
        else:
            message = "<{}> {}".format(self.name, message)
            self.sendLine(message)
            self.send_to_chatroom(message)

    def send_to_chatroom(self, message):
        with Chat.lock:
            recipients = self.room.users
        for name in recipients:
            if name != self.name:
                self.users[name].sendLine(message)

    def command_rooms(self):
        message = "Active rooms are:\n"
        with Chat.lock:
            for room in Chat.rooms:
                message += " * {} ({})\n".format(Chat.rooms[room].name, len(Chat.rooms[room].users))
        message += "end of list.\n"
        self.sendLine(message)<commit_msg>Move sanity checks into function to make it reusable<commit_after>from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
import threading
import chatroom

class Chat(LineReceiver):

    lock = threading.Lock()
    rooms = {}
    MAXLEN_NAME = 64

    def __init__(self, users):
        self.users = users
        self.name = None
        self.state = "INTRO"
        self.room = None

    def connectionMade(self):
        self.sendLine("Welcome to the fenfiresong chat server\nLogin Name?")

    def connectionLost(self, reason):
        if self.name in self.users:
            del self.users[self.name]

    def lineReceived(self, line):
        if self.state == "INTRO":
            self.handle_INTRO(line)
        else:
            self.handle_CHAT(line)

    def handle_INTRO(self, name):
        name = name.strip()
        if name in self.users:
            self.sendLine("Sorry, name taken.\nLogin Name?")
            return
        reason = self.name_sanity_check(name, "user")
        if reason:
            self.sendLine("{}Login Name?".format(reason))
            return
        self.sendLine("Welcome, {}!".format(name))
        self.name = name
        self.users[name] = self
        self.state = "CHAT"

    def handle_CHAT(self, message):
        if message.startswith("/rooms"):
            self.command_rooms()
        elif message.startswith("/join"):
            self.command_join(message)
        elif message.startswith("/leave"):
            self.command_leave()
        elif message.startswith("/quit"):
            self.command_quit()
        elif self.room == None:
            self.sendLine("You're not in any room! Use /rooms to list active rooms and use /join <room> to enter or create a room.")
        else:
            message = "<{}> {}".format(self.name, message)
            self.sendLine(message)
            self.send_to_chatroom(message)

    def name_sanity_check(self, name, nametype):
        reason = None
        if name == "":
            reason = "The {} name can't be empty.\n".format(nametype)
        if name.startswith("/"):
            reason =  "Don't start the {} name with /, that's used for commands.\n".format(nametype)
        if len(name) > Chat.MAXLEN_NAME:
            reason = "The {} name can't be longer than {} characters.\n".format(nametype, Chat.MAXLEN_NAME)
        return reason

    def send_to_chatroom(self, message):
        with Chat.lock:
            recipients = self.room.users
        for name in recipients:
            if name != self.name:
                self.users[name].sendLine(message)

    def command_rooms(self):
        message = "Active rooms are:\n"
        with Chat.lock:
            for room in Chat.rooms:
                message += " * {} ({})\n".format(Chat.rooms[room].name, len(Chat.rooms[room].users))
        message += "end of list.\n"
        self.sendLine(message)
{'fraction_non_alphanumeric': 0.11558143638609493, 'fraction_numerical': 0.0007058408328921829, 'mean_word_length': 2.082109842305601, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2301105', 'n_tokens_mistral': 1644, 'n_tokens_neox': 1591, 'n_words': 415}