Esempio n. 1
0
class YamlConf:
    """Wrapper class to pYaml - useful for more complex configurations"""
    def __init__(self, filename):
        self.log = Log()
        self.log.info("Opening YAML config file '{}'".format(filename))
        try:
            with open(filename) as f:
                self.data = yaml.load(f.read())
        except yaml.YAMLError as e:
            self.log.error("File '{}' cannot be parsed!".format(filename))
            self.log.error("{}".format(e))
        self.log.info("{} YAML parsed succesfully".format(filename))

    def getValue(self, *keys):
        """Search through our data and find the specified key or subkey"""

        data = self.data
        ##Iterate through the key heirarchy
        for i in keys:
            try:
                data = data.get(i)
            except KeyError:
                self.log.error("Key {} not found".format(
                    self._formatKey(keys)))
                return None
        return data

    def _formatKey(self, keys):
        """Pretty print a key heirarchy"""

        form = ""
        for key in keys:
            form += "{} -> ".format(key)
        return form[:-3]
Esempio n. 2
0
 def __init__(self, board):
     self.log = Log()
     self.log.info("Getting /{}/...".format(board))
     try:
         self.board = chan.Board(board)
         self.log.info("/{}/ was fetched successfully".format(board))
     except Exception as e:
         self.log.error("Failed to fetch /{}/ -- {}".format(board, e))
Esempio n. 3
0
 def __init__(self, filename, sep=":"):
     self.log = Log()
     self.filename = filename
     self.log.info("Reading {}".format(filename))
     self.config = {}
     self.sep = sep
     self._readFile()
     self._extractConfig()
     self.log.info("Succesfully parsed {}".format(filename))
Esempio n. 4
0
 def __init__(self, filename):
     self.log = Log()
     self.log.info("Opening YAML config file '{}'".format(filename))
     try:
         with open(filename) as f:
             self.data = yaml.load(f.read())
     except yaml.YAMLError as e:
         self.log.error("File '{}' cannot be parsed!".format(filename))
         self.log.error("{}".format(e))
     self.log.info("{} YAML parsed succesfully".format(filename))
Esempio n. 5
0
    def __init__(self, corpus, n, debug=False, model=None):
        self.log = Log()

        if debug:
            self.log.setLevel(self.log.DEBUG)

        self.n = n
        self.log.info("Initialising {}-Gram model...".format(n))

        if model:
            self.model = model
        else:
            if type(corpus) == type([]):
                self.buildModel(corpus)
            else:
                self.buildModel([corpus])
        self.log.info("{}-Gram model ready for use".format(self.n))
Esempio n. 6
0
 def __init__(self, board):
   self.log = Log()
   self.log.info("Getting /{}/...".format(board))  
   try:
     self.board = chan.Board(board)
     self.log.info("/{}/ was fetched successfully".format(board))
   except Exception as e:
     self.log.error("Failed to fetch /{}/ -- {}".format(board, e))
    def __init__(self, f_name, f_obj, help, module="Builtin"):
        self.log = Log()
        self.log.newline()
        self.log.info("Creating command {}".format(f_name))
        self.log.line("-")
        self.name = f_name
        self.func = f_obj
        self.help = self.func.__doc__ or ""
        self.module = module
        self.admin_required = "admin" in self.func.__code__.co_varnames
        self.nargs = self.func.__code__.co_argcount
        self.defaults = self.func.__defaults__
        self.argdefault = {}
        if (self.defaults):
            self.noptargs = len(self.defaults)
        else:
            self.noptargs = 0
        self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs]
        self.optargs = self.func.__code__.co_varnames[self.nargs - self.
                                                      noptargs:self.noptargs +
                                                      1]
        self.hints = typing.get_type_hints(self.func)
        if "self" in self.args:
            self.nargs -= 1
        self.args = tuple([x for x in self.args if x != "self"])
        for i in range(self.noptargs):
            self.argdefault[self.optargs[i]] = self.defaults[i]

        if self.nargs > 0:
            self.log.info("ARGS: " + ", ".join(self.args))
            self.log.info("OPTARGS: " + ", ".join(self.optargs))
            self.log.info("DEFAULTS: " + ", ".join([
                "{}={}".format(i, self.argdefault[i]) for i in self.argdefault
            ]))
        else:
            self.log.info("No arguments")
        self.delim = ","
        self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames

        self.success = True
        self.log.line("-")
        self.log.info(self)
Esempio n. 8
0
  def __init__(self): 

    self.log = Log()    
    __builtins__["chat"] = self
    self.log.newline()
    self.log.info("SKYPE BOT INIT")
    self.log.line("+",40)
    self.log.incIndent()
    self.log.newline()
    self.log.info("SKYPE4PY STARTUP")
    self.log.line()
    self.log.incIndent()
    self.s = skype.Skype()
    ##Connect to the API
    self.s.Attach()
    self.log.decIndent()
    self.log.line()
    self.log.info("SKYPE4PY STARTED")
    self.log.newline()
    ##Set initial variables
    self.lastMessage = None
    
    ##Create a processor for all possible commands
    self.cmdProc = commandprocessor.CommandProcessor()

    ##Try to connect to the chat
    try:
      self.chat = self.s.ActiveChats[0]
    except Exception as e:
      print("Cloud chat not supported! {}".format(e))
      sys.exit(1)
  
    ##Allow for some twiddling
    self.lastMessage = self.chat.Messages[0]
 
    ##Alert users to the bot presence
    self.log.line("+", 40)
    self.log.info("FINISHED SKYPE BOT INIT")
    self.log.newline()
Esempio n. 9
0
 def __init__(self, corpus, n, debug=False, model=None):
   self.log = Log()
   
   if debug:
     self.log.setLevel(self.log.DEBUG)
   
   self.n = n
   self.log.info("Initialising {}-Gram model...".format(n))   
   
   if model:
     self.model = model
   else:
     if type(corpus) == type([]):
       self.buildModel(corpus)
     else:
       self.buildModel([corpus])
   self.log.info("{}-Gram model ready for use".format(self.n))
  def __init__(self, f_name, f_obj, help, module = "Builtin"):
    self.log = Log()
    self.log.newline()
    self.log.info("Creating command {}".format(f_name))
    self.log.line("-")
    self.name = f_name
    self.func = f_obj
    self.help = self.func.__doc__ or ""
    self.module = module
    self.admin_required = "admin" in self.func.__code__.co_varnames
    self.nargs = self.func.__code__.co_argcount
    self.defaults = self.func.__defaults__
    self.argdefault = {}
    if (self.defaults):
      self.noptargs = len(self.defaults) 
    else:
      self.noptargs = 0
    self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs]
    self.optargs = self.func.__code__.co_varnames[self.nargs-self.noptargs:
                                                  self.noptargs+1]
    self.hints = typing.get_type_hints(self.func) 
    if "self" in self.args:
      self.nargs -= 1
    self.args = tuple([x for x in self.args if x != "self"])
    for i in range(self.noptargs):
      self.argdefault[self.optargs[i]] = self.defaults[i]

    if self.nargs > 0:
      self.log.info("ARGS: " + ", ".join(self.args))
      self.log.info("OPTARGS: " + ", ".join(self.optargs))
      self.log.info("DEFAULTS: " + ", ".join(
                            ["{}={}".format(
                      i, self.argdefault[i]) for i in self.argdefault]))      
    else:
      self.log.info("No arguments")
    self.delim = ","
    self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames

    self.success = True
    self.log.line("-")
    self.log.info(self)
