#!/usr/bin/env python """ $Id: $ Copyright (c) 2012-2013 Jan Seidl (http://wroot.org/) LICENSE: This software is distributed under the GNU General Public License version 3 (GPLv3) LEGAL NOTICE: THIS SOFTWARE IS PROVIDED FOR EDUCATIONAL USE ONLY! IF YOU ENGAGE IN ANY ILLEGAL ACTIVITY THE AUTHOR DOES NOT TAKE ANY RESPONSIBILITY FOR IT. BY USING THIS SOFTWARE YOU AGREE WITH THESE TERMS. """ import getopt, sys import string #### # Program info #### USERNAMER_VERSION="1.0-rc3" BUILD_DATE="2018-11-11" AVAILABLE_PLUGINS=[ 'normal', 'two_terms', 'one_term', 'normal_abbreviated', 'dotted_two_terms', 'starts_with', 'under_score'] AVAILABLE_FILTERS=[ 'sort', 'unique' ] #### # Program Functions #### def parse_file(filePath, plugins = [], filters = []): try: with open(filePath, 'r') as fileObject: for line in fileObject: parse_name(line, plugins, filters) except IOError: e = "Could not open the file: " + filePath error(e) def parse_name(name, plugins = [], filters = []): name = name.strip() # Trim whitespaces nameTokens = name.split(' ') # Tokenize name and each surname numTokens = len(nameTokens) if numTokens < 2: error('Name and at least one Surname must be supplied') # Split First Name and Surnames firstName = nameTokens[0] nameTokens.pop(0) surnames = nameTokens results = [] # Run Plugins run_plugins(firstName, surnames, results, plugins) # Run Filters run_filters(results, filters) for result in results: print result def run_plugins(firstName, surnames, resultList, plugins = []): defaultPlugins = AVAILABLE_PLUGINS if len(plugins) == 0: plugins = defaultPlugins for pluginName in plugins: internalPluginName = "plugin_"+pluginName # Validate if plugin exists if not internalPluginName in globals(): error("Invalid plugin: "+pluginName) pluginObject = globals()[internalPluginName] pluginObject(firstName, surnames, resultList) def run_filters(resultList, filters = []): defaultFilters = AVAILABLE_FILTERS if len(filters) == 0: filters = defaultFilters for filterName in filters: internalFilterName = "filter_"+filterName # Validate if filter exists if not internalFilterName in globals(): error("Invalid plugin: "+filterName) filterObject = globals()[internalFilterName] filterObject(resultList) #### # Result Filters #### # Unique Filter # # Removes duplicated entries def filter_unique(resultList): uniqueResults = set(resultList) del resultList[:] for result in uniqueResults: resultList.append(result) # Sort Filter # # Filter entries alphabetically def filter_sort(resultList): resultList.sort() # Lowercase Filter # # Transforms entries to lowercase def filter_lowercase(resultList): for key, result in enumerate(resultList): resultList[key] = result.lower() #### # Parsing Plugins #### # Normal Plugin # # Generates usernames based on concatenation # of first name with surnames in permutation # # Ex: JohnPaulJones, JohnJonesPaul def plugin_normal(firstName, surnames, resultList): surnamePermutations = permutate_all(surnames) for permutations in surnamePermutations: resultList.append(firstName+string.join(permutations, '')) resultList.append(string.join(permutations, '')+firstName) # Two Terms Plugin # # Generates usernames based on concatenation # of first name with surnames in permutation # # Ex: JohnPaul, JohnJones, PaulJones def plugin_two_terms(firstName, surnames, resultList): # Try each surname with # first name and reversed for surname in surnames: resultList.append(firstName+surname) resultList.append(surname+firstName) # If more than one surname, # combine'em too if len(surnames) > 1: tokens = list(surnames) for surname in surnames: firstToken = tokens.pop(0) for token in tokens: resultList.append(firstToken+token) # One Term Plugin # # Generates usernames based on permutation # of first name and surnames generating one-word # usernames # # Ex: John, Paul, Jones def plugin_one_term(firstName, surnames, resultList): tokens = [ firstName ] tokens += surnames for name in tokens: resultList.append(name) # Dotted Two Terms Plugin # # Generates usernames based on concatenation # of first name with surnames in permutation # with a dot in the middle # # Ex: John.Paul, John.Jones, Paul.Jones def plugin_dotted_two_terms(firstName, surnames, resultList): # Try each surname with # first name and reversed for surname in surnames: resultList.append(firstName+'.'+surname) resultList.append(surname+'.'+firstName) # Normal Abbreviated Plugin # # Generates usernames based on concatenation # of first name with surnames in permutation # in abbreviated forms # # Ex: JohnPJones, JohnPaulJ, JohnJonesP JohnJPaul def plugin_normal_abbreviated(firstName, surnames, resultList): permutatedSurnames = permutate_all(surnames) firstNameArr = [ firstName ] # All Terms for entry in permutatedSurnames: nameFirst = list(firstNameArr+entry) nameLast = list(entry+firstNameArr) for name in abbreviate(nameFirst): resultList.append(name) for name in abbreviate(nameLast): resultList.append(name) # Two Words for surname in surnames: for name in abbreviate([ firstName, surname ]): resultList.append(name) for name in abbreviate([ surname, firstName]): resultList.append(name) # Starts With Plugin # contributed by Derek Callaway [decal (AT) sdf {D0T} org] https://decal.github.io # # X Letters First Name Starts With and/or # Y Letters Last Name Starts With # # Generates usernames based on concatenation of # first X letters in first name and/or # first Y letters in last name # # Such naming schemes are often found on legacy # systems like AS/400 mainframes, DEC VMS/VAX, etc. # # Ex. dc dca dcal dcall dec deca decal decall derc derca dercal dercall def plugin_starts_with(firstName, surnames, resultList): for x in range(0, 1 + len(firstName) / 2): for surname in surnames: resultList.append(firstName[0:x] + surname) for y in range(0, 1 + len(surname) / 2): resultList.append(firstName[0:x] + surname[0:y]) resultList.append(firstName + surname[0:y]) def plugin_under_score(firstName, surnames, resultList): for x in range(0, 1 + len(firstName)): for surname in surnames: resultList.append(firstName[0:x] + "_" + surname) resultList.append(surname + "_" + firstName[0:x]) for y in range(0, 1 + len(surname)): resultList.append(firstName[0:x] + "_" + surname[0:y]) resultList.append(surname[0:y] + "_" + firstName[0:x]) resultList.append(firstName + "_" + surname[0:y]) resultList.append(surname[0:y] + "_" + firstName) #### # Util functions #### def permutate_all(tokens): if len(tokens) <=1: yield tokens else: for perm in permutate_all(tokens[1:]): for i in range(len(perm)+1): yield perm[:i] + tokens[0:1] + perm[i:] def abbreviate(tokens): resultList = [] tokenCount = len(tokens) # One abbreviated word for i in range(tokenCount): output = '' position = 0 for j in tokens: if i == position: output += j[0] else: output += j position += 1; resultList.append(output) # Two abbreviated words for i in range(tokenCount): output = '' position = 0 for j in tokens: if i == position or i == position+1: output += j[0] else: output += j position += 1; resultList.append(output) # All-but-one abbreviated words if tokenCount > 3: for i in range(tokenCount): output = '' position = 0 for j in tokens: if i == position: output += j else: output += j[0] position += 1; resultList.append(output) return resultList #### # Main #### def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hlp:f:n:", ["help", "lowercase", "plugins", "file=","name="]) inputFile = None inputName = None defaultPlugins = AVAILABLE_PLUGINS defaultFilters = AVAILABLE_FILTERS for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() elif o in ("-f", "--file"): inputFile = a elif o in ("-p", "--plugins"): pluginList = str(a).split(',') validPlugins = [] for plugin in pluginList: try: pluginIndex = AVAILABLE_PLUGINS.index(plugin) # check plugin existance validPlugins.append(plugin) except ValueError: error('Invalid plugin: "'+plugin+'"') defaultPlugins = validPlugins elif o in ("-n", "--name"): inputName = a elif o in ("-l", "--lowercase"): defaultFilters.append('lowercase') else: error("option '"+o+"' doesn't exists") if inputFile == None and inputName == None: error('Please specify an input file or name') if inputFile != None and inputName != None: error('Please specify only an input file or name, not both') # If name was supplied, # process single entry and exit if inputName: parse_name(inputName, plugins = defaultPlugins, filters = defaultFilters) sys.exit(0) # If file was supplied, # process each line if inputFile: parse_file(inputFile, plugins = defaultPlugins, filters = defaultFilters) sys.exit(0) except getopt.GetoptError, err: # print help information and exit: sys.stderr.write(str(err)) usage() sys.exit(2) def usage(): print print "usage: " + sys.argv[0] + " [ -f ] [ -n ] [ -l ]"; print print "flags:" print "\t-n\tsupplies a single name" print "\t-f\tsupplies name entries from text file" print "\t-l\tconverts result to lowercase" print "\t-p\tmanually specify plugins (comma-separated) [default: all]" print "\t\t"+str(AVAILABLE_PLUGINS) print "" def error(errorMsg, fatal=True, showUsage=True): sys.stderr.write(errorMsg+"\n") if showUsage: usage() if fatal: sys.exit(2) if __name__ == "__main__": main()