2
\$\begingroup\$

I wrote some code that reads the output of the rcon users command on the CS 1.6 console. It then notifies me of any players that are not in my whitelist.csv or are in my blacklist. The program requires 3 files as inputs:

  1. A text file containing the raw output of the rcon users command on CS 1.6 console.
  2. A CSV file containing the SteamID and name of the white-listed players.
  3. A CSV file containing the SteamID and name of the black-listed players.
#!/usr/bin/env python3 
import csv
import re


class WhiteListVerifier:
    """
    Class to check if non-white-listed players are playing CS.
    """
    def __init__(self, users_filepath, whitelist_filepath, blacklist_filepath):
        """
        Get filepaths and load the following files: users file , whitelist file and blacklist file

        users_filepath: Path to a text file which contains the raw output of the 'rcon users' in the in-game console.
        whitelist_filepath: Path to a csv file which contains Steam IDs and player-names of the white-listed players.
        blacklist_filepath: Path to a csv file which contains Steam IDs, player-names and alert-message for the black-listed players.
        """
        with open(users_filepath) as f:
            self.users_rawcontents = f.read()
        self.whitelist = list(csv.DictReader(open(whitelist_filepath)))
        self.blacklist = list(csv.DictReader(open(blacklist_filepath)))

    def get_playername(self, steamid, player_records):
        """
        Function to return name of a person if steamid exits in given records 
        and return 'Unknown' otherwise.
        """
        for player in player_records:
            if steamid == player['Steam_ID']:
                return player['Player_Name']
        return 'Unknown'

    def get_active_users_steamids(self):
        """
        Function to extract the Steam IDs using output of 'rcon users' command.
        """
        active_users_steamids = re.findall(r'STEAM_[0-5]:[01]:\d+', self.users_rawcontents)
        return active_users_steamids

    def verify_steamids(self):
        """
        Function to alert if people other than the ones mentioned in the whitelist are playing.
        """
        active_users_steamids = self.get_active_users_steamids()
        num_nonwhitelisted_users = 0

        for active_user in active_users_steamids:
            player = self.get_playername(active_user, self.whitelist)
            if player is 'Unknown':
                num_nonwhitelisted_users += 1
                nonwhitelisted_playername = self.get_playername(active_user, self.blacklist)
                print('-- nonwhitelisted player: '+str(nonwhitelisted_playername))
        print('>> Total number of non-whitelisted players: '+str(num_nonwhitelisted_users))


if __name__ == '__main__':
    checker = WhiteListVerifier('data/users.txt', 'data/whitelist.csv', 'data/blacklist.csv')
    checker.verify_steamids()

\$\endgroup\$
2
  • \$\begingroup\$ Why is there both a blacklist and whitelist? What does it mean for a player to neither be on the whitelist nor blacklist? \$\endgroup\$ Jun 4, 2020 at 7:38
  • \$\begingroup\$ Whitelist is for people with whom I play regularly. Blacklist is for people that I don't want to play with. And if I see a new id which is neither on my whitelist or blacklist, I'll ask them if I know them personally. \$\endgroup\$ Jun 4, 2020 at 8:23

1 Answer 1

2
\$\begingroup\$

This works, but is essentially O(N**2); you can make it O(N) fairly easily by turning your whitelist/blacklist into dicts:

def __init__(self, users_filepath, whitelist_filepath, blacklist_filepath):
    """
    Get filepaths and load the following files: users file , whitelist file and blacklist file

    users_filepath: Path to a text file which contains the raw output of the 'rcon users' in the in-game console.
    whitelist_filepath: Path to a csv file which contains Steam IDs and player-names of the white-listed players.
    blacklist_filepath: Path to a csv file which contains Steam IDs, player-names and alert-message for the black-listed players.
    """
    with open(users_filepath) as f:
        self.users_rawcontents = f.read()
    raw_whitelist = list(csv.DictReader(open(whitelist_filepath)))
    raw_blacklist = list(csv.DictReader(open(blacklist_filepath)))
    self.whitelist = { p['Steam_ID']: p for p in raw_whitelist }
    self.blacklist = { p['Steam_ID']: p for p in raw_blacklist }

def get_playername(self, steamid, player_records):
    """
    Function to return name of a person if steamid exits in given records 
    and return 'Unknown' otherwise.
    """
    return player_records.get(steamid, 'Unknown')

So instead of iterating over the entire list of player_records every time you look someone up, it iterates over your whitelist and blacklist each once at startup-time, making them thereafter be O(1) to search by steamid (which is the only kind of search you ever do).

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks a lot! I really should have thought about using hash maps instead of iterating over a list over and over to find something. Again, thanks! I appreciate it. \$\endgroup\$ Jun 4, 2020 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.