예제 #1
0
    def put(self, request):
        """
        """
        # Si cambia el email puede generar problemas serios, por eso se retorna
        # un nuevo token
        decoded_token = decode_token(request.META)
        serializer = UserSerializer(
            MyUser.objects.get(email=decoded_token['email']),
            data=request.data,
            partial=True)

        if serializer.is_valid():
            user = serializer.save()

            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            return Response({"token": token}, status=status.HTTP_200_OK)
        else:
            return Response({
                'data': serializer.errors,
                'message': 'User could not be created with the received data.'
            }, status=status.HTTP_400_BAD_REQUEST)
예제 #2
0
    def create(self, request, *args, **kwargs):
        """
        """
        try:
            Application.objects.get(client_id=self.kwargs['client_id'])
        except Application.DoesNotExist:
            return Response({
                'message': 'Invalid client_id.'
            }, status=status.HTTP_400_BAD_REQUEST)

        decoded_token = decode_token(request.META)
        instance = Profile.objects.get(
            user=MyUser.objects.get(
                email=decoded_token['email']))
        partial = kwargs.pop('partial', False)
        serializer = self.get_serializer(
            instance, data=request.data, partial=partial)
        if serializer.is_valid():
            self.perform_update(serializer)
            return Response(serializer.data, status=status.HTTP_200_OK)

        return Response({
            'data': serializer.errors,
            'message': 'Profile could not be updated with the received data.'
        }, status=status.HTTP_400_BAD_REQUEST)
예제 #3
0
    def delete(self, request):
        """
        """
        decoded_token = decode_token(request.META)
        MyUser.objects.get(email=decoded_token['email']).delete()

        return Response("User deleted!", status=status.HTTP_204_NO_CONTENT)
예제 #4
0
 def perform_update(self, serializer):
     """
     """
     decoded_token = decode_token(self.request.META)
     if decoded_token is not None:
         serializer.save(
             owner=MyUser.objects.get(
                 email=decoded_token['email']))
예제 #5
0
    def get_usertoken_data(self, token):

        token_data = decode_token(token)
        if not token_data:
            return None, response(400, 'Wrong token')

        if not self._validate_user(token_data['username']):
            return None, response(400, 'User doesn\'t exists')
        return token_data, None
예제 #6
0
    def get(self, request):
        """
        """
        decoded_token = decode_token(request.META)
        serializer = UserSerializer(
            MyUser.objects.get(
                email=decoded_token['email']))

        return Response(serializer.data, status=status.HTTP_200_OK)
예제 #7
0
 def get_queryset(self):
     """
     This view should return a list of all the applications
     for the currently authenticated user.
     """
     decoded_token = decode_token(self.request.META)
     if decoded_token is not None:
         return Application.objects.filter(
             owner=MyUser.objects.get(email=decoded_token['email']))
     return []
예제 #8
0
 def filter_queryset(self, queryset):
     """
     """
     decoded_token = decode_token(self.request.META)
     try:
         # If the user is the owner
         # app = Application.objects.get(client_id=self.kwargs['client_id'],
         #                               owner__email=decoded_token['email'])
         return queryset
     except Application.DoesNotExist:
         return queryset.filter(user__email=decoded_token['email'])
     return queryset
예제 #9
0
def authenticate():
    print("authenticating...")
    auth_header = request.headers.get('Authorization').split(' ')[1]
    if not auth_header:
        return make_response(json.dumps({'message': 'No authentication header'}), 403)
    user_id = decode_token(auth_header)
    if isinstance(user_id, int):
        print('token valid, user id is', user_id)
        return make_response(json.dumps({"message": user_id}), 200)
    else:
        print("auth fail")
        return make_response(json.dumps({"message": user_id}), 403)
예제 #10
0
    def validate_jetson_data(self, device_data, data_dict=None):
        token_data = decode_token(device_data['token'])

        jetson = Jetson.query.filter_by(mac=token_data['mac']).first()
        truck = Truck.query.filter_by(id=device_data['truck_id']).first()

        if truck.jetson_id != jetson.id:
            return response(400, 'Wrong token')

        if data_dict:
            error = self._validate_data(**data_dict)
            if error:
                return error