Esempio n. 11
0
class FourChan:
  """Wrapper class to py4chan - 4chan API"""

  def __init__(self, board):
    self.log = Log()
    self.log.info("Getting /{}/...".format(board))  
    try:
      self.board = chan.Board(board)
      self.log.info("/{}/ was fetched successfully".format(board))
    except Exception as e:
      self.log.error("Failed to fetch /{}/ -- {}".format(board, e))

  def getPosts(self,limit=10):
    self.log.info("Getting posts - limit of {}".format(limit))
    return self.board.get_all_thread_ids()[:limit+1]

  def getTitles(self):
    self.log.info("Getting thread titles...")
    q = []
    for x in self.getPosts():
      b = self.board.get_thread(x).posts
      q += [self._scrub(y.comment) for y in b]
    self.log.info("Got titles of threads successfully")
    return [x for x in q if x != '']

  def _scrub(self, post):
    """Clean up the posts, remove all HTML and formatting"""
    scrubs = ["<span class=\"quote\">", "<br>", "</span>","</s>"]
    
    for i in scrubs:
      post = post.replace(i, " ")
    post = post.replace("&gt;", ">").replace("&#039;", "'").replace("&quot;", "\"")
    post = post.replace("&lt;", "<")
    q = re.compile("<\/?[A-Za-z0-9\/\=\#\"\': ]*>")
    for w in q.findall(post):
      post = post.replace(w, "")
    postnums = re.compile(">?[0-9]{4,}")
    for w in postnums.findall(post):
      post = post.replace(w, "")
    return post.replace(">\n","").replace("\n", "")
    def __init__(self, configfile="command-proc.conf"):
        super(CommandProcessor, self).__init__()

        #Open a logger for superior feedback(tm)
        self.log = Log()

        #Alert the user that we're starting the processor
        self.log.info("Command Processor Created")
        self.log.newline()
        self.log.info("CMDPROC INIT")
        self.log.line()
        self.log.incIndent()

        #Set up some initial variables
        self.triggers = []
        self.services = []
        self.pipes = []
        self.commands = {}
        self.loadedModules = ["Builtin"]

        #Read in the config
        self.log.info("Reading config...")
        self.config = YamlConf(configfile)
        self.log.info("Setting config...")

        #Load in the config
        #The getValue() or "Value" means that we have a default
        #So if we can't get something from the config, it defaults to something
        self.bot_name = self.config.getValue("bot", "name") or "Bot"
        self.bot_version = self.config.getValue("bot", "version") or "0.01"
        self.msg_prefix = self.config.getValue("bot", "msg_prefix") or "BOT: "
        self.command_prefix = self.config.getValue("bot", "cmd_prefix") or "!"
        debug = self.config.getValue("bot", "debug_logging") or False
        module_path = self.config.getValue("modules", "path") or "."

        #This means python will be able to find modules
        #When python looks for things, it goes down a so-called PYTHONPATH
        #We give it some new directories to look in
        self.module_path = module_path
        sys.path.insert(0, module_path)
        initial_modules = self.config.getValue("modules", "load") or []
        inital_triggers = self.config.getValue("triggers") or []
        self.admins = self.config.getValue("admins")
        self.log.info("Read config.")

        #callback means that we run a function once we're done
        #processing something, so like we can go
        # output = process("!hello")
        # callback(output)
        #By default it's just print, so we print the output
        self.callback = print

        #Set up the input and output queues
        self.log.info("Initilising command queue...")
        self.cmdQ = queue.Queue()
        self.log.info("Initilising output queue...")
        self.outputQ = queue.Queue()

        #Set up some stuff so we can tell the commandprocessor to stop
        #when we want to exit, we turn the Event on
        self.log.info("Initilising requests...")
        self.stopReq = threading.Event()
        self.stopNOW = threading.Event()

        #We have a few "initial modules", things to load on startup
        self.log.info("Setting up modules...")
        for i in initial_modules:
            self.loadModule(i)

        #Same goes for triggers
        self.log.info("Setting up triggers...")
        for i in inital_triggers:
            self.addTrigger(i, inital_triggers[i])

        #If the user wants more information than usual, they can set debug to True
        self.log.info("Setting verbosity...")
        if debug:
            self.log.setLevel(self.log.DEBUG)

        #For reference: an underscore before the function name means that it only has INTERNAL use,
        #i.e nobody outside this class should call _addUtilityCommands()
        self._addUtilityCommands()

        #Tell the user that we've finished setting everything up
        self.log.line()
        self.log.info("FINISHED CMDPROC INIT")
        self.log.newline()
Esempio n. 13
0
#!/usr/bin/env python3

from floatingutils.log import Log

log = Log()
log.info("API Module Ready.")
Esempio n. 14
0
#!/usr/bin/env python3

from floatingutils.log import Log

log = Log()
log.info("Artificial Intelligence Module Ready.")
Esempio n. 15
0
 def __init__(self, useragent="FloatingGhost's python utility"):
   self.log = Log()
   self.log.info("Connecting to reddit...")
   self.api = praw.Reddit(user_agent=useragent)
   self.log.info("Connected.")
Esempio n. 16
0
class Reddit:
  def __init__(self, useragent="FloatingGhost's python utility"):
    self.log = Log()
    self.log.info("Connecting to reddit...")
    self.api = praw.Reddit(user_agent=useragent)
    self.log.info("Connected.")

  def getSub(self, subname, limit=100):
    """Get a subreddit"""

    self.log.info("Retrieving r/{}".format(subname))
    return self.api.get_subreddit(subname).get_hot(limit=limit)

  def getOPs(self, subname, limit=20):
    """Get the self text of the OPs in a subreddit"""

    self.log.info("Getting the OP self text in {} (limit {})".format(subname,limit))
    x = self.getSub(subname, limit)
    return [y.selftext for y in x if y.selftext != '']

  def getSubTitles(self, subname, limit=500):
    """Get the titles of a subreddit's posts"""
  
    self.log.info("Getting the titles in r/{}".format(subname))
    return [str(x).split("::")[-1][1:] for x in self.getSub(subname, limit)]

  def getComments(self, subname, limit=500):
    """Get the comments of a subreddit"""
    
    self.log.info("Getting the comments of r/{}".format(subname))
    x = self.api.get_subreddit(subname).get_comments(limit=limit)
    return [y.body for y in x]
Esempio n. 17
0
class NGram:
    """Class for an N-Gram model of a natural language corpus"""
    def __init__(self, corpus, n, debug=False, model=None):
        self.log = Log()

        if debug:
            self.log.setLevel(self.log.DEBUG)

        self.n = n
        self.log.info("Initialising {}-Gram model...".format(n))

        if model:
            self.model = model
        else:
            if type(corpus) == type([]):
                self.buildModel(corpus)
            else:
                self.buildModel([corpus])
        self.log.info("{}-Gram model ready for use".format(self.n))

    def buildModel(self, list_corpus):
        """Build a model from a list of strings"""
        #Pad out the message
        corpus = ""

        self.log.info("Creating N-Gram model from {} string{}".format(
            len(list_corpus), "s" if len(list_corpus) > 1 else ""))

        for i in list_corpus:
            #Remove punctuation
            i = i.replace(",", " ").replace(".", " ")

            corpus += " <s> " * (self.n - 1) + i + " <s> " * (self.n -
                                                              2) + " <end>"
        corpus = corpus.strip().lower()
        nlen = []
        self.log.info("Splitting corpus into {} length strings".format(self.n))
        corpus = [x for x in corpus.split(" ") if x != '']
        for i in range(len(corpus) - 1):
            nlen.append(corpus[i:i + self.n])
        if len(nlen) > 6000:
            nlen = nlen[:6000]
        qqq = len(nlen)
        self.log.info("Processing {} {}-length strings".format(
            len(nlen), self.n))
        self.model = []
        endWords = []
        givenWords = []
        for i in nlen:
            word = i[-1]
            given = i[:-1]
            if word not in endWords:
                endWords.append(word)
            if given not in givenWords:
                givenWords.append(given)

        self.log.info("Calculating probabilities...")
        #calculate probs
        percentages = range(10, 101, 10)
        for w in givenWords:
            p = givenWords.index(w) / qqq
            p = 100 * p
            if p > percentages[0]:
                self.log.info("{}% done...".format(p))
                percentages = percentages[1:]
            occurances = [x for x in nlen if x[:-1] == w]
            for x in occurances:
                y = x[-1]  ##endword
                endswith = [z for z in occurances if z[-1] == y]
                ##Count number of occurrences
                try:
                    modelAdd = [
                        x[-1], w, 1.0 / (1 + len(occurances) - len(endswith))
                    ]
                except ZeroDivisionError:
                    ##Prob must be 1
                    modelAdd = [x[-1], w, 1.0]
                self.model.append(modelAdd)

        self.log.info("{}-Gram model built!".format(self.n))

    def generate(self):
        """Generate a possible message from the model"""
        self.log.info("Generating a possible string...")
        try:
            m = "<s>"
            while m.split(" ")[-1] != "<end>":
                m += " " + random.choice(
                    self.getAllFromGiven(m.split(" ")[-self.n + 1:]))
            self.log.info("Generated!")
            return m.replace("<s>", "").replace("<end>", "")
        except IndexError:
            return "Could not generate... not enough data!"

    def getAllFromGiven(self, given):
        """Get all instances of x, where (given, x) is a member of the model"""
        j = []
        for i in self.model:
            if i[1] == given:
                j.append(i[0])
        return j

    def getProb(self, word, given):
        """Get P(word|given)"""
        ##Find P(word | given)
        for i in self.model:
            g = listtostr_(i[1])
            if i[0] == word and given == g:
                return i[2]
        return 0
