#Changelog :
# -- 0.7.16 | 03/11/2009 : Better login experience
# -- 0.7.15 | 09/05/2009 : Added suffix option | Updated strings
# -- 0.7.12 | 09/02/2009 : Various configuration bugfixes | Updated some strings
# -- 0.7.10 | 09/02/2009 : Some translations updates | The two status option have merged into a "synchronization" option. Seeparing them is kind of unusual now. | Comments are downloaded in a new thread if there is a new comment | Fixed a bug with commentscount displaying | Various comments bugfixes
# -- 0.7.5 | 09/01/2009 : Plugin ready for translations | Updated some strings
# -- 0.7 | 09/01/2009 : Now when the status is cleared from facebook, the commentsbox disappears. Bugfix w/ commentsactive. Now comments are grabbed in a new thread if commentscount changes. Configuration box rewritten. Optimized threads. Some cleaning.
# -- 0.6.11 | 08/30/2009 : Solved a bug w/ commentscount and comments displaying ? | Added a silhouette logo if the user doesn't have a profilepic
# -- 0.6.9 | 08/28/2009 : Removed pango from the importations | Changed a sentence in confirmation box
# -- 0.6.7 | 08/28/2009 : Comments button is destroyed when changing or clearing status | Now 'confirmation' is saved | Disable comments if 1st option disabled. Silent now.
# -- 0.6.4 | 08/28/2009 : Bugfixes
# -- 0.6.2 | 08/27/2009 : Trying to solve a bug that makes the user authenticate every time | Trying to handle silently facebook errors and urllib errors
# -- 0.6 | 08/27/2009 : This version implements threads. No need to import gobject now
# -- 0.5.14 | 08/24/2009 : Fixed a nasty bug on startup.
# -- 0.5.13 | 08/08/2009 : Created a facebook directory where is put facebook stuff | bugfix, faster | Now comments activated by default
# -- 0.5.12 | 08/08/2009 : This should reduce gui locks a lot
# -- 0.5.11 | 08/08/2009 : As fast as before, but no need to have read_stream
# -- 0.5.10 | 08/08/2009 : Comments request improved. It downloads pictures once.
# -- 0.5.9 | 08/07/2009 : Added read_stream. It prevents gui_locks but you'll have to delete Facebook.conf
# -- 0.5.8 | 08/07/2009 : Comments are saved and retrieved if commentscount didn't change (still WIP though) | it stops checking after the plugin to stop
# -- 0.5.6 | 08/07/2009 : Bugfix
# -- 0.5.5 | 08/07/2009 : Nicolaide's comments box integrated, w/ picture retrieving | New pyfacebook version | Some workarounds
# -- 0.5.2 | 08/05/2009 : Initial logged release
#
# mehd36 at gmail . com
#
# This plugin is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This plugin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
import Plugin
import paths
import gtk
import os
import gc
import base64
import desktop
from threading import Event,Thread
#
# pyfacebook - Python bindings for the Facebook API
#
import sys
import time
import struct
import urllib
import urllib2
import httplib
try:
import hashlib
except ImportError:
import md5 as hashlib
import binascii
import urlparse
import mimetypes
# try to use simplejson first, otherwise fallback to XML
RESPONSE_FORMAT = 'JSON'
try:
import json as simplejson
except ImportError:
try:
import simplejson
except ImportError:
try:
from django.utils import simplejson
except ImportError:
try:
import jsonlib as simplejson
simplejson.loads
except (ImportError, AttributeError):
from xml.dom import minidom
RESPONSE_FORMAT = 'XML'
# support Google App Engine. GAE does not have a working urllib.urlopen.
try:
from google.appengine.api import urlfetch
def urlread(url, data=None, headers=None):
if data is not None:
if headers is None:
headers = {"Content-type": "application/x-www-form-urlencoded"}
method = urlfetch.POST
else:
if headers is None:
headers = {}
method = urlfetch.GET
result = urlfetch.fetch(url, method=method,
payload=data, headers=headers)
if result.status_code == 200:
return result.content
else:
raise urllib2.URLError("fetch error url=%s, code=%d" % (url, result.status_code))
except ImportError:
def urlread(url, data=None):
try:
res = urllib2.urlopen(url, data=data)
return res.read()
except:
res = urllib2.urlopen(url, data=data)
return res.read()
__all__ = ['Facebook']
VERSION = '0.1'
FACEBOOK_URL = 'http://api.facebook.com/restserver.php'
FACEBOOK_SECURE_URL = 'https://api.facebook.com/restserver.php'
class json(object): pass
# simple IDL for the Facebook API
METHODS = {
'notifications': {
'get': []
},
# users methods
'users': {
'getInfo': [
('uids', list, []),
('fields', list, [('default', ['name'])]),
],
'getStandardInfo': [
('uids', list, []),
('fields', list, [('default', ['uid'])]),
],
'getLoggedInUser': [],
'isAppAdded': [],
'hasAppPermission': [
('ext_perm', str, []),
('uid', int, ['optional']),
],
'setStatus': [
('status', str, []),
('clear', bool, []),
('status_includes_verb', bool, ['optional']),
('uid', int, ['optional']),
]
},
# auth methods
'auth': {
'revokeAuthorization': [
('uid', int, ['optional']),
],
},
'fql': {
'query': [
('query', str, []),
],
},
#stream methods (beta)
'stream' : {
'getComments' : [
('post_id', int, []),
]
}
}
class Proxy(object):
"""Represents a "namespace" of Facebook API calls."""
def __init__(self, client, name):
self._client = client
self._name = name
def __call__(self, method=None, args=None, add_session_args=True):
# for Django templates
if method is None:
return self
if add_session_args:
self._client._add_session_args(args)
return self._client('%s.%s' % (self._name, method), args)
# generate the Facebook proxies
def __generate_proxies():
for namespace in METHODS:
methods = {}
for method in METHODS[namespace]:
params = ['self']
body = ['args = {}']
for param_name, param_type, param_options in METHODS[namespace][method]:
param = param_name
for option in param_options:
if isinstance(option, tuple) and option[0] == 'default':
if param_type == list:
param = '%s=None' % param_name
body.append('if %s is None: %s = %s' % (param_name, param_name, repr(option[1])))
else:
param = '%s=%s' % (param_name, repr(option[1]))
if param_type == json:
# we only jsonify the argument if it's a list or a dict, for compatibility
body.append('if isinstance(%s, list) or isinstance(%s, dict): %s = simplejson.dumps(%s)' % ((param_name,) * 4))
if 'optional' in param_options:
param = '%s=None' % param_name
body.append('if %s is not None: args[\'%s\'] = %s' % (param_name, param_name, param_name))
else:
body.append('args[\'%s\'] = %s' % (param_name, param_name))
params.append(param)
# simple docstring to refer them to Facebook API docs
body.insert(0, '"""Facebook API call. See http://developers.facebook.com/documentation.php?v=1.0&method=%s.%s"""' % (namespace, method))
body.insert(0, 'def %s(%s):' % (method, ', '.join(params)))
body.append('return self(\'%s\', args)' % method)
exec('\n '.join(body))
methods[method] = eval(method)
proxy = type('%sProxy' % namespace.title(), (Proxy, ), methods)
globals()[proxy.__name__] = proxy
__generate_proxies()
class FacebookError(Exception):
"""Exception class for errors received from Facebook."""
def __init__(self, code, msg, args=None):
self.code = code
self.msg = msg
self.args = args
def __str__(self):
return 'Error %s: %s' % (self.code, self.msg)
class AuthProxy(AuthProxy):
"""Special proxy for facebook.auth."""
def getSession(self):
"""Facebook API call. See http://developers.facebook.com/documentation.php?v=1.0&method=auth.getSession"""
args = {}
try:
args['auth_token'] = self._client.auth_token
except AttributeError:
raise RuntimeError('Client does not have auth_token set.')
result = self._client('%s.getSession' % self._name, args)
self._client.session_key = result['session_key']
self._client.uid = result['uid']
self._client.secret = result.get('secret')
self._client.session_key_expires = result['expires']
return result
def createToken(self):
"""Facebook API call. See http://developers.facebook.com/documentation.php?v=1.0&method=auth.createToken"""
token = self._client('%s.createToken' % self._name)
self._client.auth_token = token
return token
class Facebook(object):
def __init__(self, api_key, secret_key, auth_token=None, app_name=None, callback_path=None, internal=None, proxy=None, facebook_url=None, facebook_secure_url=None):
self.api_key = api_key
self.secret_key = secret_key
self.session_key = None
self.session_key_expires = None
self.auth_token = auth_token
self.secret = None
self.uid = None
self.page_id = None
self.in_canvas = False
self.in_profile_tab = False
self.added = False
self.app_name = app_name
self.callback_path = callback_path
self.internal = internal
self._friends = None
self.locale = 'en_US'
self.profile_update_time = None
self.ext_perms = None
self.proxy = proxy
if facebook_url is None:
self.facebook_url = FACEBOOK_URL
else:
self.facebook_url = facebook_url
if facebook_secure_url is None:
self.facebook_secure_url = FACEBOOK_SECURE_URL
else:
self.facebook_secure_url = facebook_secure_url
for namespace in METHODS:
self.__dict__[namespace] = eval('%sProxy(self, \'%s\')' % (namespace.title(), 'facebook.%s' % namespace))
def _hash_args(self, args, secret=None):
"""Hashes arguments by joining key=value pairs, appending a secret, and then taking the MD5 hex digest."""
# @author: houyr
# fix for UnicodeEncodeError
hasher = hashlib.md5(''.join(['%s=%s' % (isinstance(x, unicode) and x.encode("utf-8") or x, isinstance(args[x], unicode) and args[x].encode("utf-8") or args[x]) for x in sorted(args.keys())]))
if secret:
hasher.update(secret)
elif self.secret:
hasher.update(self.secret)
else:
hasher.update(self.secret_key)
return hasher.hexdigest()
def _parse_response_item(self, node):
"""Parses an XML response node from Facebook."""
if node.nodeType == node.DOCUMENT_NODE and \
node.childNodes[0].hasAttributes() and \
node.childNodes[0].hasAttribute('list') and \
node.childNodes[0].getAttribute('list') == "true":
return {node.childNodes[0].nodeName: self._parse_response_list(node.childNodes[0])}
elif node.nodeType == node.ELEMENT_NODE and \
node.hasAttributes() and \
node.hasAttribute('list') and \
node.getAttribute('list')=="true":
return self._parse_response_list(node)
elif len(filter(lambda x: x.nodeType == x.ELEMENT_NODE, node.childNodes)) > 0:
return self._parse_response_dict(node)
else:
return ''.join(node.data for node in node.childNodes if node.nodeType == node.TEXT_NODE)
def _parse_response_dict(self, node):
"""Parses an XML dictionary response node from Facebook."""
result = {}
for item in filter(lambda x: x.nodeType == x.ELEMENT_NODE, node.childNodes):
result[item.nodeName] = self._parse_response_item(item)
if node.nodeType == node.ELEMENT_NODE and node.hasAttributes():
if node.hasAttribute('id'):
result['id'] = node.getAttribute('id')
return result
def _parse_response_list(self, node):
"""Parses an XML list response node from Facebook."""
result = []
for item in filter(lambda x: x.nodeType == x.ELEMENT_NODE, node.childNodes):
result.append(self._parse_response_item(item))
return result
def _check_error(self, response):
"""Checks if the given Facebook response is an error, and then raises the appropriate exception."""
if type(response) is dict and response.has_key('error_code'):
raise FacebookError(response['error_code'], response['error_msg'], response['request_args'])
def _build_post_args(self, method, args=None):
"""Adds to args parameters that are necessary for every call to the API."""
if args is None:
args = {}
for arg in args.items():
if type(arg[1]) == list:
args[arg[0]] = ','.join(str(a) for a in arg[1])
elif type(arg[1]) == unicode:
args[arg[0]] = arg[1].encode("UTF-8")
elif type(arg[1]) == bool:
args[arg[0]] = str(arg[1]).lower()
args['method'] = method
args['api_key'] = self.api_key
args['v'] = '1.0'
args['format'] = RESPONSE_FORMAT
args['sig'] = self._hash_args(args)
return args
def _add_session_args(self, args=None):
"""Adds 'session_key' and 'call_id' to args, which are used for API calls that need sessions."""
if args is None:
args = {}
if not self.session_key:
return args
#some calls don't need a session anymore. this might be better done in the markup
#raise RuntimeError('Session key not set. Make sure auth.getSession has been called.')
args['session_key'] = self.session_key
args['call_id'] = str(int(time.time() * 1000))
return args
def _parse_response(self, response, method, format=None):
"""Parses the response according to the given (optional) format, which should be either 'JSON' or 'XML'."""
if not format:
format = RESPONSE_FORMAT
if format == 'JSON':
result = simplejson.loads(response)
if type(result) is dict and result.has_key('error_code'):
result = simplejson.loads(response)
self._check_error(result)
elif format == 'XML':
dom = minidom.parseString(response)
result = self._parse_response_item(dom)
dom.unlink()
if 'error_response' in result:
dom = minidom.parseString(response)
result = self._parse_response_item(dom)
dom.unlink()
if 'error_response' in result:
self._check_error(result['error_response'])
result = result[method[9:].replace('.', '_') + '_response']
else:
raise RuntimeError('Invalid format specified.')
return result
def hash_email(self, email):
"""
Hash an email address in a format suitable for Facebook Connect.
"""
email = email.lower().strip()
return "%s_%s" % (
struct.unpack("I", struct.pack("i", binascii.crc32(email)))[0],
hashlib.md5(email).hexdigest(),
)
def unicode_urlencode(self, params):
"""
@author: houyr
A unicode aware version of urllib.urlencode.
"""
if isinstance(params, dict):
params = params.items()
return urllib.urlencode([(k, isinstance(v, unicode) and v.encode('utf-8') or v)
for k, v in params])
def __call__(self, method=None, args=None, secure=False):
"""Make a call to Facebook's REST server."""
# for Django templates, if this object is called without any arguments
# return the object itself
if method is None:
return self
# @author: houyr
# fix for bug of UnicodeEncodeError
post_data = self.unicode_urlencode(self._build_post_args(method, args))
if self.proxy:
proxy_handler = urllib2.ProxyHandler(self.proxy)
opener = urllib2.build_opener(proxy_handler)
if secure:
response = opener.open(self.facebook_secure_url, post_data).read()
else:
response = opener.open(self.facebook_url, post_data).read()
else:
if secure:
response = urlread(self.facebook_secure_url, post_data)
else:
response = urlread(self.facebook_url, post_data)
return self._parse_response(response, method)
# URL helpers
def get_url(self, page, **args):
"""
Returns one of the Facebook URLs (www.facebook.com/SOMEPAGE.php).
Named arguments are passed as GET query string parameters.
"""
return 'http://www.facebook.com/%s.php?%s' % (page, urllib.urlencode(args))
def get_app_url(self, path=''):
"""
Returns the URL for this app's canvas page, according to app_name.
"""
return 'http://apps.facebook.com/%s/%s' % (self.app_name, path)
def get_add_url(self, next=None):
"""
Returns the URL that the user should be redirected to in order to add the application.
"""
args = {'api_key': self.api_key, 'v': '1.0'}
if next is not None:
args['next'] = next
return self.get_url('install', **args)
def get_authorize_url(self, next=None, next_cancel=None):
args = {'api_key': self.api_key, 'v': '1.0'}
if next is not None:
args['next'] = next
if next_cancel is not None:
args['next_cancel'] = next_cancel
return self.get_url('authorize', **args)
def get_login_url(self, next=None, popup=False, canvas=True):
args = {'api_key': self.api_key, 'v': '1.0'}
if next is not None:
args['next'] = next
if canvas is True:
args['canvas'] = 1
if popup is True:
args['popup'] = 1
if self.auth_token is not None:
args['auth_token'] = self.auth_token
return self.get_url('login', **args)
def login(self, popup=False):
desktop.open(self.get_login_url(popup=popup))
def get_ext_perm_url(self, ext_perm, next=None, popup=False):
args = {'ext_perm': ext_perm, 'api_key': self.api_key, 'v': '1.0'}
if next is not None:
args['next'] = next
if popup is True:
args['popup'] = 1
return self.get_url('authorize', **args)
def request_extended_permission(self, ext_perm, popup=False):
"""Open a web browser telling the user to grant an extended permission."""
desktop.open(self.get_ext_perm_url(ext_perm, popup=popup))
def check_session(self, request):
self.in_canvas = (request.POST.get('fb_sig_in_canvas') == '1')
if self.session_key and (self.uid or self.page_id):
return True
if request.method == 'POST':
params = self.validate_signature(request.POST)
else:
if 'installed' in request.GET:
self.added = True
if 'fb_page_id' in request.GET:
self.page_id = request.GET['fb_page_id']
if 'auth_token' in request.GET:
self.auth_token = request.GET['auth_token']
try:
self.auth.getSession()
except FacebookError, e:
self.auth_token = None
return False
return True
params = self.validate_signature(request.GET)
if not params:
# first check if we are in django - to check cookies
if hasattr(request, 'COOKIES'):
params = self.validate_cookie_signature(request.COOKIES)
else:
# if not, then we might be on GoogleAppEngine, check their request object cookies
if hasattr(request,'cookies'):
params = self.validate_cookie_signature(request.cookies)
if not params:
return False
if params.get('in_canvas') == '1':
self.in_canvas = True
if params.get('in_profile_tab') == '1':
self.in_profile_tab = True
if params.get('added') == '1':
self.added = True
if params.get('expires'):
self.session_key_expires = int(params['expires'])
if 'locale' in params:
self.locale = params['locale']
if 'profile_update_time' in params:
try:
self.profile_update_time = int(params['profile_update_time'])
except ValueError:
pass
if 'ext_perms' in params:
self.ext_perms = params['ext_perms']
if 'friends' in params:
if params['friends']:
self._friends = params['friends'].split(',')
else:
self._friends = []
if 'session_key' in params:
self.session_key = params['session_key']
if 'user' in params:
self.uid = params['user']
elif 'page_id' in params:
self.page_id = params['page_id']
else:
return False
elif 'profile_session_key' in params:
self.session_key = params['profile_session_key']
if 'profile_user' in params:
self.uid = params['profile_user']
else:
return False
elif 'canvas_user' in params:
self.uid = params['canvas_user']
else:
return False
return True
def validate_signature(self, post, prefix='fb_sig', timeout=None):
"""
Validate parameters passed to an internal Facebook app from Facebook.
"""
args = post.copy()
if prefix not in args:
return None
del args[prefix]
if timeout and '%s_time' % prefix in post and time.time() - float(post['%s_time' % prefix]) > timeout:
return None
args = dict([(key[len(prefix + '_'):], value) for key, value in args.items() if key.startswith(prefix)])
hash = self._hash_args(args)
if hash == post[prefix]:
return args
else:
return None
def validate_cookie_signature(self, cookies):
"""
Validate parameters passed by cookies, namely facebookconnect or js api.
"""
if not self.api_key in cookies.keys():
return None
sigkeys = []
params = dict()
for k in sorted(cookies.keys()):
if k.startswith(self.api_key+"_"):
sigkeys.append(k)
params[k.replace(self.api_key+"_","")] = cookies[k]
vals = ''.join(['%s=%s' % (x.replace(self.api_key+"_",""), cookies[x]) for x in sigkeys])
hasher = hashlib.md5(vals)
hasher.update(self.secret_key)
digest = hasher.hexdigest()
if digest == cookies[self.api_key]:
return params
else:
return False
class MainClass( Plugin.Plugin ):
'''Main plugin class
This plugins synchronizes Emesene with your Facebook life'''
description = _('Synchronize emesene with your Facebook status, profile picture and more!')
authors = { 'Mehdi Rejraji' : 'mehd36 at gmail dot com' }
website = ''
displayName = 'Facebook'
name = 'Facebook'
def __init__( self, controller, msn):
'''Contructor'''
Plugin.Plugin.__init__( self, controller, msn)
self.description = _('Synchronize emesene with your Facebook status, profile picture and more!')
self.authors = { 'Mehdi Rejraji' : 'mehd36 at gmail dot com' }
self.website = ''
self.displayName = 'Facebook'
self.name = 'Facebook'
self.controller = controller
self.config = controller.config
self.config.readPluginConfig(self.name)
self.dest_filename = os.path.join(paths.CONFIG_DIR, \
controller.config.getCurrentUser(), '')
facebookdir = os.path.join(self.dest_filename, \
'facebook', '')
if os.path.exists(facebookdir):
self.dest_filename = facebookdir
else:
os.mkdir(facebookdir)
if os.path.exists(facebookdir):
self.dest_filename = facebookdir
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
self.time = (self.config.getPluginValue \
(self.name, 'time', '0') == '1')
self.avatar = (self.config.getPluginValue \
(self.name, 'avatar', '1') == '1')
self.buttonconv = (self.config.getPluginValue \
(self.name, 'buttonconv', '0') == '1')
self.buttonhome = (self.config.getPluginValue \
(self.name, 'buttonhome', '1') == '1')
self.unread = (self.config.getPluginValue \
(self.name, 'unread', '1') == '1')
self.pokes = (self.config.getPluginValue \
(self.name, 'pokes', '0') == '1')
self.comments = (self.config.getPluginValue \
(self.name, 'comments', '1') == '1')
self.timechanged = False
api_key = '92d4a977a81ac68bb53fdb4dac115fd9'
secret_key = 'd51f6f904f0082684c899d4d511fe99b'
self.fb = Facebook(api_key, secret_key)
self.theme = controller.theme
self.doichangestatus = True
self.enabled = False
def start(self):
if self.enabled == False:
self.check()
## Add a button to the conversation windows if enabled
###Creates a new button with an encoded facebook icon
items = [('facebook-logo', '_Facebook', 0, 0, '')]
gtk.stock_add(items)
factory = gtk.IconFactory()
factory.add_default()
fbimageencoded = \
"""AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAcRoNUP2qk+Uhy\nqv9MdKv/Tnas/1F3rf9Sea3/VHqu/1V7rv9V
e67/VXqu/1N6rv9SeK3/T3et/011rP9Kc6v/R3Gq\n/0NuqP87ZqP5HEWDVAAAAA
AAAAAAAAAAAAAAAAA+aKP5SX/D/z53v/8+d77/Pne+/z52vv89dr7/\nPXa+/z12
vv89dr7/PXa+/z12vv8+dr7/Pna+/z53vv8+d77/P3e//z93v/9HfsP/OmWh+QAA
AAAA\nAAAAAAAAAAAAAABGcKj/PXS8/0B2vf9Adr3/QHa9/0B2vf9Adr3/QHa9/0
B2vf9Adr3/QHa9/z91\nvP9DeL7/g6bU/5u43f+bt9z/jq7Y/1yKx/8+dLz/Qmyn
/wAAAAAAAAAAAAAAAAAAAABJcaj/PHK4\n/z90uf8/dLn/P3S5/z90uf8/dLn/P3
S5/z90uf8/dLn/PnO5/3+i0P//////////////////////\n/////6G73f88crj/
RW6m/wAAAAAAAAAAAAAAAAAAAABKcaj/O3C1/z5ytv8+crb/PnK2/z5ytv8+\ncr
b/PnK2/z5ytv8+crb/S3u7///////+/v7//v7+/////////////////6G62/87cL
X/SG+n/wAA\nAAAAAAAAAAAAAAAAAABLcqf/OW2y/z1ws/89cLP/PXCz/z1ws/89
cLP/PXCz/z1ws/89cLP/j6zT\n/////////////////4Gjzv9AcrT/T326/1eDvf
85brL/SnGn/wAAAAAAAAAAAAAAAAAAAABMcqf/\nN2uv/ztusP87brD/O26w/ztu
sP87brD/O26w/zxvsP8uZKv/orrZ//7+/v///////f7+/yJcpv8v\nZav/Mmes/z
tusP83a6//S3Gn/wAAAAAAAAAAAAAAAAAAAABMcqb/Nmmr/zpsrf86bK3/Omyt/z
ps\nrf86bK3/Omyt/y5jqP//////////////////////////////////////1N/t
/zRoq/82aav/TXKm\n/wAAAAAAAAAAAAAAAAAAAABMcaX/NWeo/zlqqv85aqr/OW
qq/zlqqv85aqr/OWqq/yxhpf//////\n////////////////////////////////
z9vq/zNmqP80Z6j/TXKm/wAAAAAAAAAAAAAAAAAAAABL\ncKT/NGWl/zhop/84aK
f/OGin/zhop/84aKf/OGin/zFjpP+iudb/1d/s/////////////////5qy\n0v+e
ttT/hqPK/zVmpv8zZaX/TnOl/wAAAAAAAAAAAAAAAAAAAABJbqL/MmOi/zZmo/82
ZqP/Nmaj\n/zZmo/82ZqP/Nmaj/zZmo/80ZaP/qL3X/////////////////yxen/
82ZqT/Nmak/zZmpP8yY6L/\nTnKl/wAAAAAAAAAAAAAAAAAAAABHbaH/MmGf/zVk
of81ZKH/NWSh/zVkof81ZKH/NWSh/zVkof80\nY6D/qLzW/////////////////y
xdnP81ZKD/NWSg/zVkoP8xYZ//TXGj/wAAAAAAAAAAAAAAAAAA\nAABEap//MGCc
/zRinv80Yp7/NGKe/zRinv80Yp7/NGKe/zRinv8yYZ3/p7zV////////////////
\n/ypamf80Yp7/NGKe/zRinv8vX5z/S3Ci/wAAAAAAAAAAAAAAAAAAAABCaJz/L1
6Z/zJgm/8yYJv/\nMmCb/zJgm/8yYJv/MmCb/zJgm/8wX5r/p7vU////////////
/////ylYlv8yYJv/MmCb/zJgm/8u\nXZn/SW2g/wAAAAAAAAAAAAAAAAAAAAA+ZZ
r/K1mV/ytZlP8rWZT/K1mU/ytZlP8rWZT/K1mU/ytZ\nlP8pWJP/pLfR////////
/////////yFRj/8rWZT/K1mU/ytZlP8qWZT/Rmue/wAAAAAAAAAAAAAA\nAAAAAA
A6YZf/ZYWv/52yzP+dssz/nbLM/52yzP+dscz/nbHM/52xzP+cscz/1N3p//////
//////\n/////5etyf+cscz/nLHM/5yxzP9fga3/RGic/wAAAAAAAAAAAAAAAAAA
AAA2XZT/YYKs/5esyP+X\nrMj/l6zI/5esyP+XrMj/l6zI/5esyP+Wq8j/0tvn//
///////////////5Koxv+XrMj/l6zI/5es\nyP9cfqn/QGWZ/wAAAAAAAAAAAAAA
AgAAAAAyWpH/YIGq/5arxv+Vq8b/lavG/5Wrxv+Vq8b/lavG\n/5Wrxv+Vqsb/0d
vm/////////////////5GnxP+Vq8b/lavG/5asxv9bfaf/PGKW/wAAAAAAAAAC\n
AAAABQAAAAwqUov8Nl6R/19+p/9ffqf/Xn6n/15+p/9efab/XX2m/119pv9dfKb/
e5W2/5Gnw/+R\np8P/lanE/1t7pf9dfab/Xn2n/119pv83X5L/M1qQ/AAAAAwAAA
AFAAAACgAAACgSK0+NKlGK/DFa\nkv82XZX/OWCW/zximP8/ZZr/Qmeb/0NonP9E
aZ3/Rmqd/0Zrnf9Gap3/RGmc/0NonP9BZ5v/P2WZ\n/zximP8zWI/8EitQjQAAAC
gAAAAKAAAACAAAACIAAABIAAAAWwAAAGIAAABjAAAAYwAAAGMAAABj\nAAAAYwAA
AGMAAABjAAAAYwAAAGMAAABjAAAAYwAAAGMAAABjAAAAYwAAAGIAAABbAAAASAAA
ACIA\nAAAIAAAAAwAAAA0AAAAcAAAAJgAAACkAAAApAAAAKQAAACkAAAApAAAAKQ
AAACkAAAApAAAAKQAA\nACkAAAApAAAAKQAAACkAAAApAAAAKQAAACkAAAAmAAAA
HAAAAA0AAAADAAAAAAAAAAIAAAAFAAAA\nBgAAAAYAAAAHAAAABwAAAAcAAAAHAA
AABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAH\nAAAABwAAAAYAAAAG
AAAABQAAAAIAAAAA\n
"""
fbimage = base64.decodestring(fbimageencoded)
pixbuf = gtk.gdk.pixbuf_new_from_data(fbimage, gtk.gdk.COLORSPACE_RGB, True, 8, 24, 24, 96)
icon_set = gtk.IconSet(pixbuf)
factory.add('facebook-logo', icon_set)
if self.unread:
self.addunread()
self.unreadid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.unreadcheck)
self.unreadid.start()
if self.pokes:
self.addpokes()
self.pokesid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.pokescheck)
self.pokesid.start()
self.controller.mainWindow.userPanel.vbox2h1.show_all()
##Adds a button to the conversation manager if enabled
if self.buttonconv:
for conversation in self.getOpenConversations():
self.addbuttonconv(conversation=conversation)
self.buttonadded = self.controller.conversationManager.connect_after('new-conversation-ui',
self.addbuttonconv)
self.buttonremove = self.controller.conversationManager.connect('close-conversation-ui',
self.removebuttonconv)
self.hbox = gtk.HBox()
if self.buttonhome:
self.addbuttonhome()
##Check for a new personal image if enabled
if self.avatar:
self.setavatar()
self.enabled = True
##Check for a new status if enabled, and starts the timer
if self.status == '1':
self.checkstatus()
self.timeout = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.checkstatus)
self.timeout.start()
if self.config.getPluginValue(self.name, 'comments','1') == '1':
self.commentsbutton()
self.commentsid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.commentscheck)
self.commentsid.start()
self.controller.mainWindow.userPanel.vbox2h2.pack_start(self.hbox,True,False)
self.hbox.show_all()
self.msn.connect( 'self-personal-message-changed', self.changestatus )
def getcomments(self):
comment_id = self.config.getPluginValue(self.name, 'uid', '')+'_'+self.config.getPluginValue(self.name, 'status_id', '')
count = len(self.fb.fql.query('SELECT "" FROM comment WHERE post_id="'+ comment_id +'"'))
if self.config.getPluginValue(self.name, 'commentscounted', '') != str(count):
brutcomments = self.fb.stream.getComments(comment_id)
self.uids = []
for x in brutcomments:
if ((str(x['fromid']) in self.config.getPluginValue(self.name, 'uids', '')) == False) and ((str(x['fromid']) in self.uids) == False):
urlimage = (self.fb.users.getInfo(str(x['fromid']), ['pic_square'])[0])['pic_square']
if urlimage != None:
urllib.urlretrieve(urlimage, self.dest_filename + str(x['fromid']) + '.jpg')
else:
urllib.urlretrieve('http://static.ak.fbcdn.net/pics/q_silhouette_logo.gif', self.dest_filename + str(x['fromid']) + '.jpg')
self.uids.append(str(x['fromid']))
names = self.fb.users.getInfo(self.uids,'name')
nameslist = []
for x in names:
nameslist.append(x['name'])
def nub(inpt):
seen = set()
out = []
for item in inpt:
if item not in seen:
seen.add(item)
out.append(item)
return out
ids = nub(self.uids)
namesref = {}
for x,y in zip(nameslist,ids):
name = (x)+' :'
namesref[y] = name
self.authors = []
self.commenttexts = []
for x in brutcomments:
text = x['text']
name = namesref[str(x['fromid'])]
self.authors.append(name)
self.commenttexts.append(text)
self.config.setPluginValue(self.name, 'authors', self.authors)
self.config.setPluginValue(self.name, 'commenttexts', self.commenttexts)
self.config.setPluginValue(self.name, 'uids', self.uids)
else:
self.authors = eval(self.config.getPluginValue(self.name, 'authors', ''))
self.commenttexts = eval(self.config.getPluginValue(self.name, 'commenttexts', ''))
self.uids = eval(self.config.getPluginValue(self.name, 'uids', ''))
self.config.setPluginValue(self.name, 'commentscounted', str(count))
try:
self.commentsgetone.cancel()
except:
''
try:
self.commentsgettwo.cancel()
except:
''
def addcomments(self, fbcomments):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("destroy", gtk.main_quit)
window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
window.set_title(_('Comments'))
window.resize(500, 350)
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
scrolled_window.set_border_width(5)
box = gtk.VBox(False, 0)
statusMessageLabel = gtk.Label(self.config.getPluginValue(self.name, 'currentstatus', ''))
statusMessageLabel.set_markup('<b>'+statusMessageLabel.get_text()+'</b>')
separatorLabel = gtk.Label("--------------------------------------------------------------------------------------------")
separatorLabel.set_markup('<big>'+separatorLabel.get_text()+'</big>')
box.pack_start(statusMessageLabel, False, False, 0)
box.pack_start(separatorLabel, False, False, 0)
scrolled_window.add_with_viewport(box)
window.add(scrolled_window)
self.getcomments()
size = len(self.authors)
for x in range(0,size):
commentBox = gtk.EventBox()
commentBox.set_border_width(2)
if not(x%2): #this check if the comment is odd
commentBox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(62708,62708,45489,0))
contactImage = gtk.Image()
contactImage.set_from_file(self.dest_filename+str(self.uids[x])+'.jpg')
contactImage.set_alignment(0,0)
authorLabel = gtk.Label(self.authors[x])
authorLabel.set_alignment(0, 0)
authorLabel.set_markup('<u><b>'+authorLabel.get_text()+'</b></u>')
commentLabel = gtk.Label(self.commenttexts[x])
commentLabel.set_alignment(0, 0)
commentLabel.set_line_wrap(True)
HorBox = gtk.HBox(False, 20)
HorBox.pack_start(contactImage, False, False, 0)
HorBox.set_border_width(5)
VerBox = gtk.VBox(False, 0)
VerBox.pack_start(authorLabel, False, False, 0)
VerBox.pack_start(commentLabel,True, True, 0)
HorBox.pack_start(VerBox, True, True, 0)
commentBox.add(HorBox)
box.add(commentBox)
window.show_all()
gtk.main()
def commentsbutton(self):
fbimageencoded = \
"""R5YOAEaWDQBGlgwARZUMAEWWDQBFlg0ARZYNAEWWDQBFlg0ARZYNAEWWDQBFlg0A
RZYNAEWWDQBF\nlg0ARZYNAEWWDQBFlg0ARZYNAEWWDQBFlQwARpYMAEaWDQBHlg
4ARZUMAEaWDABOmxYAZKcuAGao\nMQBmqDAAZqgxAGaoMQBmqDEAZqgxAGaoMQBm
qDEAZqgxAGaoMQBmqDEAZqgxAGaoMQBmqDEAZqgw\nAGaoMQBkpy4ATpsWAEaWDA
BFlQwARZUMAEaWDQB1sEIAlsNmAJbCZgCXw2cAl8NnAJfDZgCXw2YA\nl8NnAJfD
ZwCXw2cAl8NmAJfDZgCXw2YAl8NmAJfDZgCXw2YAl8NnAJbCZgCWw2YAdbBCAEaW
DQBF\nlQwARZUMAEeXDgCBtk4AksBiAJLAYQCRv2AAkb9gAJLAYQCSwGEAksBhAJ
G/YACRwGAAk8FiAJLA\nYQCSwGEAksBhAJLAYQCSwGEAksBhAJLAYQCSwGIAgbZO
AEeXDgBFlQwARZUMAEaWDgCAtk0Ak8Fi\nAEaWDENIlw/fSZgR/kmYEf9JmBH+SZ
gR/0mYEf9JmBH/SZgR/0mYEf9JmBH/SZgR/kmYEf9JmBH+\nSJcP30aWDEOTwWIA
gLZNAEaWDgBFlQwARZUMAEeWDgCAtk0Akb9gAEqYEe95s0b/hrlV/oe6Vf6H\nul
X/h7pV/4e6Vf+Hulb/h7pV/4e6Vf+HulX/h7pV/4e6Vf6GuVX+ebNG/0qYEe+TwW
IAgLZNAEeW\nDgBFlQwARZUMAEeWDgB+tUsAlsJmAE6bFv6OvV3+kb9h/5C+X/+R
v2D+kb9g/5G/YP+Qv1//ksBh\n/5G/YP+Rv2D/kb9g/pG/YP+Rv2H/jr1d/k6bFv
6TwWMAgLZNAEeWDgBFlQwARZUMAEaWDgB+tUoA\nsdGNAE6aFv+NvVv+kcBg/q/R
jP+Xw2n/kL5e/6nMgf+fxnT/kb9f/5PBYv+TwWL/k8Fi/5PBYv+S\nwGH+jr5c/k
6aFv+TwGEAgLZNAEaWDgBFlQwARZUMAEaWDQCAtk4AzuK3AE6aFv6Ju1b/y+G1/9
7s\n0P+Vwmb/ncZy/+vz4v+jyXr/kb9g/5PBYv+TwWL/ksBh/5PBYv+TwWL/jr5d
/06aFv6axGwAfrZL\nAEeWDgBFlQwARZUMAEaWDQCBt08A1ufDAEyZFf+exnP///
///7fUl/+Dt0v/3+zS/97sz/+TwGP/\nkcBg/5bCZ/+SwGH/kcBg/5TBZP+Wwmf/
jb1b/02aFv/I364AgLZNAEaWDQBFlQwARZUMAEaWDgB/\ntUsAtNORAE2ZFP+z05
L//v7+/+Tv2P+TwGL/9vny//7+/v+lyn3/pMp7//X48f/X58b/kL9e/93r\n0P/v
9uj/oMh2/02ZFP/W6MMAgbdPAEaWDQBFlQwARZUMAEeWDgB/tk0AlMJkAE2ZFf+a
xG3/8ffr\n/9rqy/+NvVv/zeK3//T48P+hyHb/osl5//r8+P/z9+3/ksBh/+Ht0/
/9/v3/stOR/02ZFP/F3aoA\nf7ZMAEaWDgBFlQwARZUMAEeWDgCAtk0Ak8FiAE6a
Fv+NvVv/kL9e/5C/X/+SwGH/kL5e/5C/Xv+S\nwGD/k8Bj/97s0P/a6cj/g7hM/7
fUl///////msVu/02ZFf+iynkAfbRJAEeWDgBFlQwARZUMAEeW\nDgCAtk0Ak8Fi
AE6aFv6Ovlz/ksFh/5LAYf+SwGL/ksBh/5PBYv+Qvl//qc2D/+z05f+WwWf/mMRr
\n/+ny3/+82Z//irtX/06aFv6SwGEAgLZNAEeWDgBFlQwARZUMAEaWDgCAtk0Ak8
FjAE6aFv6OvV3+\nksBh/5LAYf6TwWL/k8Fi/5LAYf+SwGD/ncZx/6DId/+RwGD/
l8Jo/6jMgv6PvVz/jr5c/k6aFv6T\nwWEAgLZNAEaWDgBFlQwARZUMAEeWDgCBtk
0Ak8BiAE6aFv+Pvl3+ksBh/pPBYv+SwGH/ksBh/5G/\nYP+TwWL+ksBh/5LAYf+T
wWL/k8Bi/5LAYP+SwGH+j75e/k6aFv+TwGIAgbZNAEeWDgBFlQwARZUM\nAEaWDg
B/tk0Ak8FiAEmYEOt2sEL/hLhS/4W4U/+Pvl7+ksBh/pPAYv6KvFn/hLhR/4S4Uv
+EuFL/\nhLhS/4S4Uv+EuFL/drBC/0mYEOuTwWIAf7ZNAEaWDgBFlQwARZUMAEaW
DABmqDAAirxZAEWVDD1G\nlQ2xSJgQu0uYEu+GuFP+l8Nn/nuzR/9Qmxj/SJcPuE
iXEL1IlxC9SJcQvUiXEL1IlxC9RpUNsUWV\nDD2KvFkAZqgwAEaWDABFlQwARpYN
AEaWDQBHlg8AUZwZAFOeHABElAoBaqo0AEqXEMKJu1f/aak0\n/kWVDPBElQtKU5
4bAEOUCgFDlAoBQ5QKAUOUCgFDlAoBRJQLAVOeHABRnBkAR5YPAEaWDQBGlg0A\n
AAAAAEeXDgBFlQwARZUMAESVCwBCkwcASZYQAkiXEMZRnBn/QJIHv0OUCi5FlgwA
RZULAESVCwBE\nlQsARJULAESVCwBElQsARJULAESVCwBFlQwARZUMAEeXDgAAAA
AAR5cOAAAAAAAAAAAAAAAAAEmW\nEQBBkwcARZUMAUWVDKdElAtqRZUMCUSVCwBG
lg0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAA
BHlw4AAAAAAAAAAAAAAAAAAAAAAEaVDQBDlAoAWKAhAF2iJgBFlQwA\nRJULAEeW
DgAAAAAAAAAAAEeXDgAAAAAAAAAAAAAAAAAAAAAARpYNAAAAAABGlg0AAAAAAAAA
AAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAEaWDQBGlg0ARpYNAEWVDABFlQwAR5YOAA
AAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAEaWDQBGlg0ARpYNAEWVDABGnA0AAA
AAAC5+AABHlw4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA\n
"""
fbimage = base64.decodestring(fbimageencoded)
commentsicon = gtk.gdk.pixbuf_new_from_data(fbimage, gtk.gdk.COLORSPACE_RGB, True, 8, 24, 24, 96)
self.fbcomments = ImageButton(commentsicon,'(0)')
self.fbcomments.set_relief(gtk.RELIEF_NONE)
self.fbcomments.connect('clicked',self.addcomments)
self.fbcomments.set_tooltip_text(_("My current Facebook status' comments"))
if self.config.getPluginValue(self.name, 'statusprinted', '') != '':
comment_id = self.config.getPluginValue(self.name, 'uid', '')+'_'+self.config.getPluginValue(self.name, 'status_id', '')
count = len(self.fb.fql.query('SELECT "" FROM comment WHERE post_id="'+ comment_id +'"'))
else:
count = '0'
if str(count) != '0' and self.config.getPluginValue(self.name, 'statusprinted', '') != '':
self.fbcomments.setText('('+str(count)+')')
self.hbox.pack_start(self.fbcomments, True, False)
self.commentsactive = True
else:
self.commentsactive = False
def addbuttonhome(self):
self.fbbuttonmain = gtk.ToolButton()
self.fbbuttonmain.set_label('Facebook')
self.fbbuttonmain.set_stock_id('facebook-logo')
self.fbbuttonmain.connect('clicked',self.gofacebook)
self.fbbuttonmain.set_tooltip_text(_("Go to your Facebook homepage"))
self.hbox.pack_end(self.fbbuttonmain,True,False)
def addpokes(self):
pkcount = (self.fb.notifications.get()['pokes'])['unread']
iconPoke = self.theme.getSmiley("(y)") #poke icon
self.fbpk = ImageButton(iconPoke, '(0)')
self.fbpk.set_relief(gtk.RELIEF_NONE)
self.fbpk.connect('clicked', self.gofacebook)
self.fbpk.setText('(' + str(pkcount) + ')')
self.fbpk.set_tooltip_text(_("Facebook - %s unread poke(s)") % str(pkcount))
if str(pkcount) != '0':
self.controller.mainWindow.userPanel.vbox2h1.pack_start(self.fbpk, True, False)
self.pokesactive = True
else:
self.pokesactive = False
def addunread(self):
fbmailencoded = \
"""RoPEAEaDxABGgsMARoLDAEaCwwBGgsMARoLDAEaCwwBGgsMARoLDAEaCwwBGgsMA
RoLDAEaCwwBG\ngsMARoLDAEaCwwBGgsMARoLDAEaCwwBGgsMARoLDAEaCwwBGgs
MARoPEAEaCwwBGgsMARoLDAEaC\nwwBGgsMARoLDAEaCwwBGgsMARoLDAEaCwwBG
gsMARoLDAEaCwwBGgsMARoLDAEaCwwBGgsMARoLD\nAEaCwwBGgsMARoLDAEaCww
BGgsMARoLDAEaCwwBVmMkAc6DQAHOg0ABzoNAAc6DQAHOg0ABzoNAA\nc6DQAHOg
0ABzoNAAc6DQAHOg0ABzoNAAc6DQAHOg0ABzoNAAc6DQAHOg0ABzoNAAVZjJAEaC
wwBG\ngsMARoLDAKTC4AD///8A////AP///wD///8A////AP///wD///8A////AP
///wD///8A////AP//\n/wD///8A////AP///wD///8A////AP///wD///8A////
AKTC4ABGgsMARoLDAP///wD///8A////\nAP///wD///8A////AP///wD///8A//
//AP///wD///8A////AP///wD///8A////AP///wD///8A\n////AP///wD///8A
////AP///wBCf74ARoLDAP///wD///8A/v7+IlJ1xf9SdcX/UnXF/1J1xf9S\ndc
X/UnXF/1J1xf9SdcX/UnXF/1J1xf9SdcX/UnXF/1J1xf9SdcX/UnXF/1J1xf////
8i////AP//\n/wBCf74ARoLDAP///wD///8AUnXF//////3//////////+70+f/g
6/T/4ev0/+Hr9P/h6/T/4ev0\n/+Hr9P/h6/T/4ez0/9zp8////v7///////////
1SdcX/////AP///wBCf74ARoLDAP///wD///8A\nUnXF//f6/P/4+vz//////+Tt
9v9bfMj/bInO/2qIzf9qiM3/aojN/2qIzf9sic7/ZIPL/7rO3///\n//////////
///v9SdcX/////AP///wBCf74ARoLDAP///wD///8AUnXF/9bj8v+Tt9v//Pz9//
//\n//+gwOD/WoLI/1t8yP9bfMj/W3zI/1t8yP9XeMf/aIfN//38+/////7/xdjk
/9vq8/9SdcX/////\nAP///wBCf74AQn++AP///wD///8AUnXF/9Ph8f9SdcX/bY
rO//n5+v/8/Pv/ts7f/2B/yv9bfMj/\nXn7J/1t8yP92kdH/7fP5//////+70ej/
UnXF/9Lh8f9SdcX/////AP///wBCf74ARoLDAP///wD/\n//8AUnXF/9Ph8f9Uds
b/W3zI/1t8yP///////////8HW6f9nhcz/YH/K/5y73P/2+fz//////5e5\n3P9U
dsb/VHbG/9Ph8f9SdcX/////AP///wBCf74AQn++AP///wD///8AUnXF/9Ph8f9U
dsb/Xn7J\n/1x9yP+xy+X/8/f7///////P3u7/q83i///++f////7/2Ofv/1h5x/
9efsn/VHbG/9Ph8f9SdcX/\n////AP///wBCf74AQn++AP///wD///8AUnXF/9Ph
8f9Udsb/Xn7J/1t8yP9bfMj/lbnc//D0+P//\n//////////////+7z+X/Z4XM/1
x9yP9efsn/VHbG/9Ph8f9SdcX/////AP///wBCf74AQn++AP//\n/wD///8AUnXF
/9Ph8f9Vd8b/Xn7J/15+yf9efsn/XH3I/3ic0//s7ez//////5283v9gf8r/XH3I
\n/15+yf9efsn/VXfG/9Ph8f9SdcX/////AP///wBCf74ALHu3AP///wD///8AUn
XF/8zg7v9IbMH/\nT3LE/09yxP9PcsT/T3LE/09yxP9ll87/c6zS/01xw/9PcsT/
T3LE/09yxP9PcsT/SGzB/8zg7v9S\ndcX/////AP///wAse7cAKH+5AP///wD///
8AUnXF/8vg7v9EasD/T3LE/09yxP9PcsT/T3LE/09y\nxP9NccP/THDD/09yxP9P
csT/T3LE/09yxP9PcsT/RGrA/8vg7v9SdcX/////AP///wAWebMAFnmz\nAP///w
D///8AUnXF/8vi7/1NccP/V3jH/1d4x/9XeMf/V3jH/1d4x/9XeMf/V3jH/1d4x/
9XeMf/\nV3jH/1d4x/9XeMf/TXHD/8zi7/9SdcX/////AP///wAWebMAFnmzAP//
/wD///8AUnXF/1J1xf/Y\n5/L92unz/9rp8//a6fP/2unz/9rp8//a6fP/2unz/9
rp8//a6fP/2unz/9rp8//a6fP/2Ojy/1J1\nxf9SdcX/////AP///wAWebMAFnmz
AP///wD///8A////AFJ1xf9SdcX/UnXF/1J1xf9SdcX/UnXF\n/1J1xf9SdcX/Un
XF/1J1xf9SdcX/UnXF/1J1xf9SdcX/UnXF/1J1xf/+/v4j////AP///wAFc6oA\n
CHixAJG42gD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
////AP///wD/\n//8A////AP///wD///8A////AP///wD///8A////AJG42gAFc6
oACHixAAh4sQAof7kARZS8AEWU\nvABFlLwARZS8AEWUvABFlLwARZS8AEWUvABF
lLwARZS8AEWUvABFlLwARZS8AEWUvABFlLwARZS8\nAEWUvABFlLwAKH+5AAVzqg
AFc6oACHixAAh4sQAIeLEABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oA\nBXOqAAVz
qgAFc6oABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oABXOqAAVz
qgAF\nc6oAA3ixAAN4sQADeLEABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oABXOqAA
VzqgAFc6oABXOqAAVz\nqgAFc6oABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oABXOq
AAVzqgAFc6oAA3ixAAN4sQADeLEAA3ix\nAAVzqgAFc6oABXOqAAVzqgAFc6oABX
OqAAVzqgAFc6oABXOqAAVzqgAFc6oABXOqAAVzqgAFc6oA\nBXOqAAVzqgAFc6oA
BXOqAAVzqgADeLEA\n
"""
fbmail = base64.decodestring(fbmailencoded)
fbpmpixbuf = gtk.gdk.pixbuf_new_from_data(fbmail, gtk.gdk.COLORSPACE_RGB, True, 8, 24, 24, 96)
pmcount = (self.fb.notifications.get()['messages'])['unread']
self.fbpm = ImageButton(fbpmpixbuf, '(0)')
self.fbpm.set_relief(gtk.RELIEF_NONE)
self.fbpm.connect('clicked', self.gofacebookinbox)
self.fbpm.setText('(' + str(pmcount) + ')')
self.fbpm.set_tooltip_text(_("Facebook - %s unread message(s)") % str(pmcount))
if str(pmcount) != '0':
self.controller.mainWindow.userPanel.vbox2h1.pack_start(self.fbpm, True, False)
self.unreadactive = True
else:
self.unreadactive = False
def addbuttonconv(self, conversationManager=None, conversation=None, window=None):
'''This function adds a button. If clicked, it calls gofacebook'''
self.fbbutton = gtk.ToolButton()
self.fbbutton.set_label(_('Facebook'))
self.fbbutton.set_stock_id('facebook-logo')
self.fbbutton.connect('clicked',self.gofacebook)
self.fbbutton.set_tooltip_text(_("Go to your Facebook homepage"))
self.fbbutton.show()
conversation.ui.input.toolbar.add(self.fbbutton)
conversation.ui.input.toolbar.insert(gtk.SeparatorToolItem(), -1)
def removebuttonconv(self, conversationManager=None, conversation=None, window=None):
for button in conversation.ui.input.toolbar.get_children():
conversation.ui.input.toolbar.remove(self.fbbutton)
self.fbbutton.destroy()
def gofacebook(self, fbbutton):
'''Opens a new tab (if any) and goes to facebook'''
desktop.open('http://www.facebook.com/home.php')
def gofacebookinbox(self, fbpm):
'''Opens a new tab (if any) and goes to facebook'''
desktop.open('http://www.facebook.com/inbox/')
def stop(self):
'''This is called when the plugin is stopped'''
##Removes the status checking if enabled
if self.status == '1':
self.timeout.cancel()
if self.pokes:
self.pokesid.cancel()
if self.comments:
self.commentsid.cancel()
if self.unread:
self.unreadid.cancel()
##Removes buttons from conversation if exists
if self.buttonconv:
self.controller.conversationManager.disconnect(self.buttonremove)
self.controller.conversationManager.disconnect(self.buttonadded)
for conversation in self.getOpenConversations():
self.removebuttonconv(conversation=conversation)
##Removes buttons from homepage if exists
if self.buttonhome:
self.fbbuttonmain.destroy()
if self.unread and self.unreadactive == True :
self.fbpm.destroy()
if self.pokes and self.pokesactive == True :
self.fbpk.destroy()
if self.comments and self.commentsactive == True:
self.fbcomments.destroy()
self.enabled = False
def check(self):
'''This part is used for checkings before the plugin to be started'''
api_key = '92d4a977a81ac68bb53fdb4dac115fd9'
secret_key = 'd51f6f904f0082684c899d4d511fe99b'
self.fb = Facebook(api_key, secret_key)
if self.config.getPluginValue(self.name, 'expires', '') == '0' :
self.fb.session_key = self.config.getPluginValue(self.name, 'session_key', '')
self.fb.secret = self.config.getPluginValue(self.name, 'secret', '')
self.fbreturn = True
## If it expires, get a new auth :
else:
if self.config.getPluginValue(self.name, 'session_key', '') != '':
uidgotten = str(self.fb.users.getLoggedInUser())
updatestatus = self.fb.users.hasAppPermission("status_update",uidgotten)
else:
uidgotten = '00'
updatestatus = '00'
if uidgotten == self.config.getPluginValue(self.name, 'uid','') and str(updatestatus) == '1':
self.auth = self.fb.auth.getSession()
self.config.setPluginValue( self.name, 'session_key', self.auth['session_key'] )
self.config.setPluginValue( self.name, 'secret', self.auth['secret'] )
self.config.setPluginValue( self.name, 'expires', str(self.auth['expires']) )
else:
self.fb.auth.createToken()
self.fb.login(popup=True)
def authbox():
mdone = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK_CANCEL, _('Please login on Facebook (just opened in your browser). Check the box "Keep me logged in to Emesene Plugin". Then you can valid.'))
response = mdone.run()
mdone.destroy()
if response == gtk.RESPONSE_OK:
try:
self.auth = self.fb.auth.getSession()
self.config.setPluginValue( self.name, 'session_key', self.auth['session_key'] )
self.config.setPluginValue( self.name, 'secret', self.auth['secret'] )
self.config.setPluginValue( self.name, 'uid', self.auth['uid'] )
self.config.setPluginValue( self.name, 'expires', str(self.auth['expires']) )
self.fb.request_extended_permission('status_update', popup=False)
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_YES_NO, _("Now, you can authorize the plugin to update your Facebook status. If you say yes, your Facebook status and your Emesene personal message will be synchronized"))
answer = md.run()
## If the user said yes, ask facebook if the user hasAppPermission, if not, status disabled
if answer == gtk.RESPONSE_YES:
updatestatus = self.fb.users.hasAppPermission("status_update",self.config.getPluginValue(self.name, 'uid',''))
if str(updatestatus) == '1':
self.config.setPluginValue( self.name, 'status', '1' )
else:
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK, _("You don't have the permission to update your Facebook status with this plugin. The status synchronization option has been disabled, but you can still enable it in the plugin properties."))
md.run()
md.destroy()
self.config.setPluginValue( self.name, 'status', '0' )
else:
self.config.setPluginValue( self.name, 'status', '0' )
md.destroy()
self.fbreturn = True
self.enabled = True
except:
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK, _("The authentication process didn't work. Please try again"))
md.run()
md.destroy()
self.fb.auth.createToken()
self.fb.login(popup=True)
authbox()
else:
self.fbreturn = False
authbox()
if self.fbreturn == True:
return (True, 'Ok')
else:
return (False, _('As you cancelled, this plugin was disabled. But you can enable it in the plugins list.'))
def configure(self):
'''Display a configuration dialog'''
l = []
##STATUS SYNCHRONIZATION##
l.append(Plugin.Option('', gtk.Widget, '', '', gtk.Label(_("[ Facebook synchronization ]"))))
l.append(Plugin.Option('status', bool, \
_('Synchronize my Facebook status and my Emesene personal message'), '', self.config.\
getPluginValue(self.name, 'status', '1') == '1'))
l.append(Plugin.Option('avatar', bool, \
_('Update my Emesene avatar from my Facebook profile image (on every startup)'), '', self.config.\
getPluginValue(self.name, 'avatar', '1') == '1'))
##STATUS DISPLAY
l.append(Plugin.Option('', gtk.Widget, '', '', gtk.Label(_("[ Status display ]"))))
l.append(Plugin.Option('prefix', str, _("Custom status prefix (can be blank):"), '',\
self.config.getPluginValue( self.name, 'prefix', '' )) )
l.append(Plugin.Option('suffix', str, _("Custom status suffix (can be blank):"), '',\
self.config.getPluginValue( self.name, 'suffix', '' )) )
l.append(Plugin.Option('time', bool, \
_('Show time (default is messages such as "2 hours ago")'), '', self.config.\
getPluginValue(self.name, 'time', '0') == '1'))
l.append(Plugin.Option('format', str, _("Custom time (example: \'%(q)sx, %(q)sX\'):") % {'q': '%'}, '',\
self.config.getPluginValue( self.name, 'format', '' )) )
l.append(Plugin.Option('separator', list, _('Time separator'), '',
self.config.getPluginValue\
( self.name, 'separator', '[Time]' ), ['[Time]', '(Time)', '-- Time', 'Time' ]))
##MISC
l.append(Plugin.Option('', gtk.Widget, '', '', gtk.Label(_("[ Miscellaneous ]"))))
l.append(Plugin.Option('checktime', str, _('Check for Facebook every [sec]:'), '',\
self.config.getPluginValue( self.name, 'checktime', '30' )) )
l.append(Plugin.Option('confirmation', bool, \
_('Display a confirmation box before my Facebook status to be updated'), '', self.config.\
getPluginValue(self.name, 'confirmation', '1') == '1'))
l.append(Plugin.Option('buttonhome', bool, \
_('Add a "Facebook Homepage" button to the main window'), '', self.config.\
getPluginValue(self.name, 'buttonhome', '1') == '1'))
l.append(Plugin.Option('buttonconv', bool, \
_('Add a "Facebook Homepage" button to each conversation windows'), '', self.config.\
getPluginValue(self.name, 'buttonconv', '0') == '1'))
l.append(Plugin.Option('unread', bool, \
_('Notify for unread messages on the main window'), '', self.config.\
getPluginValue(self.name, 'unread', '1') == '1'))
l.append(Plugin.Option('pokes', bool, \
_('Notify for unread pokes on the main window'), '', self.config.\
getPluginValue(self.name, 'pokes', '0') == '1'))
l.append(Plugin.Option('comments', bool, \
_('Display comments for my current Facebook status'), '', self.config.\
getPluginValue(self.name, 'comments', '1') == '1'))
response = Plugin.ConfigWindow(_('Facebook Plugin'), l).run()
## If the user didn't cancel :
if response != None:
## Used for the plugin not to ask for a fb update if the user sets time display
self.timechanged = False
##Sets the new checktimetime, if it has changed
if self.config.getPluginValue(self.name, 'checktime', '30') != str(int(response['checktime'].value)):
self.config.setPluginValue(self.name, 'checktime', str(int(response['checktime'].value)))
self.timeout.cancel()
self.timeout = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.checkstatus)
self.timeout.start()
if self.config.getPluginValue(self.name, 'confirmation', '1') != str(int(response['confirmation'].value)):
self.config.setPluginValue(self.name, 'confirmation', str(int(response['confirmation'].value)))
if self.config.getPluginValue(self.name, 'comments', '1') != str(int(response['comments'].value)):
self.config.setPluginValue(self.name, 'comments', str(int(response['comments'].value)))
if self.config.getPluginValue(self.name, 'comments', '1') == '1':
self.config.setPluginValue( self.name, 'comments', '1' )
self.commentsid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.commentscheck)
self.commentsid.start()
self.commentsbutton()
self.hbox.show_all()
else:
self.fbcomments.destroy()
self.commentsid.cancel()
##Sets the new status value
if str(int(response['status'].value)) == '1':
if self.config.getPluginValue(self.name, 'status', '1') == '0':
updatestatus = self.fb.users.hasAppPermission("status_update",self.config.getPluginValue(self.name, 'uid',''))
if str(updatestatus) != '1':
self.fb.request_extended_permission("status_update", popup=True)
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_YES_NO, _("Now, you can authorize the plugin to update your Facebook status. If you say yes, your Facebook status and your Emesene personal message will be synchronized"))
answer = md.run()
md.destroy()
if answer == gtk.RESPONSE_YES:
updatestatus = self.fb.users.hasAppPermission("status_update",self.config.getPluginValue(self.name, 'uid',''))
if str(updatestatus) == '1':
self.config.setPluginValue( self.name, 'status', '1' )
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
self.checkstatus()
self.timeout = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.checkstatus)
self.timeout.start()
else:
self.config.setPluginValue( self.name, 'status', '0' )
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK, _("You don't have the permission to update your Facebook status with this plugin. The status synchronization option has been disabled, but you can still enable it in the plugin properties."))
md.run()
md.destroy()
else:
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
self.config.setPluginValue( self.name, 'status', '0' )
else:
self.config.setPluginValue( self.name, 'status', '1' )
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
self.checkstatus()
self.timeout = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.checkstatus)
self.timeout.start()
else:
self.config.setPluginValue(self.name, 'status', str(int(response['status'].value)))
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
if self.config.getPluginValue(self.name, 'time', '0') != str(int(response['time'].value)):
self.timechanged = True
self.config.setPluginValue(self.name, 'time', str(int(response['time'].value)))
self.time = (self.config.getPluginValue \
(self.name, 'time', '0') == '1')
self.checkstatus()
else:
if self.config.getPluginValue(self.name, 'status', '1') == '1':
try:
self.timeout.cancel()
self.fbcomments.destroy()
self.commentsid.cancel()
except:
""
self.config.setPluginValue(self.name, 'time', '0')
self.config.setPluginValue(self.name, 'comments', '0')
self.time = (self.config.getPluginValue \
(self.name, 'time', '0') == '1')
self.config.setPluginValue(self.name, 'status', str(int(response['status'].value)))
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
self.config.setPluginValue(self.name, 'status', str(int(response['status'].value)))
self.status = self.config.getPluginValue \
(self.name, 'status', '1')
if self.config.getPluginValue(self.name, 'separator', '[Time]') != str(response['separator'].value):
self.config.setPluginValue(self.name, 'separator', str(response['separator'].value))
if self.config.getPluginValue(self.name, 'time', '0') == '1':
self.timechanged = True
self.checkstatus()
if self.config.getPluginValue(self.name, 'prefix', '') != str(response['prefix'].value):
self.config.setPluginValue(self.name, 'prefix', str(response['prefix'].value))
self.timechanged = True
self.checkstatus()
if self.config.getPluginValue(self.name, 'suffix', '') != str(response['suffix'].value):
self.config.setPluginValue(self.name, 'suffix', str(response['suffix'].value))
self.timechanged = True
self.checkstatus()
if self.config.getPluginValue(self.name, 'format', '') != str(response['format'].value):
self.config.setPluginValue(self.name, 'format', str(response['format'].value))
if self.config.getPluginValue(self.name, 'time', '0') == '1':
self.timechanged = True
self.checkstatus()
##AVATAR
if str(int(response['avatar'].value)) == '1' and self.config.getPluginValue(self.name, 'avatar', '1') == '0' :
self.setavatar()
self.config.setPluginValue(self.name, 'avatar', str(int(response['avatar'].value)))
self.avatar = (self.config.getPluginValue \
(self.name, 'avatar', '1') == '1')
##BUTTON
## If the "buttonconv" value changed, set the new value and add the button if it was disabled,
## or remove the button if it was enabled.
if self.config.getPluginValue(self.name, 'buttonhome', '1') != str(int(response['buttonhome'].value)):
self.config.setPluginValue(self.name, 'buttonhome', str(int(response['buttonhome'].value)))
if self.config.getPluginValue(self.name, 'buttonhome', '1') == '1':
self.addbuttonhome()
self.hbox.show_all()
else:
self.fbbuttonmain.destroy()
if self.config.getPluginValue(self.name, 'unread', '1') != str(int(response['unread'].value)):
self.config.setPluginValue(self.name, 'unread', str(int(response['unread'].value)))
if self.config.getPluginValue(self.name, 'unread', '1') == '1':
self.unreadid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.unreadcheck)
self.unreadid.start()
self.addunread()
self.controller.mainWindow.userPanel.vbox2h1.show_all()
self.unreadcheck()
else:
self.fbpm.destroy()
self.unreadid.cancel()
if self.config.getPluginValue(self.name, 'pokes', '0') != str(int(response['pokes'].value)):
self.config.setPluginValue(self.name, 'pokes', str(int(response['pokes'].value)))
if self.config.getPluginValue(self.name, 'pokes', '0') == '1':
self.pokesid = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.pokescheck)
self.pokesid.start()
self.addpokes()
self.controller.mainWindow.userPanel.vbox2h1.show_all()
self.pokescheck()
else:
self.fbpk.destroy()
self.pokesid.cancel()
if self.config.getPluginValue(self.name, 'buttonconv', '0') != str(int(response['buttonconv'].value)):
self.config.setPluginValue(self.name, 'buttonconv', str(int(response['buttonconv'].value)))
if self.config.getPluginValue(self.name, 'buttonconv', '0') == '1':
for conversation in self.getOpenConversations():
self.addbuttonconv(conversation=conversation)
self.buttonadded = self.controller.conversationManager.connect_after('new-conversation-ui',
self.addbuttonconv)
self.buttonremove = self.controller.conversationManager.connect('close-conversation-ui',
self.removebuttonconv)
else:
self.controller.conversationManager.disconnect(self.buttonremove)
self.controller.conversationManager.disconnect(self.buttonadded)
for conversation in self.getOpenConversations():
self.removebuttonconv(conversation=conversation)
return True
def commentscheck(self):
if self.config.getPluginValue(self.name, 'statusprinted','') != '':
comment_id = self.config.getPluginValue(self.name, 'uid', '')+'_'+self.config.getPluginValue(self.name, 'status_id', '')
count = len(self.fb.fql.query('SELECT "" FROM comment WHERE post_id="'+ comment_id +'"'))
if (str(count) != '0' and self.commentsactive != True):
self.commentsbutton()
self.hbox.show_all()
self.commentsgetone = SimpleThread(self.getcomments)
self.commentsgetone.start()
if str(count) == '0' and self.commentsactive == True:
self.fbcomments.destroy()
self.commentsactive = False
elif self.config.getPluginValue(self.name, 'commentscount', '') != str(count):
self.fbcomments.setText("("+str(count)+")")
self.commentsgettwo = SimpleThread(self.getcomments)
self.commentsgettwo.start()
self.config.setPluginValue(self.name, 'commentscount', str(count))
elif self.commentsactive == True:
self.fbcomments.destroy()
self.commentsactive = False
return True
def unreadcheck(self):
pmcount = (self.fb.notifications.get()['messages'])['unread']
if str(pmcount) != '0' and self.unreadactive != True:
self.addunread()
self.controller.mainWindow.userPanel.vbox2h1.show_all()
if str(pmcount) == '0' and self.unreadactive == True:
self.fbpm.destroy()
self.unreadactive = False
elif self.config.getPluginValue(self.name, 'unreadcount', '') != str(pmcount):
self.fbpm.setText('(' + str(pmcount) + ')')
self.fbpm.set_tooltip_text(_("Facebook - %s unread message(s)") % str(pmcount))
self.config.setPluginValue(self.name, 'unreadcount', str(pmcount))
return True
def pokescheck(self):
pkcount = (self.fb.notifications.get()['pokes'])['unread']
if str(pkcount) != '0' and self.pokesactive != True:
self.addpokes()
self.controller.mainWindow.userPanel.vbox2h1.show_all()
if str(pkcount) == '0' and self.pokesactive == True:
self.fbpk.destroy()
self.pokesactive = False
elif self.config.getPluginValue(self.name, 'pokescount', '') != str(pkcount):
self.fbpk.setText('(' + str(pkcount) + ')')
self.fbpk.set_tooltip_text(_("Facebook - %s unread poke(s)") % str(pkcount))
self.config.setPluginValue(self.name, 'pokescount', str(pkcount))
return True
def checkstatus(self):
if self.status == '1' and self.enabled == True :
if self.timechanged == True :
if str(self.message['message']) != '':
if self.config.getPluginValue(self.name, 'time', '0') == '1':
self.addtime()
pm = self.config.getPluginValue(self.name, 'prefix', '') + self.pm + self.config.getPluginValue(self.name, 'suffix', '')
self.config.setPluginValue( self.name, 'statusprinted', pm )
self.msn.changePersonalMessage(pm)
else:
pm = self.config.getPluginValue(self.name, 'prefix', '') + self.config.getPluginValue(self.name, 'currentstatus', '') + self.config.getPluginValue(self.name, 'suffix', '')
self.config.setPluginValue( self.name, 'statusprinted', pm )
self.msn.changePersonalMessage(pm)
else:
self.message = (self.fb.users.getInfo([self.config.getPluginValue(self.name, 'uid', '')], ['status'])[0])['status']
if str(self.message['message']) != '' :
if str(self.message['message']) != self.config.getPluginValue(self.name, 'currentstatus', ''):
self.getstatus()
self.config.setPluginValue( self.name, 'commentscounted', '' )
else:
self.msn.changePersonalMessage(self.config.getPluginValue(self.name, 'statusprinted', ''))
##Personal Message sucessfully set'
if self.config.getPluginValue(self.name, 'time', '0') == '1':
self.addtime()
pm = self.config.getPluginValue(self.name, 'prefix', '') + self.pm + self.config.getPluginValue(self.name, 'suffix', '')
if pm != self.config.getPluginValue(self.name, 'statusprinted', ''):
self.config.setPluginValue( self.name, 'statusprinted', pm )
self.msn.changePersonalMessage(pm)
else:
self.doichangestatus = False
self.config.setPluginValue( self.name, 'statusprinted', '' )
self.config.setPluginValue( self.name, 'currentstatus', '' )
self.msn.changePersonalMessage('')
try:
self.config.setPluginValue( self.name, 'commentscounted', '' )
self.fbcomments.destroy()
self.commentsactive = False
except:
''
self.doichangestatus = True
return True
self.timechanged = False
else:
return False
def addtime(self):
if self.config.getPluginValue( self.name, 'format', '' ) == '':
from datetime import datetime
status = datetime.fromtimestamp(float(self.message['time']))
now = datetime.now()
delta = now - status
if delta.days != 0:
if delta.days == 1:
statustime = _("Yesterday (%s)") % str(time.strftime("%X", time.localtime(self.message['time'])))
else:
statustime = _("%(n)s days ago (%(t)s)") % {'n': str(delta.days), 't': time.strftime("%X", time.localtime(self.message['time']))}
else:
if delta.seconds >= 3599:
if delta.seconds/3600 == 1:
statustime = _("An hour ago")
else:
statustime = _("%s hours ago") % str(delta.seconds/3600)
else:
if delta.seconds/60 <= 1 or delta.seconds/60 ==1 :
statustime = _("One minute ago")
else:
statustime = _("%s minutes ago") % str(delta.seconds/60)
else:
timeseconds = time.localtime(self.message['time'])
timeformat = self.config.getPluginValue( self.name, 'format', '' )
statustime = time.strftime(timeformat, timeseconds)
if self.config.getPluginValue( self.name, 'separator', '[Time]' ) == '[Time]':
self.pm = self.message['message'] + ' [' + statustime + ']'
elif self.config.getPluginValue( self.name, 'separator', '[Time]' ) == '(Time)':
self.pm = self.message['message'] + ' (' + statustime + ')'
elif self.config.getPluginValue( self.name, 'separator', '[Time]' ) == '-- Time':
self.pm = self.message['message'] + ' -- ' + statustime
else:
self.pm = self.message['message'] + ' ' + statustime
def getstatus(self):
pm = self.message['message']
self.config.setPluginValue( self.name, 'currentstatus', pm )
self.config.setPluginValue( self.name, 'status_id', self.message['status_id'] )
if self.config.getPluginValue(self.name, 'time', '0') == '1':
self.addtime()
else:
self.pm = pm
pm = self.config.getPluginValue(self.name, 'prefix', '') + self.pm + self.config.getPluginValue(self.name, 'suffix', '')
self.config.setPluginValue( self.name, 'statusprinted', pm )
self.msn.changePersonalMessage(pm)
##Status successfully updated from facebook'
def changestatus(self, *args):
if self.enabled and self.doichangestatus == True and self.status == '1':
self.timeout.cancel()
if str(args[2]) == '' and str(args[2]) != self.config.getPluginValue(self.name, 'statusprinted', ''):
if self.config.getPluginValue(self.name, 'confirmation', '1') == '1':
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_YES_NO, _("Are you sure you want to clear your facebook status ?"))
response = md.run()
if response == gtk.RESPONSE_YES:
self.fb.users.setStatus(status='', clear=True)
self.config.setPluginValue( self.name, 'statusprinted', '' )
try:
self.config.setPluginValue( self.name, 'commentscounted', '' )
self.fbcomments.destroy()
self.commentsactive = False
except:
''
self.checkstatus()
else:
self.msn.changePersonalMessage(self.config.getPluginValue(self.name, 'statusprinted', ''))
md.destroy()
else:
self.fb.users.setStatus(status='', clear=True)
self.config.setPluginValue( self.name, 'statusprinted', '' )
self.checkstatus()
elif str(args[2]) != self.config.getPluginValue(self.name, 'statusprinted', ''):
if self.config.getPluginValue(self.name, 'confirmation', '1') == '1':
question = _('Are you sure you want to set "%s" as your new facebook status ?') % str(args[2])
md = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_YES_NO, question)
response = md.run()
if response == gtk.RESPONSE_YES:
self.fb.users.setStatus(status=str(args[2]), clear=False, status_includes_verb=True)
try:
self.config.setPluginValue( self.name, 'commentscounted', '' )
self.fbcomments.destroy()
self.commentsactive = False
except:
''
self.checkstatus()
else:
self.msn.changePersonalMessage(self.config.getPluginValue(self.name, 'statusprinted', ''))
md.destroy()
else:
self.fb.users.setStatus(status=str(args[2]), clear=False, status_includes_verb=True)
self.checkstatus()
self.timeout = ThreadTimer(int(self.config.getPluginValue(self.name, 'checktime','30')), self.checkstatus)
self.timeout.start()
def setavatar(self):
profilepicurl = (self.fb.users.getInfo([self.config.getPluginValue(self.name, 'uid', '')], ['pic'])[0])['pic']
if profilepicurl != self.config.getPluginValue(self.name, 'avatarurl', '') and profilepicurl != '' :
self.config.setPluginValue( self.name, 'avatarurl', profilepicurl )
urllib.urlretrieve(profilepicurl, self.dest_filename+'profilepic.jpg')
##Avatar successfully updated from facebook'
##Same avatar than the one saved before'
self.controller.changeAvatar(self.dest_filename+'profilepic.jpg')
##Avatar sucessfully set'
class BaseImageButton:
def __init__(self, icon, string=None):
self.icon = icon
self.image = gtk.Image()
hbox = gtk.HBox()
self.setIcon(icon)
hbox.pack_start(self.image, True, True, 3)
if string:
self.label = gtk.Label(string)
hbox.pack_start(self.label, False, False, 3)
self.add(hbox)
def setText(self, string):
self.label.set_text(string)
def getText(self):
return self.label.get_text()
def setIcon(self, icon):
if type(icon) == gtk.gdk.PixbufAnimation:
self.image.set_from_pixbuf(self.scaleImage(icon.get_static_image()))
elif type(icon) == gtk.gdk.Pixbuf:
self.image.set_from_pixbuf(self.scaleImage(icon))
else:
self.image.set_from_stock(gtk.STOCK_MISSING_IMAGE ,gtk.ICON_SIZE_SMALL_TOOLBAR)
def getIcon(self):
return self.icon
def scaleImage(self, image):
h,w = image.get_height(), image.get_width()
width_max, height_max = 18, 16
width=float(image.get_width())
height=float(image.get_height())
if (width/width_max) > (height/height_max):
height=int((height/width)*width_max)
width=width_max
else:
width=int((width/height)*height_max)
height=height_max
image = image.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
gc.collect() # Tell Python to clean up the memory
return image
class ImageButton(gtk.Button, BaseImageButton):
def __init__(self, icon, string=None):
gtk.Button.__init__(self)
BaseImageButton.__init__(self, icon, string)
class SimpleThread(Thread):
def __init__(self, function):
Thread.__init__(self)
self.function = function
self.finished = Event()
self.event = Event()
def run(self):
self.function()
def cancel(self):
self.finished.set()
self.event.set()
class ThreadTimer(Thread):
def __init__(self, interval, function):
Thread.__init__(self)
self.interval = interval
self.function = function
self.finished = Event()
self.event = Event()
def run(self):
while not self.finished.is_set():
self.event.wait(self.interval)
if not self.finished.is_set() and not self.event.is_set():
self.function()
def cancel(self):
self.finished.set()
self.event.set()
|