예제 #11
0
    def test_valid_fields(self):
        response = json.loads(
            self.client.post('/login',
                             json=dict(email='*****@*****.**', )).data)
        token = response['token']

        response = json.loads(
            self.client.post('/user/employee/profile',
                             json=dict(firstname='test',
                                       lastname='test',
                                       birth='1900-01-01',
                                       city='test',
                                       telephone='+37061234567',
                                       description='test test test',
                                       work_experience=10),
                             headers=dict(token=token)).data)

        assert response.get('status') == 'success'

        decoded_token = decode_token(token)

        with app.app_context():
            assert Employee.query.filter_by(
                user_id=decoded_token['user_id']).first() != None
예제 #12
0
def play_game(screen, color_count, max_attempts, code, attempts):
    global line, client_socket

    score = 0

    if len(attempts) > max_attempts:
        attempts = attempts[:max_attempts]

    for i, attempt in enumerate(attempts):
        utils.print_code(screen, utils.PREFIX, attempt, -1)
        line += 1
        screen.move(line, 0)

        answer_bytes = utils.receive_packet(
            client_socket
        )  # We read the server's answer for the current attempt and find the corresponding perfect and partial pin counts
        if len(answer_bytes) == 2 and int.from_bytes(answer_bytes,
                                                     "big") == 418:
            answer_bytes = utils.receive_packet(client_socket)

        perfect = int.from_bytes(answer_bytes[:2], "big")
        partial = int.from_bytes(answer_bytes[2:4], "big")

        if perfect == len(
                code
        ):  # If all the pins are perfect, that means the guessed code was the right one
            screen.move(line - 1, len(utils.PREFIX) + 1 + (len(code) + 1) * 2)
            screen.addstr("Correct!\n\r"
                          )  # Print "correct" next to the last guessed line
            screen.move(line, 0)

            score = max_attempts - i  # His score is the number of attempts left
            screen.addstr(
                "You cracked the code! Score: {}\n\r".format(score)
            )  # Print a nice message for the user to know he got it right and show his score
            line += 1
            break
        else:
            # Show the perfect and partial pins next to the guess
            offset = len(utils.PREFIX) + 1 + (len(code) + 1) * 2
            screen.addstr(line - 1, offset, "Result:")
            offset += len("Result:") + 1
            for i in range(perfect + partial):
                attr = curses.color_pair(2 if i < perfect else 1)
                screen.addstr(line - 1, offset + i * 2, " ", attr)
            screen.move(line, 0)
    else:
        if attempts:
            guess = attempts[-1].copy(
            )  # We take the last attempt as starting point for the next guess if there is one
        else:
            guess = [0] * len(
                code
            )  # Otherwise, the user's default guess will be only red pins (it could be any color, but the 0-th color is easier and always exists)

        for attempt in range(
                len(attempts), max_attempts
        ):  # Limits the number of attempts to the chosen amount
            guess = input_guess(screen, len(code), color_count, guess)
            attempts.append(guess.copy())

            guess_bytes = bytes(
            )  # While in an Online Ranked Game, instead of comparing the codes locally, we send the guess to the server

            # If guess is not the same size as code, cut it off or append zeros
            if len(guess) > len(code):
                guess = guess[:len(code)]
            elif len(guess) < len(code):
                guess += [0] * (len(code) - len(guess))

            for color in guess:
                # Encode guess' colors on 16 bits (max. 65535 colors)
                guess_bytes += (min(color, 0xFFFF) & 0xFFFF).to_bytes(2, "big")

            utils.send_packet(client_socket, guess_bytes)

            answer_bytes = utils.receive_packet(
                client_socket
            )  # We then read the server's answer and find the corresponding perfect and partial pin counts
            if len(answer_bytes) == 2 and int.from_bytes(answer_bytes,
                                                         "big") == 418:
                answer_bytes = utils.receive_packet(client_socket)

            perfect = int.from_bytes(answer_bytes[:2], "big")
            partial = int.from_bytes(answer_bytes[2:4], "big")

            if perfect == len(
                    code
            ):  # If all the pins are perfect, that means the guessed code is the right one
                screen.move(line - 1,
                            len(utils.PREFIX) + 1 + (len(code) + 1) * 2)
                screen.addstr(
                    "Correct!\n\r"
                )  # Print "correct" next to the last guessed line
                screen.move(line, 0)

                score = max_attempts - attempt  # His score is the number of attempts left
                screen.addstr(
                    "You cracked the code! Score: {}\n\r".format(score)
                )  # Print a nice message for the user to know he got it right and show his score
                line += 1
                break
            else:
                # Show the perfect and partial pins next to the guess
                offset = len(utils.PREFIX) + 1 + (len(code) + 1) * 2
                screen.addstr(line - 1, offset, "Result:")
                offset += len("Result:") + 1
                for i in range(perfect + partial):
                    attr = curses.color_pair(2 if i < perfect else 1)
                    screen.addstr(line - 1, offset + i * 2, " ", attr)
                screen.move(line, 0)

        else:  # If we reached the maximum number of attempts without quitting the loop, it means the user failed to guess the code and he lost
            token = utils.receive_packet(client_socket).decode("utf8")
            _, _, _, _, _, code, _ = utils.decode_token(
                token
            )  # Retrieve the real code from the server once the player lost

            utils.print_code(screen, "You failed! The code was:", code, -1)
            line += 1
            screen.move(line, 0)

    screen.refresh(
    )  # Update the screen before going to sleep, or it would "freeze" before updating, not showing the final text before resetting
    curses.napms(3000)

    return score