class CommandProcessor(threading.Thread):
    """Thread-based module for processing commands. 
	Takes in commands from a queue, processes them asyncronously,
	outputs to another queue.
	ARGS: configfile -- The file to load in all of our configuration from
  """
    def __init__(self, configfile="command-proc.conf"):
        super(CommandProcessor, self).__init__()

        #Open a logger for superior feedback(tm)
        self.log = Log()

        #Alert the user that we're starting the processor
        self.log.info("Command Processor Created")
        self.log.newline()
        self.log.info("CMDPROC INIT")
        self.log.line()
        self.log.incIndent()

        #Set up some initial variables
        self.triggers = []
        self.services = []
        self.pipes = []
        self.commands = {}
        self.loadedModules = ["Builtin"]

        #Read in the config
        self.log.info("Reading config...")
        self.config = YamlConf(configfile)
        self.log.info("Setting config...")

        #Load in the config
        #The getValue() or "Value" means that we have a default
        #So if we can't get something from the config, it defaults to something
        self.bot_name = self.config.getValue("bot", "name") or "Bot"
        self.bot_version = self.config.getValue("bot", "version") or "0.01"
        self.msg_prefix = self.config.getValue("bot", "msg_prefix") or "BOT: "
        self.command_prefix = self.config.getValue("bot", "cmd_prefix") or "!"
        debug = self.config.getValue("bot", "debug_logging") or False
        module_path = self.config.getValue("modules", "path") or "."

        #This means python will be able to find modules
        #When python looks for things, it goes down a so-called PYTHONPATH
        #We give it some new directories to look in
        self.module_path = module_path
        sys.path.insert(0, module_path)
        initial_modules = self.config.getValue("modules", "load") or []
        inital_triggers = self.config.getValue("triggers") or []
        self.admins = self.config.getValue("admins")
        self.log.info("Read config.")

        #callback means that we run a function once we're done
        #processing something, so like we can go
        # output = process("!hello")
        # callback(output)
        #By default it's just print, so we print the output
        self.callback = print

        #Set up the input and output queues
        self.log.info("Initilising command queue...")
        self.cmdQ = queue.Queue()
        self.log.info("Initilising output queue...")
        self.outputQ = queue.Queue()

        #Set up some stuff so we can tell the commandprocessor to stop
        #when we want to exit, we turn the Event on
        self.log.info("Initilising requests...")
        self.stopReq = threading.Event()
        self.stopNOW = threading.Event()

        #We have a few "initial modules", things to load on startup
        self.log.info("Setting up modules...")
        for i in initial_modules:
            self.loadModule(i)

        #Same goes for triggers
        self.log.info("Setting up triggers...")
        for i in inital_triggers:
            self.addTrigger(i, inital_triggers[i])

        #If the user wants more information than usual, they can set debug to True
        self.log.info("Setting verbosity...")
        if debug:
            self.log.setLevel(self.log.DEBUG)

        #For reference: an underscore before the function name means that it only has INTERNAL use,
        #i.e nobody outside this class should call _addUtilityCommands()
        self._addUtilityCommands()

        #Tell the user that we've finished setting everything up
        self.log.line()
        self.log.info("FINISHED CMDPROC INIT")
        self.log.newline()

    def join(self, timeout=None):
        """When the owner of CommandProcessor wants us to exit, 
    we alert the user that we've recieved the quit request,
    and shut everythig down
    """

        self.log.info("QUITTING")
        self.log.line("Q")
        #Tell the processing function to stop
        self.stopReq.set()

        #Join the thread to the main process,
        #wait for `timeout` seconds before forcing it to.
        super(Thread, self).join(timeout)

    def addCommand(self,
                   function_name,
                   function_object,
                   help=None,
                   module="Builtin"):
        """Add a command to the processor
       ARGS:
        function_name: The name you wish to call the function by, i.e "func" 
        function_object: The actual object to run when you call the command
    """

        self.log.info("Adding command {}".format(function_name))

        #Check if we've already got a command by name `function_name`
        if function_name in self.commands:
            self.log.info("Command {} already registered. Overwriting")

        #Make a nice little command object, for keeping track of it
        com = Command(function_name, function_object, help=help, module=module)

        #Make sure it actually worked yo
        if com.success:
            self.commands[function_name] = com
        else:
            self.log.info("Failed to add command")

    def removeCommand(self, function_name):
        """WHAT THE FEK DO YOU THINK IT DOES? MAKE CAKE? NO. IT REMOVES A COMMAND!"""

        #Check that we've actually got a command by that name
        if function_name in self.commands:
            #If we do, delete it!
            del self.commands[function_name]
            self.log.info("Succesfully removed {}".format(function_name))
        else:
            #Otherwise, we can't. Because you can't delete something that doesn't exist, dummy
            self.log.info("Could not remove non-existent function {}".format(
                function_name))

    def addTrigger(self, trigger_text, replacement_text):
        """Add a text-based trigger - will send replacement_text when
       trigger_text is in a given message"""

        #Check if we've got a trigger about that already, because we might
        for trigger in self.triggers:
            if trigger.trigger == trigger_text:
                #If we do, modifify it to the new trigger
                trigger.send_text = replacement_text
                return ("Modified trigger to {}".format(trigger))

        #If we haven't got a trigger about `trigger_text`,
        #make a new one
        self.triggers.append(Trigger(trigger_text, replacement_text))
        self.log.info("Added {}".format(self.triggers[-1]))
        return ("Added -- {}".format(self.triggers[-1]))

    def writeConfig(self):
        """Save the config, all currently loaded modules will be saved to init_modules"""
        self.log.info("Writing config...")

        #Add all of our triggers to a nice little dictionary,
        #So we can write it to a file
        trigs = {}
        for i in self.triggers:
            trigs[i.trigger] = i.send_text

        settings = {
            "bot": {
                "name": self.bot_name,
                "version": self.bot_version,
                "msg_prefix": self.msg_prefix,
                "cmd_prefix": self.command_prefix,
                "debug_logging": False
            },
            "modules": {
                "path": self.module_path,
                "load": self.loadedModules
            },
            "triggers": trigs,
            "ai": {
                "model_directory": "models"
            },
            "admins": self.admins
        }

        self.log.info(settings)

        #Write the config in YAML format
        with open("command-proc.conf", "w") as f:
            f.write(pyaml.dump(settings))
        self.log.info("Written")

    def removeTrigger(self, txt):
        """Remove the trigger with `trigger_text` == `txt`"""

        for trigger in self.triggers:
            if trigger.trigger == txt:
                self.triggers.remove(trigger)
                return ("Removed {}".format(trigger))

    def setCallback(self, function):
        """Set the function to run on function complete
       ARGS: function (python function)"""
        self.callback = function

    def _process(self, command):
        """Internal process command - parse the command and execute"""
        self.log.info("Processing request {}...".format(command[0]))

        #Remove trailing and preceeding spaces

        #isinstance checks if command is a string or list
        #e.g isinstance("hello", str) is True
        #isinstance("hello", list) is False

        if isinstance(command, str):
            command = [command, None]
        if isinstance(command[0], list):
            command = command[0]
        command[0] = command[0].strip()

        try:
            #Check if it's a command or not
            if command[0][0] == self.command_prefix:
                #It's a command
                self._checkAgainstCommands(command)
            else:
                #We'll check it against the triggers
                self._checkAgainstTriggers(command)
        except Exception:
            pass

    def _checkAgainstCommands(self, command):
        command, channel = command
        command = command[1:]
        command_name, sep, args = command.partition(" ")
        if command_name in self.commands:
            #Now we've verified, go ahead and run it
            try:
                cmd = self.commands[command_name].run(args)
                if type(cmd) == types.GeneratorType:
                    for i in cmd:
                        self.output([i, channel])
                else:
                    self.output([cmd, channel])

            except ArgumentFormatError:
                self.output("Error running {} -- Argument format error".format(
                    command_name))
            except TypeError:
                pass

        else:

            self.log.info(
                "No command of name {} detected".format(command_name))
            self.output(
                "Error running {} -- Command not found".format(command_name))

    def output(self, val):
        self.outputQ.put(val)
        if self.callback:
            self.callback(*val)

    def _checkAgainstTriggers(self, command):
        for i in self.triggers:
            if i.match(command[0]):
                self.output([i.send_text, command[1]])

    def getOutput(self):
        try:
            x = self.outputQ.get(False)
        except queue.Empty:
            return None
        return x

    def run(self):
        """Start the thread off"""
        self.log.info("Command processor thread starting...")
        while (not self.stopReq.isSet()) or self.cmdQ.qsize() != 0:
            if self.stopNOW.isSet():
                break
            try:
                toProcess = self.cmdQ.get(True, 0.5)
                self._process(toProcess)
            except queue.Empty:
                continue
            except Exception as e:
                self.log.error(e)
                traceback.format_exc(e)

        self.log.info("Stopping with qsize: {}".format(self.cmdQ.qsize()))
        self.log.info("Stopreq state: {}".format(self.stopReq.isSet()))
        self.log.info("Thread closed.")

    def push(self, commandstring, assoc_info=None):
        """Add a command to the command queue - to be processed commands
       ARGS: commandstring (str) - the command to process
             assoc_info (Any) - Things to be returned with the processed cmd"""
        self.log.info("Pushing command {}".format(commandstring))
        self.cmdQ.put([commandstring, assoc_info])
        for pipe in self.pipes:
            pipe.put([commandstring, assoc_info])

    def exit(self, now=False):
        """Quit the thread, cleanly exit"""
        admin = 1
        yield "Closing..."
        self.log.info("Exit request acknowledged, will exit.")
        self.stopReq.set()
        if (now):
            self.stopNOW.set()

    ##Module loading/unloading
    def loadModule(self, name):
        self.log.newline()
        self.log.info("LOADING MODULE {}".format(name.upper()))
        self.log.line()
        self.log.incIndent()
        try:
            ##Try loading the module as i
            yield ("Importing {}...".format(name))
            i = importlib.import_module(name)
            ##In case it's changed and was imported before, reload it
            self.log.debug("Reloading...")
            i = importlib.reload(i)
            ##Get a list of all the functions defined in the module
            self.log.debug("Getting functions...")
            funcs = dir(i)
            ##Don't import python's internal functions, like __name__ and __init__
            x = re.compile("__[a-z]*__")
            z = ([("i.{}".format(y)) for y in funcs
                  if not (x.match(y) or y[-1] == "_")])
            self.log.debug("Loaded, adding functions...")
            self.log.incIndent()
            self.funcs = "Loaded functions:\n"
            ##Load the functions in
            for j in z:
                if type(eval(j)) == types.FunctionType:
                    if "onimport" in j:
                        self.log.info("Running import function...")
                        eval(j)()
                    elif "onexit" in j:
                        atexit.register(eval(j))
                    else:
                        self.addCommand(j.split(".")[1], eval(j), module=name)
                        self.funcs += "!{}, ".format(j.split(".")[1])
            if name not in self.loadedModules:
                self.loadedModules.append(name)

            yield (self.funcs)
        except ImportError as ie:
            self.log.error("Could not find module {}".format(name))
            self.log.error(ie)
        except Exception as e:
            self.log.error("Unknown exception: {}".format(e))

    def unloadModule(self, module_name):
        yield "Unloading module {}".format(module_name)
        funcs = "( "
        for i in self.commands:
            if self.commands[i].module == module_name:
                self.removeCommand(i)
                funcs += i + ", "
        self.loadedModules.remove(module_name)
        self.log.info("Unloaded {} {} )".format(module_name, funcs))

    def lsmod(self):
        """List all currently loaded modules"""
        x = "Loaded modules: \n"
        x += "\n".join(self.loadedModules)
        return (x + "\n")

    def getHelp(self, cmd=None):
        if cmd:
            if cmd in self.commands:
                return (self.commands[cmd].getHelp())
            else:
                return ("Command {} does not exist".format(cmd))
        else:
            #Return list of commands
            return "Available Commands: " + ", ".join(self.commands)

    def listTriggers(self):
        return "\n".join([str(x) for x in self.triggers])

    def loadService(self, srvname):
        self.services.append(
            Service(name=srvname, function=function, autostart=True))

    def startService(self, srvname):
        for i in self.services:
            if i.name == srvname:
                i.start()
                return "Started"
        return "Service not found"

    def killService(self, srvname):
        for i in self.services:
            if i.name == srvname:
                i.stop()
                self.services.remove(i)
                return "Killed"
        return "Service not found"

    def lsService(self):
        x = [i.name for i in self.services]
        return "\n".join(x)

    def _addUtilityCommands(self):
        self.addCommand("lsmod", self.lsmod)
        self.addCommand("import", self.loadModule)
        self.addCommand("quit", self.exit)
        self.addCommand("help", self.getHelp)
        self.addCommand("mktrig", self.addTrigger)
        self.addCommand("rmtrig", self.removeTrigger)
        self.addCommand("lstrig", self.listTriggers)
        self.addCommand("writeconf", self.writeConfig)
        self.addCommand("loadSrv", self.loadService)
        self.addCommand("startSrv", self.startService)
        self.addCommand("killSrv", self.killService)
        self.addCommand("lsSrv", self.lsService)
