def checkenv(): # Require Python 2.7 try: assert sys.version_info[:2] == (2, 7), '.'.join( map(str, sys.version_info[:3]) ) except AssertionError as e: return _("""You're using an unsupported version of Python (%s). You should install Python 2.7.X.""") % (e) # Require GTK+ 2.24 try: import gtk except Exception as e: return _("Cannot find GTK+ 2.24.X, please install it.") else: try: assert gtk.gtk_version[:2] == (2, 24), '.'.join( map(str, gtk.gtk_version[:3]) ) except AssertionError as e: return _("""You're using an unsupported version of GTK (%s). You should install GTK 2.24.X.""") % (e) # Require PyGTK 2.24 try: import pygtk except Exception as e: return _("Cannot find PyGTK 2.24.X, please install it.") else: try: assert gtk.pygtk_version[:2] == (2, 24), '.'.join( map(str, gtk.pygtk_version[:3]) ) except AssertionError as e: return _("""You're using an unsupported version of PyGTK (%s). You should install PyGTK 2.24.X.""") % (e) # On windows dbhash might be a good choice if win32: try: import dbhash except: log.add( _("Warning: the Berkeley DB module, dbhash, " + "could not be loaded.")) # Require pynicotine try: import pynicotine except ImportError, e: return _("""Can not find Nicotine+ modules. Perhaps they're installed in a directory which is not in an interpreter's module search path. (there could be a version mismatch between what version of python was used to build the Nicotine binary package and what you try to run Nicotine+ with).""")
def threadAlias(self, alias): text = expand_alias(self.frame.np.config.aliases, alias) if not text: log.add(_('Alias "%s" returned nothing') % alias) return if text[:2] == "//": text = text[1:] self.frame.np.queue.put(slskmessages.MessageUser(self.user, ToBeEncoded(self.frame.AutoReplace(text), self.encoding)))
def OnSavePicture(self, widget): if self.image is None or self.image_pixbuf is None: return #pixbuf = self.image.get_pixbuf() filename = "%s %s.jpg" % (self.user, time.strftime("%Y-%m-%d %H:%M:%S")) pathname = os.path.join(self.frame.np.config.sections["transfers"]["downloaddir"], CleanFile(filename)) if not os.path.exists(pathname): self.image_pixbuf.save(pathname, "jpeg", {"quality": "100"}) log.add(_("Picture saved to %s") % pathname) else: log.add(_("Picture not saved, %s already exists.") % pathname)
def parse_config(self): """ Parses the config file """ try: with open(self.filename, 'a+', encoding="utf-8") as f: f.seek(0) self.parser.read_file(f) except configparser.ParsingError: # Ignore parsing errors, the offending lines are removed later pass except Exception as e: # Miscellaneous failure, default config will be used log.add(_("Unable to parse config file: %s"), e)
def on_download_directory_recursive_to(self, widget): folder = choose_dir( self.frame.MainWindow, self.frame.np.config.sections["transfers"]["downloaddir"], multichoice=False) if folder is None: return try: self.download_directory(self.selected_folder, os.path.join(folder[0], ""), 1) except IOError: # failed to open log.add('Failed to open %r for reading', folder[0]) # notify user
def get_file_info(cls, name, pathname, tinytag, queue=None, file=None): """ Get file metadata """ try: audio = None bitrateinfo = None duration = None if file: # Faster way if we use scandir size = file.stat().st_size else: size = os.stat(pathname).st_size """ We skip metadata scanning of files without meaningful content """ if size > 128: try: audio = tinytag.get(pathname, size, tags=False) except Exception as errtuple: error = _( "Error while scanning metadata for file %(path)s: %(error)s" ) args = {'path': pathname, 'error': errtuple} if queue: queue.put((0, error, args)) else: log.add(error, args) if audio is not None: if audio.bitrate is not None: bitrateinfo = ( int(audio.bitrate), int(False) ) # Second argument used to be VBR (variable bitrate) if audio.duration is not None: duration = int(audio.duration) return (name, size, bitrateinfo, duration) except Exception as errtuple: error = _("Error while scanning file %(path)s: %(error)s") args = {'path': pathname, 'error': errtuple} if queue: queue.put((0, error, args)) else: log.add(error, args)
def processQueue(self): while len(self.guiqueue) > 0: i = self.guiqueue.pop(0) if i['type'] == 'logtext': log.add(i['text']) elif i['type'] == 'sayprivate': # If we use the np the chat lines only show up on the receiving end, we won't see anything ourselves. self.frame.privatechats.users[i['user']].SendMessage(i['text']) elif i['type'] == 'sendprivate': self.frame.privatechats.SendMessage(i['user'], i['text']) else: log.add(_('Unknown queue item %(type)s: %(item)s' % { 'type': i['type'], 'item': repr(i) })) return False
def on_soul_seek_uri(url): import urllib.parse try: user, file = urllib.parse.unquote(url[7:]).split("/", 1) if file[-1] == "/": NICOTINE.np.send_message_to_peer( user, slskmessages.FolderContentsRequest( None, file[:-1].replace("/", "\\"))) else: NICOTINE.np.transfers.get_file(user, file.replace("/", "\\"), "") except Exception: log.add(_("Invalid SoulSeek meta-url: %s"), url)
def on_soul_seek_uri(url): import urllib.parse try: user, file = urllib.parse.unquote(url[7:]).split("/", 1) if file[-1] == "/": NICOTINE.np.transfers.get_folder(user, file[:-1].replace("/", "\\")) else: NICOTINE.np.transfers.get_file(user, file.replace("/", "\\"), "") NICOTINE.change_main_page("downloads") except Exception: log.add(_("Invalid SoulSeek meta-url: %s"), url)
def OnSavePicture(self, widget): if self.image is None or self.image_pixbuf is None: return filename = "%s %s.jpg" % (self.user, time.strftime("%Y-%m-%d %H:%M:%S")) pathname = os.path.join( self.frame.np.config.sections["transfers"]["downloaddir"], CleanFile(filename)) if not os.path.exists(pathname): self.image_pixbuf.save(pathname, "jpeg", {"quality": "100"}) log.add(_("Picture saved to %s") % pathname) else: log.add(_("Picture not saved, %s already exists.") % pathname)
def enable_plugin(self, pluginname): if pluginname in self.enabled_plugins: return try: plugin = self.load_plugin(pluginname) if not plugin: raise Exception("Error loading plugin '%s'" % pluginname) plugin.enable(self) self.enabled_plugins[pluginname] = plugin log.add(_("Enabled plugin %s") % plugin.PLUGIN.__name__) except Exception: print_exc() log.addwarning(_("Unable to enable plugin %s") % pluginname) # common.log_exception(logger) return False return True
def _trigger_command(self, command, source, args, public_command): for module, plugin in self.enabled_plugins.items(): try: if plugin.PLUGIN is None: continue if public_command: return_value = plugin.PLUGIN.PublicCommandEvent( command, source, args) else: return_value = plugin.PLUGIN.PrivateCommandEvent( command, source, args) if return_value is None: # Nothing changed, continue to the next plugin continue if return_value == returncode['zap']: return True elif return_value == returncode['pass']: continue log.add( _("Plugin %(module)s returned something weird, '%(value)s', ignoring" ), { 'module': module, 'value': str(return_value) }) except Exception: from traceback import extract_stack from traceback import extract_tb from traceback import format_list log.add( _("Plugin %(module)s failed with error %(errortype)s: %(error)s.\nTrace: %(trace)s\nProblem area:%(area)s" ), { 'module': module, 'errortype': sys.exc_info()[0], 'error': sys.exc_info()[1], 'trace': ''.join(format_list(extract_stack())), 'area': ''.join( format_list(extract_tb(sys.exc_info()[2]))) }) return False
def disable_plugin(self, plugin_name): if plugin_name not in self.enabled_plugins: return False plugin = self.enabled_plugins[plugin_name] path = self.findplugin(plugin_name) try: plugin.disable() for trigger, _func in plugin.__publiccommands__: self.core.chatrooms.CMDS.remove('/' + trigger + ' ') for trigger, _func in plugin.__privatecommands__: self.core.privatechats.CMDS.remove('/' + trigger + ' ') self.update_completions(plugin) plugin.unloaded_notification() log.add(_("Unloaded plugin %s"), plugin.human_name) except Exception: from traceback import format_exc log.add(_("Unable to unload plugin %(module)s\n%(exc_trace)s"), { 'module': plugin_name, 'exc_trace': format_exc() }) return False finally: # Remove references to relative modules if path in sys.path: sys.path.remove(path) for name, module in list(sys.modules.items()): try: if module.__file__.startswith(path): sys.modules.pop(name, None) del module except AttributeError: # Builtin module continue del self.enabled_plugins[plugin_name] del plugin return True
def set_directory(self, directory): self.selected_folder = directory self.file_store.clear() self.files.clear() found_dir = False for d, f in self.shares: if d == directory: found_dir = True files = f break if not found_dir: return for file in files: # Filename, HSize, Bitrate, HLength, Size, Length, RawFilename rl = 0 try: size = int(file[2]) # Some clients send incorrect file sizes if size < 0 or size > maxsize: size = 0 except ValueError: size = 0 f = [file[1], human_size(size)] h_bitrate, bitrate, h_length = get_result_bitrate_length( size, file[4]) f += [h_bitrate, h_length] f += [int(size), rl, file[1]] try: self.files[f[0]] = self.file_store.append(f) except Exception as msg: log.add( _("Error while attempting to display folder '%(folder)s', reported error: %(error)s" ), { 'folder': directory, 'error': msg })
def trigger_event(self, function, args): """Triggers an event for the plugins. Since events and notifications are precisely the same except for how n+ responds to them, both can be triggered by this function.""" hotpotato = args for module, plugin in self.enabled_plugins.items(): try: ret = getattr(plugin.PLUGIN, function)(*hotpotato) if ret is not None and not isinstance(ret, tuple): if ret == returncode['zap']: return None elif ret == returncode['break']: return hotpotato elif ret == returncode['pass']: pass else: log.add( _("Plugin %(module)s returned something weird, '%(value)s', ignoring" ), { 'module': module, 'value': ret }) if ret is not None: hotpotato = ret except Exception: from traceback import extract_stack from traceback import extract_tb from traceback import format_list log.add( _("Plugin %(module)s failed with error %(errortype)s: %(error)s.\nTrace: %(trace)s\nProblem area:%(area)s" ), { 'module': module, 'errortype': sys.exc_info()[0], 'error': sys.exc_info()[1], 'trace': ''.join(format_list(extract_stack())), 'area': ''.join( format_list(extract_tb(sys.exc_info()[2]))) }) return hotpotato
def connect(self): if not self.protothread.server_disconnected: return True valid_network_interface = self.protothread.validate_network_interface() if not valid_network_interface: message = _( "The network interface you specified, '%s', does not exist. Change or remove the specified " "network interface and restart Nicotine+.") log.add_important_error(message, self.protothread.interface) return False valid_listen_port = self.protothread.validate_listen_port() if not valid_listen_port: message = _( "The range you specified for client connection ports was " "{}-{}, but none of these were usable. Increase and/or ". format(self.protothread.portrange[0], self.protothread.portrange[1]) + "move the range and restart Nicotine+.") if self.protothread.portrange[0] < 1024: message += "\n\n" + _( "Note that part of your range lies below 1024, this is usually not allowed on" " most operating systems with the exception of Windows.") log.add_important_error(message) return False self.protothread.server_connect() # Clear any potential messages queued up while offline self.queue.clear() addr = config.sections["server"]["server"] login = config.sections["server"]["login"] password = config.sections["server"]["passw"] log.add(_("Connecting to %(host)s:%(port)s"), { 'host': addr[0], 'port': addr[1] }) self.queue.append( slskmessages.ServerConnect(addr, login=(login, password))) return True
def process_search_term(self, text, mode, room, user): users = [] feedback = None if mode == "global": if self.core: feedback = self.core.pluginhandler.outgoing_global_search_event(text) if feedback is not None: text = feedback[0] elif mode == "rooms": # Space after Joined Rooms is important, so it doesn't conflict # with any possible real room if room == _("Joined Rooms ") or room.isspace(): room = None if self.core: feedback = self.core.pluginhandler.outgoing_room_search_event(room, text) if feedback is not None: room, text = feedback elif mode == "buddies" and self.core: feedback = self.core.pluginhandler.outgoing_buddy_search_event(text) if feedback is not None: text = feedback[0] elif mode == "user": if user: users = [user] else: return None if self.core: feedback = self.core.pluginhandler.outgoing_user_search_event(users, text) if feedback is not None: users, text = feedback else: log.add("Unknown search mode, not using plugin system. Fix me!") return text, room, users
def create_data_folder(self): """ Create the folder for storing data in (aliases, shared files etc.), if the folder doesn't exist """ try: if not os.path.isdir(self.data_dir): os.makedirs(self.data_dir) except OSError as msg: from pynicotine.logfacility import log log.add( _("Can't create directory '%(path)s', reported error: %(error)s" ), { 'path': self.data_dir, 'error': msg })
def append_line(textview, line, tag=None, timestamp=None, showstamp=True, timestamp_format="%H:%M:%S", username=None, usertag=None, scroll=True, find_urls=True): from pynicotine.gtkgui.widgets.textview import append_line as append_new log.add( "pynicotine.gtkgui.utils.append_line is deprecated and should not be accessed directly by plugins anymore" ) append_new(textview, line, tag, timestamp, showstamp, timestamp_format, username, usertag, scroll, find_urls)
def load_plugin(self, pluginname): path = self.__findplugin(pluginname) if path is None: log.add( _("Failed to load plugin '%s', could not find it.") % pluginname) return False sys.path.insert(0, path) plugin = imp.load_source(pluginname, os.path.join(path, '__init__.py')) instance = plugin.Plugin(self) self.plugin_settings(instance) instance.LoadNotification() # log.add("Loaded plugin %s (version %s) from %s" % (instance.__name__, instance.__version__, modulename)) # self.plugins.append((module, instance)) sys.path = sys.path[1:] self.loaded_plugins[pluginname] = plugin return plugin
def load_picture(self, data): if not data: self.placeholder_picture.show() return try: import gc import tempfile with tempfile.NamedTemporaryFile() as file_handle: file_handle.write(data) del data self.picture_data = GdkPixbuf.Pixbuf.new_from_file( file_handle.name) picture_width = self.picture_data.get_width() picture_height = self.picture_data.get_height() allocation = self.picture_container.get_allocation() max_width = allocation.width - 72 max_height = allocation.height - 72 # Resize picture to fit container ratio = min(max_width / picture_width, max_height / picture_height) self.picture_data = self.picture_data.scale_simple( ratio * picture_width, ratio * picture_height, GdkPixbuf.InterpType.BILINEAR) if Gtk.get_major_version() == 4: self.picture.set_pixbuf(self.picture_data) else: self.picture.set_from_pixbuf(self.picture_data) gc.collect() self.actual_zoom = 0 self.picture_view.show() except Exception as error: log.add(_("Failed to load picture for user %(user)s: %(error)s"), { "user": self.user, "error": error })
def load_plugin(self, plugin_name): try: # Import builtin plugin from importlib import import_module plugin = import_module("pynicotine.plugins." + plugin_name) except Exception: # Import user plugin path = self.findplugin(plugin_name) if path is None: log.add(_("Failed to load plugin '%s', could not find it."), plugin_name) return None # Add plugin folder to path in order to support relative imports sys.path.append(path) import importlib.util spec = importlib.util.spec_from_file_location( plugin_name, os.path.join(path, '__init__.py')) plugin = importlib.util.module_from_spec(spec) spec.loader.exec_module(plugin) instance = plugin.Plugin() instance.internal_name = BasePlugin.internal_name instance.human_name = BasePlugin.human_name self.plugin_settings(plugin_name, instance) if hasattr(plugin, "enable"): instance.log( "top-level enable() function is obsolete, please use BasePlugin.__init__() instead" ) if hasattr(plugin, "disable"): instance.log( "top-level disable() function is obsolete, please use BasePlugin.disable() instead" ) if hasattr(instance, "LoadNotification"): instance.log("LoadNotification() is obsolete, please use init()") return instance
def process_search_term(self, text, mode, room, user): users = [] feedback = None if mode == "global": if self.core: feedback = self.core.pluginhandler.outgoing_global_search_event( text) if feedback is not None: text = feedback[0] elif mode == "rooms": if self.core: feedback = self.core.pluginhandler.outgoing_room_search_event( room, text) if feedback is not None: room, text = feedback elif mode == "buddies" and self.core: feedback = self.core.pluginhandler.outgoing_buddy_search_event( text) if feedback is not None: text = feedback[0] elif mode == "user": if user: users = [user] else: return None if self.core: feedback = self.core.pluginhandler.outgoing_user_search_event( users, text) if feedback is not None: users, text = feedback else: log.add("Unknown search mode, not using plugin system. Fix me!") return text, room, users
def disable_plugin(self, pluginname): if pluginname not in self.enabled_plugins: return try: plugin = self.enabled_plugins[pluginname] log.add(_("Disabled plugin {}".format(plugin.PLUGIN.__name__))) del self.enabled_plugins[pluginname] plugin.disable(self) except Exception: from traceback import print_exc print_exc() log.add(_("Unable to fully disable plugin %s"), pluginname) return False return True
def get_shared_folders(self, sharestype): if sharestype == "normal": log.add(_("Rescanning normal shares...")) shared_folders = self.config.sections["transfers"]["shared"][:] else: log.add(_("Rescanning buddy shares...")) shared_folders = self.config.sections["transfers"][ "buddyshared"][:] + self.config.sections["transfers"][ "shared"][:] if self.config.sections["transfers"]["sharedownloaddir"]: shared_folders.append( (_('Downloaded'), self.config.sections["transfers"]["downloaddir"])) return shared_folders
def get_dirs_mtimes(self, dirs): """ Get Modification Times """ list = {} for folder in dirs: try: if self.is_hidden(folder): continue mtime = os.path.getmtime(folder) list[folder] = mtime for entry in os.scandir(folder): if entry.is_dir(): path = entry.path try: mtime = entry.stat().st_mtime except OSError as errtuple: log.add( _("Error while scanning %(path)s: %(error)s") % { 'path': path, 'error': errtuple }) continue list[path] = mtime dircontents = self.get_dirs_mtimes([path]) for k in dircontents: list[k] = dircontents[k] except OSError as errtuple: log.add( _("Error while scanning folder %(path)s: %(error)s") % { 'path': folder, 'error': errtuple }) continue return list
def login(self, msg): """ Server code: 1 """ log.add_msg_contents(msg) if msg.success: self.logged_in = True self.login_username = msg.username self.set_away_mode(config.sections["server"]["away"]) self.watch_user(msg.username) if msg.ip_address is not None: self.user_ip_address = msg.ip_address self.transfers.server_login() self.search.server_login() self.userbrowse.server_login() self.userinfo.server_login() self.userlist.server_login() self.privatechats.server_login() self.chatrooms.server_login() if self.ui_callback: self.ui_callback.server_login() if msg.banner: log.add(msg.banner) self.interests.server_login() self.shares.send_num_shared_folders_files() self.queue.append( slskmessages.PrivateRoomToggle( config.sections["server"]["private_chatrooms"])) self.pluginhandler.server_connect_notification() else: if msg.reason == "INVALIDPASS": self.ui_callback.invalid_password() return log.add_important_error( _("Unable to connect to the server. Reason: %s"), msg.reason)
def get_shared_file_list(self, msg): """ Peer code: 4 """ log.add_msg_contents(msg) user = msg.init.target_user request_time = time.time() if user in self.requested_share_times and request_time < self.requested_share_times[ user] + 0.4: # Ignoring request, because it's less than half a second since the # last one by this user return self.requested_share_times[user] = request_time log.add(_("User %(user)s is browsing your list of shared files"), {'user': user}) ip_address, _port = msg.init.addr checkuser, reason = self.network_filter.check_user(user, ip_address) if not checkuser: message = self.ban_message % reason self.privatechats.send_automatic_message(user, message) shares_list = None if checkuser == 1: # Send Normal Shares shares_list = self.shares.get_compressed_shares_message("normal") elif checkuser == 2: # Send Buddy Shares shares_list = self.shares.get_compressed_shares_message("buddy") if not shares_list: # Nyah, Nyah shares_list = slskmessages.SharedFileList(msg.init, {}) shares_list.init = msg.init self.queue.append(shares_list)
def load_plugin(self, pluginname): path = self.__findplugin(pluginname) if path is None: log.add(_("Failed to load plugin '%s', could not find it."), pluginname) return False sys.path.insert(0, path) from importlib.machinery import SourceFileLoader plugin = SourceFileLoader(pluginname, os.path.join(path, '__init__.py')).load_module() instance = plugin.Plugin(self) self.plugin_settings(instance) instance.LoadNotification() sys.path = sys.path[1:] self.loaded_plugins[pluginname] = plugin return plugin
def plugin_settings(self, plugin): try: if not hasattr(plugin, "settings"): return if plugin.__id__ not in self.frame.np.config.sections["plugins"]: self.frame.np.config.sections["plugins"][plugin.__id__] = plugin.settings for i in plugin.settings: if i not in self.frame.np.config.sections["plugins"][plugin.__id__]: self.frame.np.config.sections["plugins"][plugin.__id__][i] = plugin.settings[i] customsettings = self.frame.np.config.sections["plugins"][plugin.__id__] for key in customsettings: if key in plugin.settings: plugin.settings[key] = customsettings[key] else: log.add(_("Stored setting '%(name)s' is no longer present in the plugin") % {'name': key}) except KeyError: log.add("No custom settings found for %s" % (plugin.__name__,)) pass
def get_dir_stream(self, dir): """ Pack all files and metadata in directory """ message = slskmessages.SlskMessage() stream = bytearray() stream.extend(message.packObject(len(dir))) for fileinfo in dir: stream.extend(bytes([1])) stream.extend(message.packObject(fileinfo[0])) stream.extend( message.packObject(fileinfo[1], unsignedlonglong=True)) if fileinfo[2] is not None: try: stream.extend(message.packObject('mp3')) stream.extend(message.packObject(3)) stream.extend(message.packObject(0)) stream.extend(message.packObject(fileinfo[2][0])) stream.extend(message.packObject(1)) stream.extend(message.packObject(fileinfo[3])) stream.extend(message.packObject(2)) stream.extend(message.packObject(fileinfo[2][1])) except Exception: log.add( _( "Found meta data that couldn't be encoded, possible corrupt file: '%(file)s' has a bitrate of %(bitrate)s kbs, a length of %(length)s seconds and a VBR of %(vbr)s" % { 'file': fileinfo[0], 'bitrate': fileinfo[2][0], 'length': fileinfo[3], 'vbr': fileinfo[2][1] })) stream.extend(message.packObject('')) stream.extend(message.packObject(0)) else: stream.extend(message.packObject('')) stream.extend(message.packObject(0)) return stream
def get_user_status(self, msg): status = msg.status if status < 0: # User doesn't exist, nothing to do return user = msg.user iterator = self.user_iterators.get(user) if iterator is None: return if status == int(self.usersmodel.get_value(iterator, 10)): return notify = self.usersmodel.get_value(iterator, 6) if notify: if status == 1: status_text = _("User %s is away") elif status == 2: status_text = _("User %s is online") else: status_text = _("User %s is offline") log.add(status_text, user) self.frame.notifications.new_text_notification(status_text % user) img = self.frame.get_status_image(status) self.usersmodel.set_value(iterator, 0, GObject.Value(GObject.TYPE_OBJECT, img)) self.usersmodel.set_value(iterator, 10, GObject.Value(GObject.TYPE_INT64, status)) if status: # online self.set_last_seen(user, online=True) elif not self.usersmodel.get_value(iterator, 8): # disconnected self.set_last_seen(user)
def new_notification(self, message, title=None, priority=Gio.NotificationPriority.NORMAL): if title is None: title = GLib.get_application_name() try: if sys.platform == "win32": """ Windows notification popup support via plyer Once https://gitlab.gnome.org/GNOME/glib/-/issues/1234 is implemented, we can drop plyer """ from plyer import notification notification.notify(app_name=GLib.get_application_name(), title=title, message=message) if self.frame.np.config.sections["notifications"][ "notification_popup_sound"]: import winsound winsound.PlaySound("SystemAsterisk", winsound.SND_ALIAS) return notification_popup = Gio.Notification.new(title) notification_popup.set_body(message) if self.frame.images["notify"]: notification_popup.set_icon(self.frame.images["notify"]) notification_popup.set_priority(priority) self.application.send_notification(None, notification_popup) if self.frame.np.config.sections["notifications"][ "notification_popup_sound"]: Gdk.beep() except Exception as error: log.add(_("Unable to show notification popup: %s"), str(error))
def run(): renameprocess('nicotine') import getopt import os.path try: opts, args = getopt.getopt(sys.argv[1:], "hc:p:tdvswb:", [ "help", "config=", "plugins=", "profile", "enable-trayicon", "disable-trayicon", "enable-rgba", "disable-rgba", "version", "hidden", "bindip=" ] ) except getopt.GetoptError: # print help information and exit usage() sys.exit(2) if win32: try: mydir = os.path.join(os.environ['APPDATA'], 'nicotine') except KeyError: mydir, x = os.path.split(sys.argv[0]) config = os.path.join(mydir, "config", "config") plugins = os.path.join(mydir, "plugins") else: config = os.path.join(os.path.expanduser("~"), '.nicotine', 'config') plugins = os.path.join(os.path.expanduser("~"), '.nicotine', 'plugins') profile = 0 trayicon = 1 tryrgba = False hidden = False bindip = None for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() if o in ("-c", "--config"): config = a if o in ("-p", "--plugins"): plugins = a if o in ("-b", "--bindip"): bindip = a if o == "--profile": profile = 1 if o in ("-t", "--enable-trayicon"): trayicon = 1 if o in ("-d", "--disable-trayicon"): trayicon = 0 if o in ('-r', '--enable-rgba'): tryrgba = True if o in ('-x', '--disable-rgba'): tryrgba = False if o in ('-s', '--hidden'): hidden = True if o in ("-v", "--version"): version() sys.exit() result = checkenv() if result is None: from pynicotine.gtkgui import frame app = frame.MainApp(config, plugins, trayicon, tryrgba, hidden, bindip) if profile: import hotshot logfile = os.path.expanduser(config) + ".profile" profiler = hotshot.Profile(logfile) log.add(_("Starting using the profiler (saving log to %s)") % logfile) profiler.runcall(app.MainLoop) else: app.MainLoop() else: print result
) # Windows stuff: detect GTK dll's path and add it to %PATH% if we're not running a py2exe package if win32 and not py2exe: # Fetchs gtk2 path from registry import _winreg try: k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\GTK\\2.0") except EnvironmentError: print _("You must install the Gtk+ 2.x Runtime Environment to run this program") sys.exit(1) else: gtkdir = _winreg.QueryValueEx(k, "Path") msg = "GTK DLLs found at %s" % (gtkdir[0]) log.add(msg) import os os.environ["PATH"] += ";%s/lib;%s/bin" % (gtkdir[0], gtkdir[0]) if win32: try: import dbhash except: log.add(_("Warning: the Berkeley DB module, dbhash, could not be loaded.")) innerexception = None try: if win32: try: import gtk
def run(): renameprocess("nicotine") import locale # Win32 hack to fix LANG and LC_ALL environnment variables with unix compliant language code # See pynicotine/libi18n.py if win32: import pynicotine.libi18n pynicotine.libi18n.fix_locale() del pynicotine.libi18n try: locale.setlocale(locale.LC_ALL, "") except: log.addwarning(_("Cannot set locale")) import gettext gettext.textdomain("nicotine") import sys, getopt, os.path try: opts, args = getopt.getopt( sys.argv[1:], "hc:p:tdvswb:", [ "help", "config=", "plugins=", "profile", "enable-trayicon", "disable-trayicon", "enable-rgba", "disable-rgba", "version", "hidden", "disable-webbrowser", "bindip=", ], ) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) if win32: try: mydir = os.path.join(os.environ["APPDATA"], "nicotine") except KeyError: # windows 9x? mydir, x = os.path.split(sys.argv[0]) config = os.path.join(mydir, "config", "config") plugins = os.path.join(mydir, "plugins") else: config = os.path.join(os.path.expanduser("~"), ".nicotine", "config") plugins = os.path.join(os.path.expanduser("~"), ".nicotine", "plugins") profile = 0 trayicon = 1 webbrowser = True tryrgba = False hidden = False bindip = None for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() if o in ("-c", "--config"): config = a if o in ("-p", "--plugins"): plugins = a if o in ("-b", "--bindip"): bindip = a if o == "--profile": profile = 1 if o in ("-t", "--enable-trayicon"): trayicon = 1 if o in ("-d", "--disable-trayicon"): trayicon = 0 if o in ("-w", "--disable-webbrowser"): webbrowser = False if o in ("-r", "--enable-rgba"): tryrgba = True if o in ("-x", "--disable-rgba"): tryrgba = False if o in ("-s", "--hidden"): hidden = True if o in ("-v", "--version"): version() sys.exit() result = checkenv() if result is None: from pynicotine.gtkgui import frame app = frame.MainApp(config, plugins, trayicon, tryrgba, hidden, webbrowser, bindip) if profile: import hotshot logfile = os.path.expanduser(config) + ".profile" profiler = hotshot.Profile(logfile) log.add(_("Starting using the profiler (saving log to %s)") % logfile) profiler.runcall(app.MainLoop) else: app.MainLoop() else: print result