예제 #13
0
def main(screen=None, color_count=None, max_attempts=None, code_length=None):
    if screen is None:
        try:
            token = curses.wrapper(
                main
            )  # Use curses to handle user input, screen clearing and simplify other display management tools

            if token is not None:  # If the game has been interrupted and a token to resume was generated, show a message to inform the user
                print(
                    "This game has been interrupted. To resume, copy paste this token:",
                    token)
        except KeyboardInterrupt:
            pass
        except Exception as e:
            if utils.DEBUG:
                traceback.print_exc()
            else:
                print("Oops! An error occured:", e)
        return

    curses.start_color()  # Enable curses' colors
    curses.use_default_colors()
    curses.curs_set(
        0
    )  # Hide the cursor as we will use a custom way to show the selected color

    if color_count is None or color_count <= 0:
        color_count = utils.DEFAULT_COLOR_COUNT

    if max_attempts is None or max_attempts <= 0:
        max_attempts = utils.DEFAULT_MAX_ATTEMPTS

    if code_length is None or code_length <= 0:
        code_length = utils.DEFAULT_CODE_LENGTH

    global score, games

    score, games = 0, 0
    code, attempts = None, None
    # Create a token containing the settings requested by the user
    token = utils.encode_token(1, score, games, color_count, max_attempts,
                               [0xFFFF] * code_length, [])

    global client_socket, line

    username = ""

    initialized, first = False, True
    while True:  # Play an infinite number of games until the user quits the program (with Ctrl+C)
        if client_socket is None:  # If the client isn't connected to the server yet, connect to it
            screen.clear()
            screen.addstr("Connecting to the server, please wait...\n\r")
            screen.refresh(
            )  # Refresh the screen, because the following code could block for a few seconds

            try:
                client_socket = socket.socket(socket.AF_INET,
                                              socket.SOCK_STREAM)
                client_socket.connect(
                    (utils.SERVER_HOST,
                     utils.SERVER_PORT))  # Connect to socket server
                client_socket.settimeout(
                    2
                )  # Let the server 2 seconds to understand our request and answer it, or disconnect
            except socket.error as e:
                screen.clear()
                raise Exception(
                    "Failed to connect to server. Please try again later.")

            # TODO: GDPR Prompt
            utils.send_packet(client_socket, "OK".encode("utf8"))

        while not initialized:  # While the game hasn't fully been created and started on the server, don't start it locally
            try:
                status = int.from_bytes(utils.receive_packet(client_socket),
                                        "big")

                if status == 401 or status == 403:  # Status 401: Unknown user; Status 403: Unknown user, username provided taken
                    username = ""
                    while not username:
                        screen.clear()
                        screen.addstr(
                            "Please enter a username which will represent you in the Online Ranked Games scoreboard.\n\r"
                        )
                        screen.addstr(
                            "WARNING: This username CAN NOT BE CHANGED and will be linked to your address. It must be UNIQUE.\n\r"
                        )
                        screen.addstr("\n\r")
                        screen.addstr("Username: \n\r")
                        if status == 403:
                            screen.addstr(
                                "Invalid username. Please try again.")
                        curses.curs_set(2)
                        curses.echo()
                        username = screen.getstr(3, 10).decode("utf8")
                        curses.noecho()
                        curses.curs_set(0)

                    screen.clear()
                    screen.addstr("Registering new user, please wait...\n\r")
                    screen.refresh()

                    utils.send_packet(client_socket, username.encode("utf8"))

                elif status == 204:  # Status 204: Known user, no game started
                    if not username:
                        username = utils.receive_packet(client_socket).decode(
                            "utf8")

                    if not first:
                        display_scoreboard(screen)

                    screen.clear()
                    screen.addstr(
                        "Initializing new Online Ranked Game, please wait...\n\r"
                    )
                    screen.refresh()

                    utils.send_packet(
                        client_socket, token.encode("utf8")
                    )  # Send the token containing all the settings requested by the user to the server

                elif status == 200:  # Status 200: Known user, game pending
                    if not username:
                        username = utils.receive_packet(client_socket).decode(
                            "utf8")
                    token = utils.receive_packet(client_socket).decode("utf8")
                    # Get all the required information about the game from the server
                    _, score, games, color_count, max_attempts, code, attempts = utils.decode_token(
                        token)
                    code_length = len(code)

                    curses.init_pair(0, -1, utils.find_nearest_color(0, 0, 0))
                    curses.init_pair(1, -1, utils.find_nearest_color(1, 1, 1))
                    for color in range(
                            2, color_count + 2
                    ):  # Initialize all the colors we will need, generating them around the color wheel
                        # Each color is uniformly spread around the color spectrum, keeping its saturation and value to the max (excludes black and white)
                        h, s, v = (color - 2) / color_count, 1.0, 1.0
                        r, g, b = colorsys.hsv_to_rgb(
                            h, s, v
                        )  # Convert the color from HSV (easier to generate) to RGB (easier to manipulate)

                        # Because we can't use custom colors in most terminals, we find the closest available one and pair it to the color's id with a white foreground
                        curses.init_pair(color, -1,
                                         utils.find_nearest_color(r, g, b))

                    initialized = True
                    break

                elif status == 409:  # Status 409: Known user, game already running
                    screen.clear()
                    raise Exception(
                        "A user is already playing an Online Ranked Game from this address."
                    )

                elif not status:
                    screen.clear()
                    raise Exception(
                        "Server disconnected unexpectedly. Please try again later."
                    )

                else:
                    screen.clear()
                    raise Exception(
                        "Unknown status {} returned by server.".format(status))
            except socket.timeout:
                pass

        screen.clear()
        line = 0
        first = False

        try:
            if code is None:
                code = [0xFFFF] * code_length
            if attempts is None:
                attempts = []

            game_score = play_game(screen, color_count, max_attempts, code,
                                   attempts)
            code, attempts = None, None  # Reset the code and the attempts to make the next game independent
        except KeyboardInterrupt:
            screen.move(line, 0)
            screen.clrtoeol(
            )  # Clear the current line, just in case some text was there

            token = utils.encode_token(1, score, games, color_count,
                                       max_attempts, code, attempts)
            return token

        if game_score > 0:
            score += game_score  # If the user won this game, we increment his score and the number of (consecutive) games he played
            games += 1
        else:
            score, games = 0, 0  # If he lost, we reset his score and the number of (consecutive) games

            initialized = False