Esempio n. 19
0
#!/usr/bin/env python3

from floatingutils.log import Log
import requests
import sys

log = Log()


class Client:
    def __init__(self, IP: str, PORT: int, protocol: str = "http"):
        self.ip = IP
        self.port = PORT
        self.socket = "{}://{}:{}".format(protocol, IP, PORT)

        log.info("Connecting to server {}".format(self.socket))

    def post(self, path, data: dict = {}):
        try:
            data["SESSION_KEY"] = self.session
        except AttributeError:
            pass

        try:
            r = requests.post("{}/{}".format(self.socket, path), data=data)
        except requests.exceptions.ConnectionError:
            log.error("Server did not respond.")
            sys.exit(1)
        return self._processResponse(r.text)

    def getServerPub(self):
Esempio n. 20
0
#!/usr/bin/env python3

from floatingutils.log import Log
Log().info("Utils ready.")
Esempio n. 21
0
class FourChan:
    """Wrapper class to py4chan - 4chan API"""
    def __init__(self, board):
        self.log = Log()
        self.log.info("Getting /{}/...".format(board))
        try:
            self.board = chan.Board(board)
            self.log.info("/{}/ was fetched successfully".format(board))
        except Exception as e:
            self.log.error("Failed to fetch /{}/ -- {}".format(board, e))

    def getPosts(self, limit=10):
        self.log.info("Getting posts - limit of {}".format(limit))
        return self.board.get_all_thread_ids()[:limit + 1]

    def getTitles(self):
        self.log.info("Getting thread titles...")
        q = []
        for x in self.getPosts():
            b = self.board.get_thread(x).posts
            q += [self._scrub(y.comment) for y in b]
        self.log.info("Got titles of threads successfully")
        return [x for x in q if x != '']

    def _scrub(self, post):
        """Clean up the posts, remove all HTML and formatting"""
        scrubs = ["<span class=\"quote\">", "<br>", "</span>", "</s>"]

        for i in scrubs:
            post = post.replace(i, " ")
        post = post.replace("&gt;", ">").replace("&#039;",
                                                 "'").replace("&quot;", "\"")
        post = post.replace("&lt;", "<")
        q = re.compile("<\/?[A-Za-z0-9\/\=\#\"\': ]*>")
        for w in q.findall(post):
            post = post.replace(w, "")
        postnums = re.compile(">?[0-9]{4,}")
        for w in postnums.findall(post):
            post = post.replace(w, "")
        return post.replace(">\n", "").replace("\n", "")
