diff -Nru fbmessenger-0.1.0-20131212/.gitignore fbmessenger-0.2.0-20140120/.gitignore --- fbmessenger-0.1.0-20131212/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ fbmessenger-0.2.0-20140120/.gitignore 2014-01-20 11:29:16.000000000 +0000 @@ -0,0 +1,2 @@ +__pycache__ +*.pyc diff -Nru fbmessenger-0.1.0-20131212/README.md fbmessenger-0.2.0-20140120/README.md --- fbmessenger-0.1.0-20131212/README.md 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/README.md 2014-01-20 11:29:16.000000000 +0000 @@ -7,17 +7,20 @@ If you have all the dependencies, you can launch the app straight from this repository with `./run.sh`. After you install it, you can launch it with -`fbmessenger`. There are packaging scripts included under `packaging/` for -Linux (deb, rpm, arch) and Mac (brew). See the `README` files in there for -installation instructions. You can also install with `python3 setup.py -install`. Ubuntu users can install from a PPA by following [the instructions +`fbmessenger`. Ubuntu users can install from a PPA by following [the +instructions here](http://www.webupd8.org/2013/04/fbmessenger-stand-alone-facebook.html) (thanks Alin Andrei). Arch users can [install from the -AUR](https://aur.archlinux.org/packages/fbmessenger-git/). +AUR](https://aur.archlinux.org/packages/fbmessenger-git/). There are packaging +scripts included under `packaging/` for Linux (Debian/Ubuntu in `deb`, Red +Hat/Fedora in `rpm`, and Arch) and OS X (using the Homebrew package manager). +See the `README` files in packaging subdirectories for more specific +instructions. You can also install with `sudo python3 setup.py install`, but +that makes it hard to uninstall, so prefer to use the packaging scripts. -The configuration file is `~/.fbmessenger/settings.json`. Right now the only -setting that users might want to mess with is `"Zoom"`; set a value like `1.2` -to make the fonts 20% bigger. +The configuration file is `~/.fbmessenger/config.py`. Right now the only +setting that users might want to mess with is `Zoom`; set a value like +`Zoom = 1.2` to make the fonts 20% bigger. ####Dependencies * Python 3 diff -Nru fbmessenger-0.1.0-20131212/bin/fbmessenger fbmessenger-0.2.0-20140120/bin/fbmessenger --- fbmessenger-0.1.0-20131212/bin/fbmessenger 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/bin/fbmessenger 2014-01-20 11:29:16.000000000 +0000 @@ -1,4 +1,4 @@ -#! /usr/bin/python3 +#! /usr/bin/env python3 from fbmessenger import main diff -Nru fbmessenger-0.1.0-20131212/debian/changelog fbmessenger-0.2.0-20140120/debian/changelog --- fbmessenger-0.1.0-20131212/debian/changelog 2013-12-12 11:00:53.000000000 +0000 +++ fbmessenger-0.2.0-20140120/debian/changelog 2014-01-20 11:34:14.000000000 +0000 @@ -1,4 +1,11 @@ -fbmessenger (0.1.0-20131212-0~webupd8~precise) precise; urgency=medium +fbmessenger (0.2.0-20140120-0~webupd8~precise) precise; urgency=medium + + * new git pull: + - Use os._exit(0) instead of sys.exit() + + -- Alin Andrei Mon, 20 Jan 2014 13:30:18 +0200 + +fbmessenger (0.1.0-20131212-0~webupd8~saucy) saucy; urgency=medium * new git pull: - Implement isIdle() properly diff -Nru fbmessenger-0.1.0-20131212/fbmessenger/application.py fbmessenger-0.2.0-20140120/fbmessenger/application.py --- fbmessenger-0.1.0-20131212/fbmessenger/application.py 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/fbmessenger/application.py 2014-01-20 11:29:16.000000000 +0000 @@ -6,6 +6,7 @@ sip.setapi(module, 2) import sys +import os import signal import os.path from PyQt4 import QtCore @@ -72,6 +73,6 @@ def quit(): # Don't bother with _app.exit(). Other parts of the app may still use Qt # objects while they're being cleaned up, which causes scary errors - # (https://github.com/oconnor663/fbmessenger/issues/33). Just exit the - # process directly. - sys.exit() + # (https://github.com/oconnor663/fbmessenger/issues/33). Even sys.exit() is + # has the potential to let threads spin forever. Just do a hard os exit. + os._exit(0) diff -Nru fbmessenger-0.1.0-20131212/fbmessenger/mqtt.py fbmessenger-0.2.0-20140120/fbmessenger/mqtt.py --- fbmessenger-0.1.0-20131212/fbmessenger/mqtt.py 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/fbmessenger/mqtt.py 2014-01-20 11:29:16.000000000 +0000 @@ -13,6 +13,11 @@ MQTT_URL = "orcart.facebook.com" MQTT_PORT = 443 +use_tls = True +# Uncomment below to connect to MQTT on a devserver (Facebook internal). +# MQTT_URL = your_devserver_here +# MQTT_PORT = 8883 +# use_tls = False is_connected = False @@ -29,11 +34,13 @@ _client.on_disconnect = _on_disconnect _client.on_message = _on_message - # Find the system certs file, or fall back to our own copy. - cert_path = "/etc/ssl/certs/ca-certificates.crt" - if not os.path.exists(cert_path): - cert_path = application.resource_path("ca-certificates-fallback.crt") - _client.tls_set(cert_path) + if use_tls: + # Find the system certs file, or fall back to our own copy. + cert_path = "/etc/ssl/certs/ca-certificates.crt" + if not os.path.exists(cert_path): + cert_path = application.resource_path( + "ca-certificates-fallback.crt") + _client.tls_set(cert_path) event.subscribe(settings.AUTH_CHANGED_EVENT, _force_reconnect) event.subscribe(network.NETWORK_CHANGED_EVENT, _force_reconnect) diff -Nru fbmessenger-0.1.0-20131212/fbmessenger/settings.py fbmessenger-0.2.0-20140120/fbmessenger/settings.py --- fbmessenger-0.1.0-20131212/fbmessenger/settings.py 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/fbmessenger/settings.py 2014-01-20 11:29:16.000000000 +0000 @@ -1,13 +1,32 @@ +import json import os from os import path -import json +import shutil +import traceback from . import event AUTH_CHANGED_EVENT = object() +SETTINGS_DIR = path.expanduser("~/.fbmessenger") + +_internal_settings_file = path.join(SETTINGS_DIR, "internal_data.json") +_legacy_settings_file = path.join(SETTINGS_DIR, "settings.json") + +_user_config_file = path.join(SETTINGS_DIR, "config.py") + +_values = {} +_settings = {} +# User settings should not be persisted in the internal data file. That would +# make it hard to unset a setting, because the previous value would stick +# around in internal data. Maintain a separate dictionary containing only those +# settings that were either loaded from disk or set with set_setting(). Only +# the keys in this dictionary will get written back to disk. +_internal_settings = {} + def set_setting(key, val): _settings[key] = val + _internal_settings[key] = val _save_settings() def get_setting(key, default=""): @@ -30,27 +49,74 @@ event.inform(AUTH_CHANGED_EVENT) def _save_settings(): + with open(_internal_settings_file, "w") as f: + # Only persist internal settings to disk. See comment above. + json.dump(_internal_settings, f, indent=2, sort_keys=True, + separators=(',', ': ')) + +_default_user_config = '''\ +# To configure fbmessenger, set Python variables in this file. For example, to +# make text appear 20% bigger, set the Zoom variable: +# +# Zoom = 1.2 +''' + +def _read_user_config(): + user_settings = {} + + # If no config file exists, create an empty one with a helpful comment. + if not path.exists(_user_config_file): + with open(_user_config_file, "w") as f: + f.write(_default_user_config) + + # Read the contents of the config file, which should be Python code. + with open(_user_config_file, "r") as f: + config_code = f.read() + + # Execute that code and copy the local variables it defines into _settings. + # If there are exceptions, print them, but continue startup as if the + # user's config file had been empty. + try: + exec(config_code, {}, user_settings) + except: + print("Loading {0} failed:".format(_user_config_file)) + traceback.print_exc() + else: + _settings.update(user_settings) + +def _init(): if not path.exists(SETTINGS_DIR): os.mkdir(SETTINGS_DIR) - with open(_settings_file, "w") as f: - json.dump(_settings, f, indent=2, sort_keys=True, - separators=(',', ': ')) -def _load_settings(): - global _settings - if path.exists(_settings_file): - with open(_settings_file) as f: + # The settings file used to be called "settings.json". It's been renamed to + # "internal_data.json" to avoid the impression that users should edit it, + # but we still need to check for the old path for backwards compatibility. + # TODO: Eventually remove this legacy code. + path_to_open = _internal_settings_file + if not path.exists(path_to_open): + path_to_open = _legacy_settings_file + + # Read internal settings from disk. + if path.exists(path_to_open): + with open(path_to_open) as f: try: - _settings = json.load(f) + parsed_json = json.load(f) except Exception as e: - print("Loading settings failed: ", e) - _settings = {} - -SETTINGS_DIR = path.expanduser("~/.fbmessenger") - -_settings_file = path.join(SETTINGS_DIR, "settings.json") - -_values = {} -_settings = {} - -_load_settings() + print("Loading {0} failed:".format(path_to_open)) + traceback.print_exc() + # Continuing with startup will overwrite an existing settings + # file. Save a copy of the bad file for debugging. + bad_copy_path = path_to_open + ".bad" + print("Saving the bad file at", bad_copy_path) + shutil.copyfile(path_to_open, bad_copy_path) + else: + _internal_settings.update(parsed_json) + _settings.update(parsed_json) + + # Reading the user config last allows it to override disk settings. + _read_user_config() + +# Settings like CookieJar are needed at import time, even before application.py +# starts calling init() functions. So we have to read settings from disk as +# soon as this module is imported. +_init() diff -Nru fbmessenger-0.1.0-20131212/fbmessenger/windows.py fbmessenger-0.2.0-20140120/fbmessenger/windows.py --- fbmessenger-0.1.0-20131212/fbmessenger/windows.py 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/fbmessenger/windows.py 2014-01-20 11:29:16.000000000 +0000 @@ -7,9 +7,6 @@ # Used for toast and chat window positioning _margin = 10 -# Chat position is not saved when the application closes -_chat_rectangle = None - def init(): base_url = "https://www.facebook.com" base_url_override = settings.get_setting("BaseUrl") @@ -32,11 +29,11 @@ global chat_window chat_window = browser.BrowserWindow(base_url + "/desktop/client/chat.php") chat_window.set_size(420, 340) - def chat_window_moved(): - global _chat_rectangle - _chat_rectangle = chat_window.get_rectangle() - event.subscribe(chat_window.MOVE_EVENT, chat_window_moved) - event.subscribe(chat_window.RESIZE_EVENT, chat_window_moved) + def chat_window_moved_or_resized(): + settings.set_setting( + "ChatWindowRectangle", chat_window.get_rectangle()) + event.subscribe(chat_window.MOVE_EVENT, chat_window_moved_or_resized) + event.subscribe(chat_window.RESIZE_EVENT, chat_window_moved_or_resized) global toast_window toast_window = browser.BrowserWindow( @@ -59,8 +56,9 @@ # aligned on the left (or right if not enough space). If moved or resized, the # position is remembered while the app is still running. def show_chat_window(): - if _chat_rectangle: - rect = _chat_rectangle + saved_rectangle = settings.get_setting("ChatWindowRectangle") + if saved_rectangle: + rect = saved_rectangle else: desk_x, desk_y, desk_width, desk_height = \ main_window.get_desktop_rectangle() diff -Nru fbmessenger-0.1.0-20131212/packaging/deb/README fbmessenger-0.2.0-20140120/packaging/deb/README --- fbmessenger-0.1.0-20131212/packaging/deb/README 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/packaging/deb/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -To create a .deb package for Debian/Ubuntu/etc, just run: - - ./build-deb.sh - -That will create a package named something like "fbmessenger-0.2.0.deb" in the -current directory. To install it, run: - - sudo dpkg -i fbmessenger-0.2.0.deb - -The package manager will probably complain that you're missing some -dependencies. To fix that, run: - - sudo apt-get install -f - -Now you should be good to go. The app should show up in your desktop -environment, or you can launch it with: - - fbmessenger diff -Nru fbmessenger-0.1.0-20131212/packaging/deb/README.md fbmessenger-0.2.0-20140120/packaging/deb/README.md --- fbmessenger-0.1.0-20131212/packaging/deb/README.md 1970-01-01 00:00:00.000000000 +0000 +++ fbmessenger-0.2.0-20140120/packaging/deb/README.md 2014-01-20 11:29:16.000000000 +0000 @@ -0,0 +1,24 @@ +First make sure you've installed setuptools for Python 3. You can probably do +that with the command: + + sudo apt-get install python3-setuptools + +The rest of the dependencies will get taken care of later by the package +manager. Now, to create a .deb package for Debian/Ubuntu/etc, just run: + + ./build-deb.sh + +That will create a package named something like "fbmessenger-0.2.0.deb" in the +current directory. To install it, run: + + sudo dpkg -i fbmessenger-0.2.0.deb + +The package manager will probably complain that you're missing some +dependencies. To fix that, run: + + sudo apt-get install -f + +Now you should be good to go. The app should show up in your desktop +environment, or you can launch it with: + + fbmessenger diff -Nru fbmessenger-0.1.0-20131212/run.sh fbmessenger-0.2.0-20140120/run.sh --- fbmessenger-0.1.0-20131212/run.sh 2013-12-12 10:58:30.000000000 +0000 +++ fbmessenger-0.2.0-20140120/run.sh 2014-01-20 11:29:16.000000000 +0000 @@ -1,3 +1,5 @@ +#! /bin/bash + root=`dirname $BASH_SOURCE` PYTHONPATH="$root" "$root/bin/fbmessenger"