class Bot(gobject.GObject): """""" # custom properties __gproperties__ = { 'apiAccessible' : (gobject.TYPE_BOOLEAN, 'api accessible', 'is api accessible', False, gobject.PARAM_READWRITE), 'isRunning' : (gobject.TYPE_BOOLEAN, 'is running', 'is running', False, gobject.PARAM_READWRITE) } CHANNEL_TELL = 0 CHANNEL_ORG = 1 CHANNEL_PRIVATE = 2 def __init__(self, name, settingModel): """Constructor method.""" self.__gobject_init__() self.name = name self.settingModel = settingModel self.api = budapi.Budapi() self.process = Process() self.consoleModel = gtk.TextBuffer() self.configFile = None self.noRestart = False self.set_property('apiAccessible', False) self.process.connect('stdout_received', self.onBotStdoutReceived) self.process.connect('stderr_received', self.onBotStderrReceived) self.process.connect('stopped', self.onBotDied) tagTable = self.consoleModel.get_tag_table() def addTag(buffer, name, foreground, weight = None): """Adds a text tag to buffer with given name and styles.""" tag = gtk.TextTag(name) tag.set_property('foreground', foreground) if weight != None: tag.set_property('weight', weight) buffer.get_tag_table().add(tag) addTag(self.consoleModel, 'error', foreground = 'red', weight = pango.WEIGHT_BOLD) addTag(self.consoleModel, 'response', foreground = 'lightblue') def do_get_property(self, property): """Returns value of given property. This is required to make GTK's properties to work. See: http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm#d0e127 """ if property.name == 'apiAccessible': return self.apiAccessible elif property.name == 'isRunning': return self.process.isRunning() else: raise AttributeError, 'unknown property %s' % property.name def do_set_property(self, property, value): """Sets value of given property. This is required to make GTK's properties to work. See: http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm#d0e127 """ if property.name == 'apiAccessible': self.apiAccessible = value else: raise AttributeError, 'unknown property %s' % property.name def getName(self): """Returns name of the bot.""" return self.name def getConsoleModel(self): """Returns console model""" return self.consoleModel def start(self): """Starts the bot.""" # do nothing if bot process is still running. if self.process.isRunning(): return configPath = self.settingModel.getValue(self.name, 'configfile') self.configFile = BotPhpConfigFile(configPath) self.configFile.load() port = self.configFile.getVar('API Port') # make sure that port is within defined range lowPort = self.settingModel.getApiPortRangeLow() highPort = self.settingModel.getApiPortRangeHigh() if port < lowPort or port > highPort: port = lowPort self.configFile.setVar('API Port', port) self.configFile.save() # find a free port if currently set port is not free if self.isPortFree(port) == False: for port in range(lowPort, highPort + 1): if self.isPortFree(port): self.configFile.setVar('API Port', port) self.configFile.save() break self.noRestart = False self.process.setConfigFilePath(configPath) self.process.setWorkingDirectoryPath(self.settingModel.getValue(self.name, 'installdir')) self.process.start() self.notify('isRunning') self.pollApi() def isPortFree(self, port): """Returns True if given TCP/IP port is free.""" s = None try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('0.0.0.0', port)) return True except socket.error, e: try: s.close() except: pass return False