Esempio n. 22
0
class Chat:
  """Represents a chat class in a skype client"""
  def __init__(self): 

    self.log = Log()    
    __builtins__["chat"] = self
    self.log.newline()
    self.log.info("SKYPE BOT INIT")
    self.log.line("+",40)
    self.log.incIndent()
    self.log.newline()
    self.log.info("SKYPE4PY STARTUP")
    self.log.line()
    self.log.incIndent()
    self.s = skype.Skype()
    ##Connect to the API
    self.s.Attach()
    self.log.decIndent()
    self.log.line()
    self.log.info("SKYPE4PY STARTED")
    self.log.newline()
    ##Set initial variables
    self.lastMessage = None
    
    ##Create a processor for all possible commands
    self.cmdProc = commandprocessor.CommandProcessor()

    ##Try to connect to the chat
    try:
      self.chat = self.s.ActiveChats[0]
    except Exception as e:
      print("Cloud chat not supported! {}".format(e))
      sys.exit(1)
  
    ##Allow for some twiddling
    self.lastMessage = self.chat.Messages[0]
 
    ##Alert users to the bot presence
    self.log.line("+", 40)
    self.log.info("FINISHED SKYPE BOT INIT")
    self.log.newline()

  def send(self, msg):
    """Send a message to the chat"""
    if msg != None and msg != "" and type(msg) != type(True):
      self.chat.SendMessage(">>>"+msg)

  def processMessage(self):
    """Figure out what to do with the last received message"""
    if ">>>" not in self.lastMessage.Body:
      self.log.info("Processing {}".format(self.lastMessage.Body))
      self.cmdProc.push([self.lastMessage.Body, None])
    
  def mainloop(self):
    self.log.info("Starting mainloop...")
    self.cmdProc.start()
    threading.Thread(target=self.getOutput).start()
    self.log.info("Started thread.")
    while 1:
      try:
        newmsg = self.chat.Messages[0]
        if self.lastMessage != newmsg:
          self.lastMessage = newmsg
          self.processMessage()
      except KeyboardInterrupt:
        sys.exit()
   
  def addCommand(self, cmdName, func):
    self.cmdProc.addCommand(cmdName, func)

  def getAllBy(self, handle):
    return [i.Body for i in self.chat.Messages if str(i.FromHandle).lower() == handle]

  def getOutput(self):
    self.log.info("Starting output thread...")
    while True:
      x = (self.cmdProc.getOutput())
      if type(x) == list:
        self.send(x[0])
      else:
        self.send(x)
Esempio n. 23
0
class Reddit:
    def __init__(self, useragent="FloatingGhost's python utility"):
        self.log = Log()
        self.log.info("Connecting to reddit...")
        self.api = praw.Reddit(user_agent=useragent)
        self.log.info("Connected.")

    def getSub(self, subname, limit=100):
        """Get a subreddit"""

        self.log.info("Retrieving r/{}".format(subname))
        return self.api.get_subreddit(subname).get_hot(limit=limit)

    def getOPs(self, subname, limit=20):
        """Get the self text of the OPs in a subreddit"""

        self.log.info("Getting the OP self text in {} (limit {})".format(
            subname, limit))
        x = self.getSub(subname, limit)
        return [y.selftext for y in x if y.selftext != '']

    def getSubTitles(self, subname, limit=500):
        """Get the titles of a subreddit's posts"""

        self.log.info("Getting the titles in r/{}".format(subname))
        return [
            str(x).split("::")[-1][1:] for x in self.getSub(subname, limit)
        ]

    def getComments(self, subname, limit=500):
        """Get the comments of a subreddit"""

        self.log.info("Getting the comments of r/{}".format(subname))
        x = self.api.get_subreddit(subname).get_comments(limit=limit)
        return [y.body for y in x]
Esempio n. 24
0
class Conf:
    """Class for parsing simple (key sep value) format files"""
    def __init__(self, filename, sep=":"):
        self.log = Log()
        self.filename = filename
        self.log.info("Reading {}".format(filename))
        self.config = {}
        self.sep = sep
        self._readFile()
        self._extractConfig()
        self.log.info("Succesfully parsed {}".format(filename))

    def _readFile(self):
        """Read in the configuration file"""

        self.log.debug("Opening file {}".format(self.filename))
        ##Open the config file
        try:
            f = open(self.filename, "r")
        except FileNotFoundError:
            self.log.error("File '{}' not found!".format(self.filename))

        ##Read in each line, ignoring empty lines
        self.text = [x[:-1] for x in f.readlines() if x[:-1] != ""]
        self.log.debug("File read succesfully")
        ##Close the file
        f.close()
        self.log.debug("{} closed".format(self.filename))

    def writeFile(self, alternateFile=None):
        """Write the changed configuration back to a file"""

        self.log.info("Writing config back to file")
        filename = self.filename
        ##Just in case the user wants to change location
        if alternateFile:
            filename = alternateFile
        self.log.info("Writing to {}".format(filename))

        try:
            with open(filename, "w") as f:
                for i in sorted(self.config):
                    f.write("{}:{}\n".format(i, self.config[i]))
        except Exception as e:
            self.log.warning("An error occurred -- {}".format(e))
            return 1
        self.log.debug("{} Written succesfully".format(filename))
        return 0

    def _extractConfig(self):
        """Get all the key value pairs from the config file"""

        ##Keep track of line of debug purposes
        lineno = 1
        for i in self.text:
            ##Split the line by the seperator
            setting, sep, value = i.partition(self.sep)
            if setting in self.config:
                ##If we've already seen that key before
                self.log.warning("Duplicate setting '{}' (Line {})".format(
                    setting, lineno))
            else:
                ##Check for empty setting name
                if setting == "":
                    self.log.warning(
                        "Empty setting name (Line {})".format(lineno))
                else:
                    ##Check for empty value
                    if value == "":
                        self.log.warning(
                            "Empty setting value '{}'(Line {})".format(
                                setting, lineno))
                    else:
                        ##It all looks good
                        self.config[setting] = value
            lineno += 1

    def getValue(self, key):
        """Get the value associated with a key"""

        if key in self.config:
            return self.config[key]
        else:
            ##If we can't find the key
            self.log.error("Setting '{}' not found!".format(key))
            return 0

    def getData(self, key):
        """Get the parsed value of a key - for lists and dicts"""
        x = self.getValue(key)
        return eval(x)

    def setValue(self, key, value):
        """Change the value of a setting"""

        if key == "":
            self.log.warning(
                "Non-empty keys only please! (value thrown: {})".format(value))
            return False
        else:
            self.config[key] = value
            return True
Esempio n. 25
0
#!/usr/bin/env python3

from floatingutils.log import Log

log = Log()

log.info("Networking submodule ready.")
class Command:
    def __init__(self, f_name, f_obj, help, module="Builtin"):
        self.log = Log()
        self.log.newline()
        self.log.info("Creating command {}".format(f_name))
        self.log.line("-")
        self.name = f_name
        self.func = f_obj
        self.help = self.func.__doc__ or ""
        self.module = module
        self.admin_required = "admin" in self.func.__code__.co_varnames
        self.nargs = self.func.__code__.co_argcount
        self.defaults = self.func.__defaults__
        self.argdefault = {}
        if (self.defaults):
            self.noptargs = len(self.defaults)
        else:
            self.noptargs = 0
        self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs]
        self.optargs = self.func.__code__.co_varnames[self.nargs - self.
                                                      noptargs:self.noptargs +
                                                      1]
        self.hints = typing.get_type_hints(self.func)
        if "self" in self.args:
            self.nargs -= 1
        self.args = tuple([x for x in self.args if x != "self"])
        for i in range(self.noptargs):
            self.argdefault[self.optargs[i]] = self.defaults[i]

        if self.nargs > 0:
            self.log.info("ARGS: " + ", ".join(self.args))
            self.log.info("OPTARGS: " + ", ".join(self.optargs))
            self.log.info("DEFAULTS: " + ", ".join([
                "{}={}".format(i, self.argdefault[i]) for i in self.argdefault
            ]))
        else:
            self.log.info("No arguments")
        self.delim = ","
        self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames

        self.success = True
        self.log.line("-")
        self.log.info(self)

    def getHelp(self):
        h = self.name + ":\n" + self.help
        if self.nargs > 0:
            h += "\nARGS: " + ", ".join(self.args) + "\n"
        if self.noptargs > 0:
            h += "\nOPTARGS: " + " , ".join(self.optargs)
        if "\n" not in h:
            h += " (No Arguments)"
        return h

    def run(self, args, user_is_admin=False):
        if self.admin_required and not user_is_admin:
            self.log.warning("{} requires administrative permissions".format(
                self.name))
        self.log.newline()
        self.log.newline()
        self.log.line("+")
        if not self.NOSPLIT:
            args = self._formatArgs(args.split(self.delim))
        else:
            args = self._formatArgs([args])
        self.log.info("Running {} with args {}".format(self.name, args))
        output = self.func(**args)
        self.log.line("+")
        self.log.newline()
        self.log.newline()
        return output

    def _formatArgs(self, args):
        args = [x.strip() for x in args if x != '']
        processedArgs = {}
        allargs = self.args + self.optargs
        for i in range(self.nargs):
            arg = ""
            argn = allargs[i]
            if i >= len(args):
                arg = self.argdefault[argn]
            else:
                arg = args[i]
            if allargs[i] in self.hints:
                try:
                    arg = self.hints[argn](arg)
                except ValueError as ex:
                    raise ArgumentFormatError(ex)
            processedArgs[argn] = arg

        return processedArgs

    def __repr__(self):
        x = "\n\nCOMMAND DEFINITION ::- \n"
        return x + "\nCommand (\n Name: {}.{},\n Args: {},\n OptArgs: {}\n Admin: {}\n)\n".format(
            self.module, self.name, self.args, self.optargs,
            self.admin_required)