예제 #14
0
파일: server.py 프로젝트: au2001/Mastermind
def tick_client(conn, address, data, user_list, scoreboard):
    try:
        buff = data["inputs"].pop(
            0) if data["inputs"] else utils.receive_packet(conn)

        if buff:
            if data["status"] == 200:
                game = user_list[address[0]]["game"]

                guess = [0xFFFF] * len(game["code"])
                for i in range(len(game["code"])):
                    guess[i] = int.from_bytes(buff[2 * i:2 * (i + 1)], "big")

                perfect, partial = utils.compare_codes(guess, game["code"])

                if game["color_count"] == 6 and len(
                        game["code"]) == 4 and guess == [0, 1, 0, 0]:
                    utils.send_packet(conn, (418).to_bytes(2, "big"))

                utils.send_packet(
                    conn,
                    perfect.to_bytes(2, "big") + partial.to_bytes(2, "big"))

                if perfect == len(game["code"]):
                    game["score"] += game["max_attempts"] - len(
                        game["attempts"])
                    game["games"] += 1
                    game["code"] = utils.generate_code(len(game["code"]),
                                                       game["color_count"])
                    game["attempts"] = []

                    if utils.DEBUG:
                        print("Client {}:{} won a game on thread #{}.".format(
                            *address, thread.ident))
                else:
                    game["attempts"].append(guess)
                    if len(game["attempts"]) >= game["max_attempts"]:
                        token = utils.encode_token(
                            game["gamemode"], game["score"], game["games"],
                            game["color_count"], game["max_attempts"],
                            game["code"], game["attempts"])
                        utils.send_packet(conn, token.encode("utf8"))

                        total_attempts = (game["max_attempts"] +
                                          1) * game["games"] - game["score"]
                        normalized_score = game["score"]
                        normalized_score *= game["color_count"]**len(
                            game["code"]) / 1000
                        normalized_score /= 1.2**game["max_attempts"] / 10
                        normalized_score = int(normalized_score)

                        entry = (address[0], user_list[address[0]]["username"],
                                 game["score"], game["games"], total_attempts,
                                 normalized_score, game["color_count"],
                                 len(game["code"]), game["max_attempts"],
                                 time.time())
                        for i, other in enumerate(scoreboard):
                            if other[5] < entry[5] or (
                                    other[5] == entry[5]
                                    and other[3] < entry[3] or
                                (other[3] == entry[3]
                                 and other[4] > entry[4])):
                                scoreboard.insert(i, entry)
                                break
                        else:
                            scoreboard.append(entry)

                        del user_list[address[0]]["game"]
                        user_list[address[0]]["connected"] = False
                        data["status"] = 204
                        utils.send_packet(conn,
                                          data["status"].to_bytes(2, "big"))

                        if utils.DEBUG:
                            print("Client {}:{} lost a game on thread #{}.".
                                  format(*address, thread.ident))

            elif address[0] in user_list and "connected" in user_list[
                    address[0]] and user_list[address[0]]["connected"]:
                data["status"] = 409
                utils.send_packet(conn, data["status"].to_bytes(2, "big"))
                conn.close()

                if utils.DEBUG:
                    print(
                        "Client {}:{} forcefully disconnected from thread #{}."
                        .format(*address, thread.ident))

                return False

            elif data["status"] == 204:
                token = buff.decode("utf8")
                if re.match(r"^SB:\d+ \d+$", token):
                    page_size, offset = map(int, token[3:].split())
                    answer_bytes = bytes()

                    if len(scoreboard) >= offset:
                        for entry in scoreboard[
                                offset:min(offset +
                                           page_size, len(scoreboard))]:
                            username = entry[1].encode("utf8")

                            if 6 + len(answer_bytes) + len(
                                    username) + 6 > 65535:
                                break

                            answer_bytes += (min(len(username), 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")
                            answer_bytes += username

                            answer_bytes += (min(entry[5], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")
                            answer_bytes += (min(entry[3], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")
                            answer_bytes += (min(entry[4], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")

                            answer_bytes += (min(entry[4], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")
                            answer_bytes += (min(entry[5], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")
                            answer_bytes += (min(entry[6], 0xFFFF)
                                             & 0xFFFF).to_bytes(2, "big")

                            answer_bytes += (
                                min(int(entry[8] * 1000), 2**64 - 1)
                                & 2**64 - 1).to_bytes(8, "big")

                    utils.send_packet(conn, answer_bytes)
                else:
                    gamemode, score, games, color_count, max_attempts, code, attempts = utils.decode_token(
                        token)

                    score, games = 0, 0
                    code = utils.generate_code(len(code), color_count)

                    user_list[address[0]]["connected"] = True
                    game = {
                        "gamemode": gamemode,
                        "score": score,
                        "games": games,
                        "color_count": color_count,
                        "max_attempts": max_attempts,
                        "code": code,
                        "attempts": []
                    }
                    user_list[address[0]]["game"] = game

                    if len(attempts) > max_attempts:
                        attempts = attempts[:max_attempts]

                    for attempt in attempts:
                        attempt_bytes = bytes()

                        if len(attempt) > len(code):
                            attempt = attempt[:len(code)]
                        elif len(attempt) < len(code):
                            attempt += [0] * (len(code) - len(attempt))

                        for color in attempt:
                            attempt_bytes += (min(color, 0xFFFF)
                                              & 0xFFFF).to_bytes(2, "big")

                        data["inputs"].append(attempt_bytes)

                        if attempt == code:
                            break

                    data["status"] = 200
                    utils.send_packet(conn, data["status"].to_bytes(2, "big"))

                    fake_code = [0xFFFF] * len(game["code"])
                    fake_token = utils.encode_token(game["gamemode"],
                                                    game["score"],
                                                    game["games"],
                                                    game["color_count"],
                                                    game["max_attempts"],
                                                    fake_code, attempts)
                    utils.send_packet(conn, fake_token.encode("utf8"))

                    if utils.DEBUG:
                        print("Client {}:{} started a new game on thread #{}.".
                              format(*address, thread.ident))

            elif data["status"] == 401 or data["status"] == 403:
                username = buff.decode("utf8")

                if buff == b"\x36\x39":
                    for chars in itertools.product(*[
                        [
                            b"\x4e", b"\x6e", b"\xc3\xb1", b"\xc5\x84",
                            b"\xc3\x91", b"\xc5\x83"
                        ],
                        [
                            b"\x69", b"\x49", b"\xc3\xae", b"\xc3\xaf",
                            b"\xc3\xac", b"\xc3\xad", b"\xc4\xaf", b"\xc4\xab",
                            b"\xc3\x8e", b"\xc3\x8f", b"\xc3\x8c", b"\xc3\x8d",
                            b"\xc4\xae", b"\xc4\xaa"
                        ],
                        [
                            b"\x63", b"\x43", b"\xc3\xa7", b"\xc4\x87",
                            b"\xc4\x8d", b"\xc3\x87", b"\xc4\x86", b"\xc4\x8c"
                        ],
                        [
                            b"\x65", b"\x45", b"\xc3\xa9", b"\xc3\xa8",
                            b"\xc3\xaa", b"\xc3\xab", b"\xc4\x99", b"\xc4\x97",
                            b"\xc4\x93", b"\xc3\x89", b"\xc3\x88", b"\xc3\x8a",
                            b"\xc3\x8b", b"\xc4\x98", b"\xc4\x96", b"\xc4\x92"
                        ]
                    ]):
                        username = "".join(
                            map(lambda x: x.decode("utf8"), chars))
                        for other_address in user_list:
                            if username == user_list[other_address][
                                    "username"]:
                                data["status"] = 403
                                utils.send_packet(
                                    conn, data["status"].to_bytes(2, "big"))
                                break
                        else:
                            break
                    else:
                        username = ""

                if 3 <= len(username) <= 32 and set(
                        username) <= USERNAME_CHARACTERS:
                    for other_address in user_list:
                        if username == user_list[other_address]["username"]:
                            data["status"] = 403
                            utils.send_packet(
                                conn, data["status"].to_bytes(2, "big"))
                            break
                    else:
                        user_list[address[0]] = {"username": username}
                        data["status"] = 204
                        utils.send_packet(conn,
                                          data["status"].to_bytes(2, "big"))
                else:
                    data["status"] = 403
                    utils.send_packet(conn, data["status"].to_bytes(2, "big"))

            elif data["status"] == 300:
                if buff.decode("utf8") == "OK":
                    if address[0] in user_list:
                        if not "connected" in user_list[address[
                                0]] or not user_list[address[0]]["connected"]:
                            if "game" in user_list[address[0]] and user_list[
                                    address[0]]["game"] is not None:
                                game = user_list[address[0]]["game"]
                                user_list[address[0]]["connected"] = True

                                attempts = game["attempts"]
                                game["attempts"] = []

                                if len(attempts) > game["max_attempts"]:
                                    attempts = attempts[:game["max_attempts"]]

                                for attempt in attempts:
                                    attempt_bytes = bytes()

                                    if len(attempt) > len(game["code"]):
                                        attempt = attempt[:len(game["code"])]
                                    elif len(attempt) < len(game["code"]):
                                        attempt += [0] * (len(game["code"]) -
                                                          len(attempt))

                                    for color in attempt:
                                        attempt_bytes += (min(color, 0xFFFF)
                                                          & 0xFFFF).to_bytes(
                                                              2, "big")

                                    data["inputs"].append(attempt_bytes)

                                    if attempt == game["code"]:
                                        break

                                data["status"] = 200
                                utils.send_packet(
                                    conn, data["status"].to_bytes(2, "big"))
                                utils.send_packet(
                                    conn, user_list[address[0]]
                                    ["username"].encode("utf8"))

                                fake_code = [0xFFFF] * len(game["code"])
                                fake_token = utils.encode_token(
                                    game["gamemode"], game["score"],
                                    game["games"], game["color_count"],
                                    game["max_attempts"], fake_code, attempts)
                                utils.send_packet(conn,
                                                  fake_token.encode("utf8"))

                                if utils.DEBUG:
                                    print(
                                        "Client {}:{} resumed a game on thread #{}."
                                        .format(*address, thread.ident))
                            else:
                                data["status"] = 204
                                utils.send_packet(
                                    conn, data["status"].to_bytes(2, "big"))
                                utils.send_packet(
                                    conn, user_list[address[0]]
                                    ["username"].encode("utf8"))
                        else:
                            data["status"] = 409
                            utils.send_packet(
                                conn, data["status"].to_bytes(2, "big"))
                            conn.close()

                            if utils.DEBUG:
                                print(
                                    "Client {}:{} forcefully disconnected from thread #{}."
                                    .format(*address, thread.ident))

                            return False
                    else:
                        data["status"] = 401
                        utils.send_packet(conn,
                                          data["status"].to_bytes(2, "big"))

            return True
    except socket.error as e:
        if hasattr(e, "skipped_data"):
            data = e.skipped_data
            if data.decode("utf8").startswith("GET "):
                data += conn.recv(65536 - len(e.skipped_data))
                if re.match(r"^GET .*? HTTP/\d+(?:\.\d+)*\r\n",
                            data.decode("utf8")):
                    conn.send(
                        base64.b64decode(
                            "SFRUUC8xLjEgMjAwIE9LDQpDb250ZW50LVR5cGU6aW1hZ2UvZ2lmDQpDb25uZWN0aW9uOmNsb3NlZA0KDQpHSUY4OWEQAA4A8gAA/wEqFf5J4esIoOc5K+7IycenAAAAAAAAIfkECQQAAAAh/hlPcHRpbWl6ZWQgdXNpbmcgZXpnaWYuY29tACH/C05FVFNDQVBFMi4wAwEAAAAh/wt4bXAgZGF0YXhtcP8/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG10YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4zLWMwMTEgNjYuMTQ1NjYxLCAyMDEyLzAyLzA2LTE0OjU2OjI3ICAgICAgICAiPjxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53Lm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZjphYm91dD0iIiD/eG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1uczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2ICgxMy4wIDIwMTIwMzAubS40MTUgMjAxMi8wMy8wNToyMTowMDowMCkgIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YWNlSUQ9/yJ4bXAuaWlkOjNFMDkxQkU1N0I3NTExRTE5QkY3ODJBQjU0NUZGMkI2IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNFMDkxQkU2N0I3NTExRTE5QkY3ODJBQjU0NUZGMkI2Ij4gPG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozRTA5MUJFMzdCNzUxMUUxOUJGNzgyQUI1NDVGRjJCNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozRTA5MUJFNDdCNzUxMUUxOUY3ODJBQjU0NUZGMkI2Ii8+IDwvcmRmOkRlc2Nyaf9wdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKupqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAALAAAAAAQAA4AAAM7CLoM1I08EMKAKsgtMdVcB1XhNpYcM5DopAgryGkqXIF3I+yxVF2LwW4IiwEBKyGRWFAIlUviK0oFJAAAIfkECQQAAAAsAAAAAA8ADgCCAAAAKv4jqvgVGUf7ENfjsaXCAAAAAAAAAz8IukvEjIwBHClQuSKHy5UzeRO2cOJkUY2Vjkzgjmosz96zBLdrMQVez2JSCI5HIa9YQCKVAWPAmVQaqVWhIAEAIfkECQQAAAAsAQAAAA8ADgCCAAAAD/9BLDf5BdTlRu6/nbKwAAAAAAAAAzsIuiO1sBUhmoCMao3B+BsXhVtkkRQDopfyrSRDEDAIFUH+vg+U/7oBoacA5miDXC9pnAUIOQXUSA0AEgAh+QQJBAAAACwAAAAAEAAOAIIAAABMOfbGGvIG2udG7r9D338AAAAAAAADQgi6EPxACBUCgdSKsCeulSR6DCiaDxGGIwkMIDdWzACbUljbcfzYvN6FUbARgLwhkVAoHJE2YrMIHTAXzGbV5gQkAAAh+QQJBAAAACwAAAEADwANAIIAAAA5PfjdCN/WaMAEy/fgWIMAAAAAAAADOQi6MvugFTBEg9RW7WAIVjNsXmiGDxiORWGlqlaQyxef8L2mBGFbn46iR7TZCAti0RhAApQ9ZhOZAAAh+QQJBAAAACwAAAEADgANAIIAAADtR3H+EzBJLffbI9LJx6cAAAAAAAADOAi6EMUrBEXIhFYGISSuXLddFBFyGmmJZ7dUUuuW2ekBxFCtnUVQg2AmsHsogkjh7phsIgHOKCABACH5BAkEAAAALAAAAQANAA0AggAAAPk0O/q5BN0a2nVK7wAAAAAAAAAAAAMtCLrcHuGJCSEbNcx5M9UL5mlCBIjQRiko+bFtZg5xxhJ0PJwD4eO5He/nCwISACH5BAkEAAAALAAAAQAPAA0AggAAAPY8Q+DbBvG9CvIL08nHpwAAAAAAAAM7CLoswu2BMESBqhYnKg4UJ0JgJZpMwJnjErKtAoaik87s4MlEr1cDygUgCPR6s9nQeGyCHkVQ8ygFJAAAIfkECQQAAAAsAAABABAADQCCAAAA/SgnN/4K190Gu+EazqatAAAAAAAAAzsIugxTjREBByEwDlummJGzeRTYjML3TdliXWRKNMEbX/T2ysTADIEa7ML5BYM6XQt4bCIVOqdUJJ0CEgAh+QQFBAAAACwAAAAAEAAOAIIAAAD+QwQm/hsI/l3D2R1G7r8AAAAAAAADPwi63K5lifHULFjgSrT4Q+gQHTiAEUN+aDE1pRZmAhyH4WfH7KuSvE5KQQoEgEjComhsIlPIphFJJBylThIgAQA7"
                        ))
                    conn.close()

                    if utils.DEBUG:
                        print("Client {}:{} disconnected from thread #{}.".
                              format(*address, thread.ident))

                    return False

        if e.errno == errno.EWOULDBLOCK:
            return True
        elif utils.DEBUG:
            traceback.print_exc()
        else:
            print(e)
    except Exception as e:
        if utils.DEBUG:
            traceback.print_exc()
        else:
            print(e)
        pass

    conn.close()

    if address[0] in user_list and "connected" in user_list[
            address[0]] and user_list[address[0]]["connected"]:
        user_list[address[0]]["connected"] = False

    if utils.DEBUG:
        print("Client {}:{} disconnected from thread #{}.".format(
            *address, thread.ident))

    return False
예제 #15
0
def main(screen=None):
    if screen is None:
        try:
            token = curses.wrapper(
                main
            )  # Use curses to handle user input, screen clearing and simplify other display management tools

            if token is not None:  # If the game has been interrupted and a token to resume was generated, show a message to inform the user
                print(
                    "This game has been interrupted. To resume, copy paste this token:",
                    token)
        except KeyboardInterrupt:
            pass
        except Exception as e:
            if utils.DEBUG:
                traceback.print_exc()
            else:
                print("Oops! An error occured:", e)
        return

    curses.start_color()  # Enable curses' colors
    curses.use_default_colors()
    curses.curs_set(
        0
    )  # Hide the cursor as we will use a custom way to show the selected color

    if len(sys.argv) > 1 and re.match(
            "^[A-Za-z0-9+/]*=*$", sys.argv[1]
    ):  # If a (seemingly) valid token was provided, resume this game rather than starting a new one
        token = sys.argv[1]
        if len(token) % 4 > 0:
            token += "=" * (
                4 - len(token) % 4
            )  # Fix Base64 padding by adding equal signs at the end of the token

        gamemode, score, games, color_count, max_attempts, code, attempts = utils.decode_token(
            token
        )  # Get all the required information about the pending game from the token
        code_length = len(code)
    else:
        gamemode, code_length, color_count, max_attempts = select_gamemode(
            screen)
        score, games = 0, 0
        code, attempts = None, None

    if gamemode == 0:
        if code is None:
            code = utils.generate_code(
                code_length, color_count
            )  # Generate a random code to "play against the computer"

        return singleplayer.main(screen, color_count, max_attempts, score,
                                 games, code, attempts)
    elif gamemode == 1:
        return online_ranked.main(screen, color_count, max_attempts,
                                  code_length)
    elif gamemode == 2:
        if code is None:
            code = utils.generate_code(
                code_length, color_count
            )  # Generate a random code for the computer to guess

        return computer_vs_computer.main(screen, color_count, max_attempts,
                                         score, games, code, attempts)
    else:
        raise Exception("Unknown gamemode selected: {}".format(gamemode))