def addHostClicked(self, hostn): try: ip = socket.gethostbyname(hostn.strip()) get_server().call_request_info([ip]) except: d = QMessageBox(QMessageBox.Critical, "Error adding host", "Cannot add host: Hostname unknown: %s" % hostn, QMessageBox.Ok, self.mainWindow) d.exec_()
def __init__(self): cmd.Cmd.__init__(self) LunchServerController.__init__(self) self.logger = newLogger("cli") self.prompt = "> " self.commands = set(["exit"]) self.addModule(CLIMessageHandling()) self.addModule(CLIOptionHandling()) self.addModule(CLIPluginHandling(self)) self.addModule(CLIPrivacyHandling()) self.addModule(CLILoggingHandling()) get_server().initialize(self) if get_settings().get_plugins_enabled(): for pluginInfo in get_plugin_manager().getAllPlugins(): if pluginInfo.plugin_object.is_activated: self.addModule(pluginInfo.plugin_object) get_notification_center().connectApplicationUpdate(self.notifyUpdates) self.exitCode = 0 # if serverStopped is called, we can determine if it was a regular exit. self.cleanExit = False self.initialized = False
def restartWithCommands(commands, logger): """ Restart Lunchinator and execute commands in background while it is stopped. commands: lunchinator.commands.Commands instance """ from lunchinator import get_server try: # copy restart script to safe place shutil.copy(get_settings().get_resource("bin", "restart.py"), get_settings().get_main_config_dir()) startCmd = _getStartCommand(logger) args = [_getPythonInterpreter(), get_settings().get_config("restart.py"), "--lunchinator-path", get_settings().get_main_package_path(), "--start-cmd", json.dumps(startCmd), "--pid", str(os.getpid())] if commands != None: args.extend(["--commands", commands.toString()]) spawnProcess(args, logger) except: logger.exception("Error in restartWithCommands") return if get_server().getController() != None: get_server().getController().shutdown() else: sys.exit(0)
def performAction(self, peerID, peerInfo, parent): from PyQt4.QtGui import QFileDialog fname = QFileDialog.getOpenFileName(parent, 'Pipe file') with open(fname, 'r') as f: data = f.read() get_server().call("HELO_PIPE "+data, peerIDs=[peerID])
def announce_pic(self,account_name,url_text_tuple, peerIDs = []): if len(url_text_tuple[0]): with contextlib.closing(StringIO()) as strOut: writer = csv.writer(strOut, delimiter = ' ', quotechar = '"') writer.writerow([url_text_tuple[0].encode("utf-8"), url_text_tuple[1].encode("utf-8"), account_name]) get_server().call('HELO_REMOTE_PIC %s' % strOut.getvalue(), peerIDs)
def _find_remote_calls(self): import twitter get_server().call("HELO_TWITTER_REMOTE %s"%self._own_screen_name) with self._lock: try: if 0 == self._mentions_since_id: #determine the start ments = self._twitter_api.GetMentions(count=1) if len(ments): self._mentions_since_id = ments[0].GetId() else: self._mentions_since_id = 1 self.logger.debug("Twitter: Starting with mentions ID %s", self._mentions_since_id) return ments = self._twitter_api.GetMentions(since_id=self._mentions_since_id) if 0==len(ments): self.logger.debug("Twitter: Nobody mentioned me since %s", self._mentions_since_id) return self._mentions_since_id = ments[0].GetId() for m in ments: self.logger.debug("Twitter: I was mentioned: %s %s", m.GetUser(), m.GetText()) s_name = m.GetUser().GetScreenName() if s_name not in self._remote_callers: self.logger.debug("Twitter: I do not know him") # self._twitter_api.PostUpdate(u"@"+s_name+u" Sorry, I do not know you", m.GetId()) continue get_server().call("Remote call by @%s: %s"%(s_name,m.GetText())) self._twitter_api.PostUpdate(u"@"+s_name+u" OK, I forwarded your message", m.GetId()) except twitter.TwitterError as t: if t[0][0][u'code']==88: raise else: self.logger.error("Twitter: Error while trying to retrieve mentions %s", str(t))
def sendMessage(self, otherID, msgHTML, msgID=None, msgTime=None, isNoResend=False): otherID = convert_string(otherID) msgHTML = convert_string(msgHTML) if msgID == None: msgID = self._getNextMessageID() isResend = False else: isResend = True if isNoResend: isResend = False if msgTime == None: msgTime = time() msgDict = {u"id": msgID, u"format": u"html", u"data": msgHTML, u"time": msgTime} try: msgDictJSON = json.dumps(msgDict) except: self.logger.exception("Error serializing private message: %s", msgDict) return get_server().call("HELO_PM " + msgDictJSON, peerIDs=[otherID]) self._waitingForAck[msgID] = (otherID, time() if isResend else msgTime, msgHTML, isResend)
def run(self): try: get_server().start_server() except: from lunchinator.log import getCoreLogger getCoreLogger().exception("Exception in Lunch Server") get_server().running = False
def __init__(self): QObject.__init__(self) LunchServerController.__init__(self) getCoreLogger().info("Your PyQt version is %s, based on Qt %s", QtCore.PYQT_VERSION_STR, QtCore.QT_VERSION_STR) self._shuttingDown = False self.resetNextLunchTimeTimer = None self._updateAvailable = False self._repoUpdates = 0 self._installUpdatesAction = None self._appUpdateStatusAction = None self._repoUpdateStatusAction = None self._restartAction = None self._restartStatusAction = None self._restartReason = u"" self._highlightNewMessage = False self._highlightPeersReady = False self.exitCode = 0 self.serverThread = None self.running = True get_server().initialize(self) self.pluginNameToMenuAction = {} # initialize main window self.mainWindow = LunchinatorWindow(self) self.settingsWindow = None self.errorDialog = ErrorLogDialog(self.mainWindow) self.setParent(self.mainWindow) if not self.createTrayIcon(): return self.mainWindow.createMenuBar(self.pluginActions) # connect private signals self._initDone.connect(self.initDoneSlot) self._performCall.connect(self.performCallSlot) self._receiveFile.connect(self.receiveFileSlot) self._sendFile.connect(self.sendFileSlot) self._processEvent.connect(self.processEventSlot) self._processMessage.connect(self.processMessageSlot) self._updateRequested.connect(self.updateRequested) self._openWindow.connect(self.openWindowClicked) get_notification_center().connectApplicationUpdate(self._appUpdateAvailable) get_notification_center().connectOutdatedRepositoriesChanged(self._outdatedReposChanged) get_notification_center().connectUpdatesDisabled(self._updatesDisabled) get_notification_center().connectMessagePrepended(self._newMessage) get_notification_center().connectRestartRequired(self._restartRequired) get_notification_center().connectPluginActivated(self._pluginActivated) get_notification_center().connectPluginDeactivated(self._pluginDeactivated) self.serverThread = LunchServerThread(self) self.serverThread.finished.connect(self.serverFinishedUnexpectedly) self.serverThread.finished.connect(self.serverThread.deleteLater) self.serverThread.start()
def changeNextLunchTime(self, begin = None, end = None): if begin == None: if self.mainWindow == None: getCoreLogger().error("mainWindow is not initialized") return from lunchinator.timespan_input_dialog import TimespanInputDialog dialog = TimespanInputDialog(self.mainWindow, "Change Lunch Time", "When are you free for lunch today?", get_settings().get_next_lunch_begin(), get_settings().get_next_lunch_end()) dialog.exec_() if dialog.result() == QDialog.Accepted: get_settings().set_next_lunch_time(dialog.getBeginTimeString(), dialog.getEndTimeString()) else: return else: get_settings().set_next_lunch_time(begin, end) if self.resetNextLunchTimeTimer != None: self.resetNextLunchTimeTimer.stop() self.resetNextLunchTimeTimer.deleteLater() td = get_settings().get_next_lunch_reset_time() if td > 0: self.resetNextLunchTimeTimer = QTimer(getValidQtParent()) self.resetNextLunchTimeTimer.timeout.connect(self._resetNextLunchTime) self.resetNextLunchTimeTimer.setSingleShot(True) self.resetNextLunchTimeTimer.start(abs(td) + 1000) get_server().call_info()
def getValidQtParent(): from lunchinator import get_server from PyQt4.QtCore import QObject if isinstance(get_server().controller, QObject): return get_server().controller elif isinstance(qtParent, QObject): return qtParent raise Exception("Could not find a valid QObject instance")
def set_group(self, value, init=False): from lunchinator import get_server oldGroup = self._group self._group = value if not init: getCoreLogger().info("Changing Group: '%s' -> '%s'", oldGroup, self._group) get_server().changeGroup(unicode(value)) get_notification_center().emitGroupChanged(oldGroup, self._group)
def _checkSendInfoDict(self, pluginName, category): pluginName = convert_string(pluginName) category = convert_string(category) pi = get_plugin_manager().getPluginByName(pluginName, category) if pi != None: po = pi.plugin_object if po.extendsInfoDict(): get_server().call_info()
def activate(self): iface_called_plugin.activate(self) '''do something when the user activates the plugin''' '''to send a message''' get_server().call_all_members("this is a message sent by the example plugin") '''to send an event''' get_server().call_all_members("HELO_EXAMPLE an event of typ HELO_EXAMPLE")
def create_widget(self, parent): from rot13.rot13box import rot13box w = rot13box(parent) with get_server().get_messages(): if len(get_server().get_messages()) > 0: w.encodeText(get_server().get_messages().getLatest()[2]) return w
def callForLunch(self): optmsg = "" if self.sendMessageField != None: optmsg = convert_string(self.sendMessageField.text()) self.sendMessageField.clear() if len(optmsg) > 0: get_server().call_all_members(optmsg) else: get_server().call_all_members(get_settings().get_lunch_trigger())
def displayNotification(name, msg, logger, icon=None): if msg == None: msg = u"" myPlatform = getPlatform() try: from lunchinator import get_server if not lunchinator_has_gui(): print time.strftime("%Y-%m-%d %H:%M"),name, msg except: print time.strftime("%Y-%m-%d %H:%M"),name, msg try: if myPlatform == PLATFORM_LINUX: fileToClose = None if icon is None or not os.path.exists(icon): icon = "" elif _mustScaleNotificationIcon(): import Image im = Image.open(icon) im.thumbnail((64,64), Image.ANTIALIAS) fileToClose = NamedTemporaryFile(suffix='.png', delete=True) im.save(fileToClose, "PNG") fileToClose.flush() icon = fileToClose.name subprocess.call(["notify-send","--icon="+icon, name, msg]) if fileToClose is not None: fileToClose.close() elif myPlatform == PLATFORM_MAC: fh = open(os.path.devnull,"w") exe = getBinary("terminal-notifier", os.path.join("bin", "terminal-notifier.app", "Contents", "MacOS")) if not exe: logger.warning("terminal-notifier not found.") return call = [exe, "-title", "Lunchinator: %s" % name, "-message", msg] if False and checkBundleIdentifier(_LUNCHINATOR_BUNDLE_IDENTIFIER): # no sender until code signing is fixed (probably never) call.extend(["-sender", _LUNCHINATOR_BUNDLE_IDENTIFIER]) logger.debug(call) try: subprocess.call(call, stdout=fh, stderr=fh) except OSError as e: if e.errno == errno.EINVAL: logger.warning("Ignoring invalid value on Mac") else: raise except: logger.exception("Error calling %s", call) elif myPlatform == PLATFORM_WINDOWS: from lunchinator import get_server if hasattr(get_server().controller, "statusicon"): get_server().controller.statusicon.showMessage(name,msg) except: logger.exception("error displaying notification")
def request_log(self, member=None, logNum=0): if member == None: member = self.get_selected_log_member() if member != None: self.logger.debug("Requesting log %d from %s", logNum, member) get_server().call( "HELO_REQUEST_LOGFILE %s %d" % (DataReceiverThread.getOpenPort(category="log%s" % member), logNum), set([member]), ) else: self.log_area.setText("No Member selected!")
def do_call(self, args): """ Call for lunch. Usage: call - Call all members call <member1> [<member2> [...]] - Call specific members """ args = args.decode('utf-8') args = self.getArguments(args) try: get_server().call("lunch", peerIPs=self.getHostList(args)) except: getCoreLogger().exception("Error calling")
def stopWithCommands(args, logger): """ Stops Lunchinator and execute commands """ from lunchinator import get_server try: spawnProcess(args, logger) except: logger.exception("Error in stopWithCommands") return if get_server().getController() != None: get_server().getController().shutdown()
def sendRemotePicture(self, peerID, peerInfo, parent): from remote_pictures.remote_pictures_dialog import RemotePicturesDialog dialog = RemotePicturesDialog(parent, peerID, peerInfo) result = dialog.exec_() if result == RemotePicturesDialog.Accepted: data = [dialog.getURL().encode('utf-8')] if dialog.getDescription(): data.append(dialog.getDescription().encode('utf-8')) if dialog.getCategory(): data.append(dialog.getCategory().encode('utf-8')) with contextlib.closing(StringIO()) as strOut: writer = csv.writer(strOut, delimiter = ' ', quotechar = '"') writer.writerow(data) get_server().call("HELO_REMOTE_PIC " + strOut.getvalue(), peerIDs=[peerID])
def parse_json(self, http_result): if not http_result: return False j = json.loads(http_result) oldurl = self.pic_url self.pic_url = j['response']['posts'][0]['photos'][0]['original_size']['url'] if oldurl != self.pic_url: self.logger.info("TDT: New picture! Yeay!") get_server().call("HELO_TDTNOTIFY_NEW_PIC " + self.pic_url) with contextlib.closing(StringIO()) as strOut: writer = csv.writer(strOut, delimiter=' ', quotechar='"') writer.writerow([self.pic_url, "new picture from %s" % time.strftime("%b %d %Y %H:%M"), "TDT"]) get_server().call('HELO_REMOTE_PIC %s' % strOut.getvalue())
def settingsDialogAction(self, saved): if not get_settings().get_plugins_enabled(): return for pluginInfo in get_plugin_manager().getAllPlugins(): if pluginInfo.plugin_object.is_activated and self.settingsWindow.isOptionsWidgetLoaded(pluginInfo.name): if saved: try: pluginInfo.plugin_object.save_options_widget_data(sendInfoDict=False) except: getCoreLogger().exception("was not able to save data for plugin %s", pluginInfo.name) else: pluginInfo.plugin_object.discard_changes() get_settings().write_config_to_hd() get_server().call_info()
def restart(logger): """Restarts the Lunchinator""" try: #on Windows with pyinstaller we use this special handling for now if getPlatform()==PLATFORM_WINDOWS: frozen = getattr(sys, 'frozen', '') if frozen: logger.debug("Trying to spawn %s", sys.executable) from lunchinator import get_server get_server().stop_server() subprocess.Popen(sys.executable, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP, close_fds=True) restartWithCommands(None, logger) except: logger.exception("Error restarting")
def process_event(self, cmd, value, ip, member_info, _prep): if len(value)==0: return if cmd == "HELO_TWITTER_USER": screen_name = value[1:] if value[0] == "@" else value if not self.other_twitter_users.has_key(ip) or self.other_twitter_users[ip] != screen_name: self.other_twitter_users[ip] = screen_name elif cmd == "HELO_TWITTER_REMOTE": screen_name = value[1:] if value[0] == "@" else value self.remote_account = screen_name self.remote_member = member_info['name'] if member_info and member_info.has_key("name") else ip get_server().call("HELO_TWITTER_USER %s" % self.options["twitter_account"]) self.set_widget_message()
def updateMsgMenu(self): self.msgMenu.clear() messages = get_server().get_messages() with messages: for i in xrange(len(messages) - 1, len(messages) - 1 - min(10, len(messages)), -1): message = messages[i] self.msgMenu.addAction(message[2], partial(self.encodeText, message[2]))
def sendMessage(msg, cli): if msg == None: msg = "lunch" get_settings().set_plugins_enabled(False) recv_nr = get_server().perform_call(msg, peerIDs=[], peerIPs=[cli]) print "sent to", recv_nr, "clients"
def do_send(self, args): """ Send a message. Usage: send <message> - Send message to all members send <message> <member1> [<member2> [...]] - Send message to specific members """ if len(args) == 0: self.printHelp("send") return False args = self.getArguments(args) message = args.pop(0) try: get_server().call(message, peerIPs=self.getHostList(args)) except: getCoreLogger().exception("Error sending")
def statsDB(self): stats = get_server().getDBConnection() if stats == None and not self.statDBErrorLogged: self.statDBErrorLogged = True log_error( "Lunch Statistics Plugin: No database connection available.") return stats
def _transferCanceled(self, thread): peerID, transferID = thread.getUserData() sendCancel = False isUpload = False if type(thread) is DataSenderThread: if transferID in self._outgoing: del self._outgoing[transferID] sendCancel = True isUpload = True else: if (peerID, transferID) in self._incoming: del self._incoming[(peerID, transferID)] sendCancel = True if sendCancel: cancelDict = {u"id" : transferID, u"up" : isUpload} get_server().call("HELO_FT_CANCEL %s" % json.dumps(cancelDict), peerIDs=[peerID])
def quit(self, exitCode=0): if self.mainWindow is not None: self.mainWindow.close() if self.settingsWindow is not None: self.settingsWindow.close() if self.serverThread != None and not sip.isdeleted(self.serverThread) and self.serverThread.isRunning(): self.serverThread.finished.disconnect(self.serverFinishedUnexpectedly) get_server().stop_server() getCoreLogger().info("Waiting maximal 30s for server to stop...") # wait maximal 30s if self.serverThread.wait(30000): getCoreLogger().info("server stopped") else: getCoreLogger().warning("server not stopped properly") else: getCoreLogger().info("server not running") if self.running: if get_settings().get_plugins_enabled(): get_plugin_manager().deactivatePlugins(get_plugin_manager().getAllPlugins(), save_state=False) getCoreLogger().info("all plug-ins deactivated") if self.mainWindow is not None: self.mainWindow.finish() if self.settingsWindow is not None: self.settingsWindow.finish() self.running = False finalExitCode = 0 if exitCode != 0: finalExitCode = exitCode elif self.exitCode != 0: finalExitCode = self.exitCode else: finalExitCode = get_server().exitCode get_settings().write_config_to_hd() DataReceiverThread.cleanup() self.exitCode = finalExitCode self._coldShutdown(finalExitCode) return finalExitCode
def take_picture(self): import time import picamera filename = "raspicam.png" with picamera.PiCamera() as camera: camera.resolution = (1024, 768) camera.start_preview() # Camera warm-up time time.sleep(2) camera.capture(os.path.join(self.options["picture_path"], filename)) self.logger.debug("Picture taken with camera") if self.options["http_server"]: with contextlib.closing(StringIO()) as strOut: writer = csv.writer(strOut, delimiter=' ', quotechar='"') #add the time to the URL to make remote picture aware of this being a new picture but still overwrite the old one pic_url = "http://%s:%d/%s?time=%d" % (self.options["http_hostname"], self.options["http_port"], filename, int(time.time())) writer.writerow([pic_url, "Picamera picture taken at %s" % time.strftime("%b %d %Y %H:%M"), "raspicam"]) get_server().call('HELO_REMOTE_PIC %s' % strOut.getvalue())
def send_command(self, cmd, peerID=None): if peerID: get_server().call("HELO_USBROCKET %s" % cmd, peerIDs=[peerID]) else: get_server().call("HELO_USBROCKET %s" % cmd)
class panic_button_listener(Thread): idVendor = None idProduct = None running = True msg = "lunch panic" def __init__(self, idV, idP, msg): super(panic_button_listener, self).__init__() self.idVendor = idV self.idProduct = idP self.msg = msg def findButton(self): for bus in usb.busses(): for dev in bus.devices: if dev.idVendor == self.idVendor and dev.idProduct == self.idProduct: return dev return None def run(self): dev = self.findButton() if dev == None: log_error("Cannot find panic button device") return handle = dev.open() interface = dev.configurations[0].interfaces[0][0] endpoint = interface.endpoints[0] try: handle.detachKernelDriver(interface) except Exception, _: # It may already be unloaded. pass handle.claimInterface(interface) unbuffer = False while self.running: # USB setup packet. I think it's a USB HID SET_REPORT. result = handle.controlMsg( requestType=0x21, # OUT | CLASS | INTERFACE request=0x09, # SET_REPORT value=0x0200, # report type: OUTPUT buffer="\x00\x00\x00\x00\x00\x00\x00\x02") try: result = handle.interruptRead(endpoint.address, endpoint.maxPacketSize) if 22 == result[0]: if not unbuffer: log_info("pressed the Panic Button") get_server().call_all_members(self.msg) unbuffer = True else: unbuffer = False #print [hex(x) for x in result] except Exception, _: # Sometimes this fails. Unsure why. pass time.sleep(endpoint.interval / float(1000))