Esempio n. 27
0
 def __init__(self, useragent="FloatingGhost's python utility"):
     self.log = Log()
     self.log.info("Connecting to reddit...")
     self.api = praw.Reddit(user_agent=useragent)
     self.log.info("Connected.")
class CommandProcessor(threading.Thread):
  """Thread-based module for processing commands. 
	Takes in commands from a queue, processes them asyncronously,
	outputs to another queue.
	ARGS: configfile -- The file to load in all of our configuration from
  """

  def __init__(self, configfile = "command-proc.conf"):
    super(CommandProcessor, self).__init__()
    
    #Open a logger for superior feedback(tm)
    self.log = Log()
    
    #Alert the user that we're starting the processor
    self.log.info("Command Processor Created")
    self.log.newline()
    self.log.info("CMDPROC INIT")
    self.log.line()
    self.log.incIndent()

    #Set up some initial variables
    self.triggers = []
    self.services = []
    self.pipes = []
    self.commands = {}
    self.loadedModules = ["Builtin"]
    
    #Read in the config
    self.log.info("Reading config...")
    self.config = YamlConf(configfile)
    self.log.info("Setting config...")
   
    #Load in the config
    #The getValue() or "Value" means that we have a default
    #So if we can't get something from the config, it defaults to something 
    self.bot_name = self.config.getValue("bot", "name") or "Bot"
    self.bot_version = self.config.getValue("bot", "version") or "0.01"
    self.msg_prefix = self.config.getValue("bot", "msg_prefix") or "BOT: "
    self.command_prefix = self.config.getValue("bot", "cmd_prefix") or "!"
    debug = self.config.getValue("bot", "debug_logging") or False
    module_path = self.config.getValue("modules", "path") or "."

    #This means python will be able to find modules
    #When python looks for things, it goes down a so-called PYTHONPATH
    #We give it some new directories to look in
    self.module_path = module_path 
    sys.path.insert(0, module_path)
    initial_modules = self.config.getValue("modules", "load") or []
    inital_triggers = self.config.getValue("triggers") or []
    self.admins = self.config.getValue("admins")
    self.log.info("Read config.")

    #callback means that we run a function once we're done
    #processing something, so like we can go
      # output = process("!hello")
      # callback(output) 
    #By default it's just print, so we print the output
    self.callback = print

    #Set up the input and output queues
    self.log.info("Initilising command queue...")
    self.cmdQ = queue.Queue()
    self.log.info("Initilising output queue...")
    self.outputQ = queue.Queue()

    #Set up some stuff so we can tell the commandprocessor to stop
    #when we want to exit, we turn the Event on
    self.log.info("Initilising requests...")
    self.stopReq = threading.Event()
    self.stopNOW = threading.Event()

    #We have a few "initial modules", things to load on startup
    self.log.info("Setting up modules...")
    for i in initial_modules:
      self.loadModule(i)

    #Same goes for triggers
    self.log.info("Setting up triggers...")
    for i in inital_triggers:
      self.addTrigger(i, inital_triggers[i])

    #If the user wants more information than usual, they can set debug to True
    self.log.info("Setting verbosity...")
    if debug:
      self.log.setLevel(self.log.DEBUG)

    #For reference: an underscore before the function name means that it only has INTERNAL use,
    #i.e nobody outside this class should call _addUtilityCommands()
    self._addUtilityCommands()

    #Tell the user that we've finished setting everything up
    self.log.line()
    self.log.info("FINISHED CMDPROC INIT")   
    self.log.newline()
  
  def join(self, timeout=None):
    """When the owner of CommandProcessor wants us to exit, 
    we alert the user that we've recieved the quit request,
    and shut everythig down
    """

    self.log.info("QUITTING")
    self.log.line("Q")
    #Tell the processing function to stop
    self.stopReq.set()
  
    #Join the thread to the main process,
    #wait for `timeout` seconds before forcing it to.
    super(Thread, self).join(timeout)
  
  def addCommand(self, function_name, function_object, help=None, module="Builtin"):
    """Add a command to the processor
       ARGS:
        function_name: The name you wish to call the function by, i.e "func" 
        function_object: The actual object to run when you call the command
    """

    self.log.info("Adding command {}".format(function_name))

    #Check if we've already got a command by name `function_name`    
    if function_name in self.commands:
      self.log.info("Command {} already registered. Overwriting")
    
    #Make a nice little command object, for keeping track of it
    com = Command(function_name, function_object, help=help, module=module)

    #Make sure it actually worked yo
    if com.success:
      self.commands[function_name] = com
    else:
      self.log.info("Failed to add command")

  def removeCommand(self, function_name):
    """WHAT THE FEK DO YOU THINK IT DOES? MAKE CAKE? NO. IT REMOVES A COMMAND!"""

    #Check that we've actually got a command by that name
    if function_name in self.commands:
      #If we do, delete it!
      del self.commands[function_name]
      self.log.info("Succesfully removed {}".format(function_name))
    else:
      #Otherwise, we can't. Because you can't delete something that doesn't exist, dummy
      self.log.info("Could not remove non-existent function {}".format(function_name))
  
  def addTrigger(self, trigger_text, replacement_text):
    """Add a text-based trigger - will send replacement_text when
       trigger_text is in a given message"""

    #Check if we've got a trigger about that already, because we might
    for trigger in self.triggers:
      if trigger.trigger == trigger_text:
        #If we do, modifify it to the new trigger
        trigger.send_text = replacement_text
        return ("Modified trigger to {}".format(trigger))
        
    #If we haven't got a trigger about `trigger_text`, 
    #make a new one
    self.triggers.append(Trigger(trigger_text, replacement_text))
    self.log.info("Added {}".format(self.triggers[-1]))
    return ("Added -- {}".format(self.triggers[-1]))

  def writeConfig(self):
    """Save the config, all currently loaded modules will be saved to init_modules"""
    self.log.info("Writing config...")

    #Add all of our triggers to a nice little dictionary,
    #So we can write it to a file
    trigs = {}
    for i in self.triggers:
      trigs[i.trigger] = i.send_text

    settings = {
        "bot" : {
          "name": self.bot_name,
          "version": self.bot_version,
          "msg_prefix": self.msg_prefix,
          "cmd_prefix": self.command_prefix,
          "debug_logging": False
        },
        "modules" : {
          "path": self.module_path,
          "load": self.loadedModules
        },
        "triggers": trigs,
        "ai": {
          "model_directory": "models"
        },
        "admins": self.admins
      } 

    self.log.info(settings)
    
    #Write the config in YAML format 
    with open("command-proc.conf", "w") as f:
      f.write(pyaml.dump(settings))
    self.log.info("Written")

  def removeTrigger(self, txt):
    """Remove the trigger with `trigger_text` == `txt`"""

    for trigger in self.triggers:
      if trigger.trigger == txt:
        self.triggers.remove(trigger)
        return ("Removed {}".format(trigger))

  def setCallback(self, function):
    """Set the function to run on function complete
       ARGS: function (python function)"""
    self.callback = function

  def _process(self, command):
    """Internal process command - parse the command and execute"""
    self.log.info("Processing request {}...".format(command[0]))

    #Remove trailing and preceeding spaces
    
    #isinstance checks if command is a string or list
      #e.g isinstance("hello", str) is True
      #isinstance("hello", list) is False

    if isinstance(command, str):
      command = [command, None]
    if isinstance(command[0], list):
      command = command[0]
    command[0] = command[0].strip()

    try: 
      #Check if it's a command or not
      if command[0][0] == self.command_prefix:
        #It's a command
        self._checkAgainstCommands(command)
      else:
        #We'll check it against the triggers
        self._checkAgainstTriggers(command)
    except Exception:
      pass

  def _checkAgainstCommands(self, command):
    command,channel = command
    command = command[1:]
    command_name,sep,args = command.partition(" ")
    if command_name in self.commands:
      #Now we've verified, go ahead and run it
      try:
        cmd = self.commands[command_name].run(args)
        if type(cmd) == types.GeneratorType:
          for i in cmd:
            self.output([i, channel])
        else:
          self.output([cmd, channel])

      except ArgumentFormatError:
        self.output("Error running {} -- Argument format error".format(command_name))
      except TypeError:
        pass

    else:

      self.log.info("No command of name {} detected".format(command_name))
      self.output("Error running {} -- Command not found".format(command_name))
  def output(self, val):
    self.outputQ.put(val)
    if self.callback:
      self.callback(*val)

  def _checkAgainstTriggers(self, command):
    for i in self.triggers:
      if i.match(command[0]):
        self.output([i.send_text, command[1]])

  def getOutput(self):
    try:
      x = self.outputQ.get(False)
    except queue.Empty:
      return None
    return x

  def run(self):
    """Start the thread off"""
    self.log.info("Command processor thread starting...")
    while (not self.stopReq.isSet()) or self.cmdQ.qsize() != 0:
      if self.stopNOW.isSet():
        break
      try:
        toProcess = self.cmdQ.get(True, 0.5)
        self._process(toProcess)
      except queue.Empty:
        continue
      except Exception as e:
        self.log.error(e)
        traceback.format_exc(e)

    self.log.info("Stopping with qsize: {}".format(self.cmdQ.qsize()))
    self.log.info("Stopreq state: {}".format(self.stopReq.isSet()))
    self.log.info("Thread closed.")
        

  def push(self, commandstring, assoc_info = None):
    """Add a command to the command queue - to be processed commands
       ARGS: commandstring (str) - the command to process
             assoc_info (Any) - Things to be returned with the processed cmd"""
    self.log.info("Pushing command {}".format(commandstring))
    self.cmdQ.put([commandstring, assoc_info])
    for pipe in self.pipes:
      pipe.put([commandstring, assoc_info])
  
  def exit(self, now=False):
    """Quit the thread, cleanly exit"""
    admin = 1
    yield "Closing..."
    self.log.info("Exit request acknowledged, will exit.")
    self.stopReq.set()
    if (now):
      self.stopNOW.set()
    
  ##Module loading/unloading
  def loadModule(self, name):
    self.log.newline() 
    self.log.info("LOADING MODULE {}".format(name.upper())) 
    self.log.line()
    self.log.incIndent()
    try:
      ##Try loading the module as i
      yield("Importing {}...".format(name))
      i = importlib.import_module(name)
      ##In case it's changed and was imported before, reload it 
      self.log.debug("Reloading...")
      i = importlib.reload(i)
      ##Get a list of all the functions defined in the module
      self.log.debug("Getting functions...")
      funcs = dir(i)
      ##Don't import python's internal functions, like __name__ and __init__
      x = re.compile("__[a-z]*__")
      z = ([("i.{}".format(y)) for y in funcs if not (x.match(y) or y[-1]=="_")])
      self.log.debug("Loaded, adding functions...")
      self.log.incIndent()
      self.funcs = "Loaded functions:\n"
      ##Load the functions in
      for j in z:
        if type(eval(j)) == types.FunctionType:
          if "onimport" in j:
            self.log.info("Running import function...")
            eval(j)()
          elif "onexit" in j:
            atexit.register(eval(j))
          else:  
            self.addCommand(j.split(".")[1], eval(j), module=name)
            self.funcs += "!{}, ".format(j.split(".")[1])
      if name not in self.loadedModules:
        self.loadedModules.append(name)
    
      yield(self.funcs)
    except ImportError as ie:
      self.log.error("Could not find module {}".format(name))
      self.log.error(ie)
    except Exception as e:
      self.log.error("Unknown exception: {}".format(e)) 
    
  def unloadModule(self, module_name):
    yield "Unloading module {}".format(module_name)
    funcs = "( "
    for i in self.commands:
      if self.commands[i].module == module_name:
        self.removeCommand(i)
        funcs += i + ", "
    self.loadedModules.remove(module_name)
    self.log.info("Unloaded {} {} )".format(module_name, funcs))

  def lsmod(self):
    """List all currently loaded modules"""
    x = "Loaded modules: \n"
    x += "\n".join(self.loadedModules)
    return( x + "\n" )
  
  def getHelp(self, cmd=None):
    if cmd:
      if cmd in self.commands:
        return(self.commands[cmd].getHelp())
      else:
        return("Command {} does not exist".format(cmd))
    else:
      #Return list of commands
      return "Available Commands: "+", ".join(self.commands)
  def listTriggers(self):
    return "\n".join([str(x) for x in self.triggers])

  def loadService(self, srvname):
    self.services.append(
      Service( 
        name = srvname,
        function = function,
        autostart = True
      )
    )

  def startService(self, srvname):
    for i in self.services:
      if i.name == srvname:
        i.start()     
        return "Started" 
    return "Service not found"

  def killService(self, srvname):
    for i in self.services:
      if i.name == srvname:
        i.stop()
        self.services.remove(i)
        return "Killed"
    return "Service not found"

  
  def lsService(self):
    x = [i.name for i in self.services]
    return "\n".join(x)

  def _addUtilityCommands(self):
    self.addCommand("lsmod", self.lsmod)
    self.addCommand("import", self.loadModule)
    self.addCommand("quit", self.exit)
    self.addCommand("help", self.getHelp)
    self.addCommand("mktrig", self.addTrigger)
    self.addCommand("rmtrig", self.removeTrigger)
    self.addCommand("lstrig", self.listTriggers)
    self.addCommand("writeconf", self.writeConfig)
    self.addCommand("loadSrv", self.loadService)
    self.addCommand("startSrv", self.startService)
    self.addCommand("killSrv", self.killService)
    self.addCommand("lsSrv", self.lsService)
  def __init__(self, configfile = "command-proc.conf"):
    super(CommandProcessor, self).__init__()
    
    #Open a logger for superior feedback(tm)
    self.log = Log()
    
    #Alert the user that we're starting the processor
    self.log.info("Command Processor Created")
    self.log.newline()
    self.log.info("CMDPROC INIT")
    self.log.line()
    self.log.incIndent()

    #Set up some initial variables
    self.triggers = []
    self.services = []
    self.pipes = []
    self.commands = {}
    self.loadedModules = ["Builtin"]
    
    #Read in the config
    self.log.info("Reading config...")
    self.config = YamlConf(configfile)
    self.log.info("Setting config...")
   
    #Load in the config
    #The getValue() or "Value" means that we have a default
    #So if we can't get something from the config, it defaults to something 
    self.bot_name = self.config.getValue("bot", "name") or "Bot"
    self.bot_version = self.config.getValue("bot", "version") or "0.01"
    self.msg_prefix = self.config.getValue("bot", "msg_prefix") or "BOT: "
    self.command_prefix = self.config.getValue("bot", "cmd_prefix") or "!"
    debug = self.config.getValue("bot", "debug_logging") or False
    module_path = self.config.getValue("modules", "path") or "."

    #This means python will be able to find modules
    #When python looks for things, it goes down a so-called PYTHONPATH
    #We give it some new directories to look in
    self.module_path = module_path 
    sys.path.insert(0, module_path)
    initial_modules = self.config.getValue("modules", "load") or []
    inital_triggers = self.config.getValue("triggers") or []
    self.admins = self.config.getValue("admins")
    self.log.info("Read config.")

    #callback means that we run a function once we're done
    #processing something, so like we can go
      # output = process("!hello")
      # callback(output) 
    #By default it's just print, so we print the output
    self.callback = print

    #Set up the input and output queues
    self.log.info("Initilising command queue...")
    self.cmdQ = queue.Queue()
    self.log.info("Initilising output queue...")
    self.outputQ = queue.Queue()

    #Set up some stuff so we can tell the commandprocessor to stop
    #when we want to exit, we turn the Event on
    self.log.info("Initilising requests...")
    self.stopReq = threading.Event()
    self.stopNOW = threading.Event()

    #We have a few "initial modules", things to load on startup
    self.log.info("Setting up modules...")
    for i in initial_modules:
      self.loadModule(i)

    #Same goes for triggers
    self.log.info("Setting up triggers...")
    for i in inital_triggers:
      self.addTrigger(i, inital_triggers[i])

    #If the user wants more information than usual, they can set debug to True
    self.log.info("Setting verbosity...")
    if debug:
      self.log.setLevel(self.log.DEBUG)

    #For reference: an underscore before the function name means that it only has INTERNAL use,
    #i.e nobody outside this class should call _addUtilityCommands()
    self._addUtilityCommands()

    #Tell the user that we've finished setting everything up
    self.log.line()
    self.log.info("FINISHED CMDPROC INIT")   
    self.log.newline()
Esempio n. 30
0
class NGram: 
  """Class for an N-Gram model of a natural language corpus"""
  def __init__(self, corpus, n, debug=False, model=None):
    self.log = Log()
    
    if debug:
      self.log.setLevel(self.log.DEBUG)
    
    self.n = n
    self.log.info("Initialising {}-Gram model...".format(n))   
    
    if model:
      self.model = model
    else:
      if type(corpus) == type([]):
        self.buildModel(corpus)
      else:
        self.buildModel([corpus])
    self.log.info("{}-Gram model ready for use".format(self.n))

  def buildModel(self, list_corpus):
    """Build a model from a list of strings"""
    #Pad out the message
    corpus = "" 

    self.log.info("Creating N-Gram model from {} string{}".format(len(list_corpus),
                                                 "s" if len(list_corpus)>1 else ""))

    for i in list_corpus:
      #Remove punctuation
      i = i.replace(","," ").replace("."," ")

      corpus += " <s> "*(self.n-1) + i + " <s> "*(self.n-2)+" <end>"
    corpus = corpus.strip().lower()
    nlen = []
    self.log.info("Splitting corpus into {} length strings".format(self.n))
    corpus = [x for x in corpus.split(" ") if x != '']
    for i in range(len(corpus)-1):
      nlen.append(corpus[i:i+self.n])
    if len(nlen) > 6000:
      nlen = nlen[:6000]
    qqq = len(nlen)
    self.log.info("Processing {} {}-length strings".format(len(nlen), self.n))
    self.model = []   
    endWords = []
    givenWords = []
    for i in nlen:
      word = i[-1]
      given = i[:-1]
      if word not in endWords:
        endWords.append(word)
      if given not in givenWords:
        givenWords.append(given)
    
    self.log.info("Calculating probabilities...")
    #calculate probs
    percentages = range(10, 101, 10)
    for w in givenWords:
      p = givenWords.index(w) / qqq
      p = 100*p
      if p > percentages[0]:
        self.log.info("{}% done...".format(p))
        percentages = percentages[1:]
      occurances = [x for x in nlen if x[:-1] == w]
      for x in occurances:
        y = x[-1] ##endword
        endswith = [z for z in occurances if z[-1] == y]
        ##Count number of occurrences
        try:
          modelAdd = [x[-1], w, 1.0 / (1+len(occurances)-len(endswith))]
        except ZeroDivisionError:
          ##Prob must be 1
          modelAdd = [x[-1],w,1.0]
        self.model.append(modelAdd)

    self.log.info("{}-Gram model built!".format(self.n))

  def generate(self):
    """Generate a possible message from the model"""
    self.log.info("Generating a possible string...")
    try:
      m = "<s>"
      while m.split(" ")[-1] != "<end>":
        m += " " + random.choice(self.getAllFromGiven(m.split(" ")[-self.n+1:])) 
      self.log.info("Generated!")
      return m.replace("<s>","").replace("<end>","")
    except IndexError:
      return "Could not generate... not enough data!"
  def getAllFromGiven(self, given):
    """Get all instances of x, where (given, x) is a member of the model"""
    j = []
    for i in self.model:
      if i[1] == given:
        j.append(i[0])
    return j

  def getProb(self, word, given):
    """Get P(word|given)"""
    ##Find P(word | given)
    for i in self.model:
      g = listtostr_(i[1])
      if i[0] == word and given == g:
        return i[2]
    return 0
class Command:
  def __init__(self, f_name, f_obj, help, module = "Builtin"):
    self.log = Log()
    self.log.newline()
    self.log.info("Creating command {}".format(f_name))
    self.log.line("-")
    self.name = f_name
    self.func = f_obj
    self.help = self.func.__doc__ or ""
    self.module = module
    self.admin_required = "admin" in self.func.__code__.co_varnames
    self.nargs = self.func.__code__.co_argcount
    self.defaults = self.func.__defaults__
    self.argdefault = {}
    if (self.defaults):
      self.noptargs = len(self.defaults) 
    else:
      self.noptargs = 0
    self.args = self.func.__code__.co_varnames[:self.nargs - self.noptargs]
    self.optargs = self.func.__code__.co_varnames[self.nargs-self.noptargs:
                                                  self.noptargs+1]
    self.hints = typing.get_type_hints(self.func) 
    if "self" in self.args:
      self.nargs -= 1
    self.args = tuple([x for x in self.args if x != "self"])
    for i in range(self.noptargs):
      self.argdefault[self.optargs[i]] = self.defaults[i]

    if self.nargs > 0:
      self.log.info("ARGS: " + ", ".join(self.args))
      self.log.info("OPTARGS: " + ", ".join(self.optargs))
      self.log.info("DEFAULTS: " + ", ".join(
                            ["{}={}".format(
                      i, self.argdefault[i]) for i in self.argdefault]))      
    else:
      self.log.info("No arguments")
    self.delim = ","
    self.NOSPLIT = "NOSPLIT" in self.func.__code__.co_varnames

    self.success = True
    self.log.line("-")
    self.log.info(self)

  def getHelp(self):
    h =  self.name + ":\n" + self.help 
    if self.nargs > 0:
      h += "\nARGS: " + ", ".join(self.args) + "\n" 
    if self.noptargs > 0:
      h +=  "\nOPTARGS: " + " , ".join(self.optargs)
    if "\n" not in h:
      h += " (No Arguments)"
    return h 

  def run(self, args, user_is_admin=False):
    if self.admin_required and not user_is_admin:
      self.log.warning("{} requires administrative permissions".format(self.name))
    self.log.newline()
    self.log.newline()
    self.log.line("+")
    if not self.NOSPLIT:
      args = self._formatArgs(args.split(self.delim))
    else:
      args = self._formatArgs([args])
    self.log.info("Running {} with args {}".format(self.name, args))
    output = self.func(**args)
    self.log.line("+")
    self.log.newline()
    self.log.newline()
    return output
  
  def _formatArgs(self, args):
    args = [x.strip() for x in args if x != '']
    processedArgs = {}
    allargs = self.args + self.optargs
    for i in range(self.nargs):
      arg = ""
      argn = allargs[i]
      if i >= len(args):
        arg = self.argdefault[argn]
      else:
        arg = args[i]
      if allargs[i] in self.hints:
        try:
          arg = self.hints[argn](arg)
        except ValueError as ex:
          raise ArgumentFormatError(ex)
      processedArgs[argn] = arg
    
    return processedArgs

  def __repr__(self):
    x = "\n\nCOMMAND DEFINITION ::- \n"
    return x+"\nCommand (\n Name: {}.{},\n Args: {},\n OptArgs: {}\n Admin: {}\n)\n".format(
            self.module, self.name, self.args, self.optargs, self.admin_required)
Esempio n. 32
0
__author__ = "Hannah Ward"


##############
#games.ai    #
#Parser for  #
#Phaser.io AI#
##############


import json
import argparse
import re
from floatingutils.log import Log

log = Log()

log.debug("Initialising Parser...")
parser = argparse.ArgumentParser(description='Parse a .ai file into JSON')
parser.add_argument("filename", help="The .ai file to process")
parser.add_argument('--game', default="game",
                   help='The name of your \'game\' instance - usually just game')

parser.add_argument('--obj', help="The game of your game object that the AI will apply to")
parser.add_argument("--varname", help="The variable name to be output", default="ai")
parser.add_argument("--out", default="ai.out", help="The output filename")
log.debug("Parser ready")

args = parser.parse_args()

log.info("Processing {}".format(args.filename))
Esempio n. 33
0
#!/usr/bin/env python3

from floatingutils.reddit import Reddit
from floatingutils.conf import YamlConf
from floatingutils.log import Log
import webbrowser
import pickle
import time

l = Log()

r = Reddit()

l.info("Logging in...")

config = YamlConf("reddit.login")


username = config.getValue("reddit", "username")
cli_id = "CzlpOR3KW0oNBg"
headless = config.getValue("headless")

api_key  = config.getValue("reddit", "api")

l.info("Using {}".format(username))

r.api.set_oauth_app_info(client_id = cli_id, client_secret = api_key, 
                         redirect_uri="http://localhost/reddit_auth")

url = r.api.get_authorize_url("uniqueKey", "identity submit read", True)