global s/frontends/applications/, again

This commit is contained in:
Christophe Benz 2010-07-06 12:59:42 +02:00
commit 72c4d25d55
70 changed files with 0 additions and 4359 deletions

View file

@ -1 +0,0 @@
__import__('pkg_resources').declare_namespace(__name__)

View file

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from .boobank import Boobank

View file

@ -1,70 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai
# Copyright(C) 2009-2010 Romain Bignon, Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from __future__ import with_statement
import logging
import weboob
from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.application import ConsoleApplication
__all__ = ['Boobank']
class Boobank(ConsoleApplication):
APPNAME = 'boobank'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
self.load_backends(ICapBank)
return self.process_command(*argv[1:])
@ConsoleApplication.command('List every available accounts')
def command_list(self):
try:
for backend, account in self.weboob.do('iter_accounts'):
self.format(account, backend.name)
except weboob.CallErrors, errors:
for backend, error, backtrace in errors:
if isinstance(error, weboob.tools.browser.BrowserIncorrectPassword):
logging.error(u'Error: Incorrect password for backend %s' % backend.name)
else:
logging.error(u'Error[%s]: %s\n%s' % (backend.name, error, backtrace))
@ConsoleApplication.command('Display all future operations')
def command_coming(self, id):
total = 0.0
def do(backend):
account = backend.get_account(id)
return backend.iter_operations(account)
try:
for backend, operation in self.weboob.do(do):
self.format(operation, backend.name)
total += operation.amount
except weboob.CallErrors, errors:
for backend, error, backtrace in errors:
if isinstance(error, AccountNotFound):
logging.error(u'Error: account %s not found' % id)
else:
logging.error(u'Error[%s]: %s\n%s' % (backend.name, error, backtrace))

View file

@ -1,46 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from setuptools import setup
import os
setup(
name='weboob-boobank',
version='0.1',
description='Boobank, the Weboob bank-accounts swiss-knife',
long_description='List your bank accounts and get info about them',
author='Christophe Benz, Romain Bignon',
author_email='weboob@lists.symlink.me',
license='GPLv3',
url='http://weboob.org/Boobank',
namespace_packages = ['weboob', 'weboob.frontends'],
packages=[
'weboob',
'weboob.frontends',
'weboob.frontends.boobank',
],
scripts=[
'scripts/boobank',
],
install_requires=[
'weboob-bank-backends',
],
)

View file

@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from .chatoob import Chatoob

View file

@ -1,61 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import logging
from weboob.tools.application import ConsoleApplication
from weboob.capabilities.chat import ICapChat
from weboob.capabilities.contact import ICapContact, Contact
__all__ = ['Chatoob']
class Chatoob(ConsoleApplication):
APPNAME = 'chatoob'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Christophe Benz'
def main(self, argv):
self.load_backends(ICapChat)
#for backend, result in self.weboob.do('start_chat_polling', self.on_new_chat_message):
#logging.info(u'Polling chat messages for backend %s' % backend)
return self.process_command(*argv[1:])
def on_new_chat_message(self, message):
print 'on_new_chat_message: %s' % message
@ConsoleApplication.command('exit program')
def command_exit(self):
self.weboob.want_stop()
@ConsoleApplication.command('list online contacts')
def command_list(self):
for backend, contact in self.weboob.do_caps(ICapContact, 'iter_contacts', status=Contact.STATUS_ONLINE):
self.format(contact, backend.name)
@ConsoleApplication.command('get messages')
def command_messages(self):
for backend, message in self.weboob.do('iter_chat_messages'):
self.format(message, backend.name)
@ConsoleApplication.command('send message to contact')
def command_send(self, _id, message):
for backend, result in self.weboob.do('send_chat_message', _id, message):
if not result:
logging.error(u'Failed to send message to contact id="%s" on backend "%s"' % (_id, backend.name))

View file

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from .havesex import HaveSex

View file

@ -1,91 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from __future__ import with_statement
import sys
import weboob
from weboob.tools.application import PromptApplication
from weboob.capabilities.dating import ICapDating, OptimizationNotFound
__all__ = ['HaveSex']
class HaveSex(PromptApplication):
APPNAME = 'havesex'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
STORAGE_FILENAME = 'dating.storage'
CONFIG = {'optimizations': ''}
def main(self, argv):
self.load_config()
self.load_backends(ICapDating, storage=self.create_storage(self.STORAGE_FILENAME))
self.weboob.do('init_optimizations').wait()
self.optims('Starting', 'start_optimization', self.config.get('optimizations').split(' '))
return self.loop()
@PromptApplication.command("exit program")
def command_exit(self):
print 'Returning in real-life...'
self.weboob.want_stop()
@PromptApplication.command("show a profile")
def command_profile(self, id):
_id, backend_name = self.parse_id(id)
found = 0
for backend, profile in self.weboob.do_backends(backend_name, 'get_profile', _id):
if profile:
print profile.get_profile_text()
found = 1
if not found:
print >>sys.stderr, 'Profile not found'
return True
def service(self, action, function, *params):
sys.stdout.write('%s:' % action)
for backend, result in self.weboob.do(function, *params):
if result:
sys.stdout.write(' ' + backend.name)
sys.stdout.flush()
sys.stdout.write('.\n')
def optims(self, action, function, optims):
for optim in optims:
try:
self.service('Starting %s' % optim, 'start_optimization', optim)
except weboob.CallErrors, errors:
for backend, error, backtrace in errors:
if isinstance(error, OptimizationNotFound):
print 'Optimization "%s" not found' % optim
@PromptApplication.command("start optimizations")
def command_start(self, *optims):
self.optims('Starting', 'start_optimization', optims)
@PromptApplication.command("stop optimizations")
def command_stop(self, *optims):
self.optims('Stopping', 'stop_optimization', optims)

View file

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from .masstransit import Masstransit

View file

@ -1,239 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Julien Hébert
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from weboob.capabilities.travel import ICapTravel
from weboob.tools.application import BaseApplication
import conic
import gtk
import hildon
from logging import debug
__all__ = ['Masstransit']
class MasstransitHildon():
"hildon interface"
def connect_event(self, connection, event=None, c=None, d=None):
debug("DBUS-DEBUG a: %s, b:%s, c:%s,d: %s" % (connection, event, c, d))
status = event.get_status()
if status == conic.STATUS_CONNECTED:
self.connected = True
if self.touch_selector_entry_filled == False:
debug("connected, now fill")
self.fill_touch_selector_entry()
if self.refresh_in_progress:
self.refresh()
elif status == conic.STATUS_DISCONNECTED:
self.connected = False
def __init__(self, weboob):
self.touch_selector_entry_filled = False
self.refresh_in_progress = False
self.connected = False
self.weboob = weboob
self.connection = conic.Connection()
self.connection.connect("connection-event", self.connect_event)
self.connection.set_property("automatic-connection-events", True)
self.connection.request_connection(conic.CONNECT_FLAG_NONE)
main_window = hildon.Window()
main_window.set_title("Horaires des Prochains Trains")
main_window.connect("destroy", self.on_main_window_destroy)
self.refresh_button = hildon.Button(
gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
hildon.BUTTON_ARRANGEMENT_HORIZONTAL,
"Actualiser"
)
self.refresh_button.set_sensitive(False)
self.refresh_button.connect("clicked", self.on_refresh_button_clicked)
self.retour_button = hildon.Button(
gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
hildon.BUTTON_ARRANGEMENT_HORIZONTAL,
"Retour"
)
self.retour_button.set_sensitive(False)
self.retour_button.connect("clicked", self.on_retour_button_clicked)
self.treestore = gtk.TreeStore(str, str, str, str, str)
treeview = gtk.TreeView(self.treestore)
treeview.append_column(
gtk.TreeViewColumn(
'Train',
gtk.CellRendererText(),
text=0
))
treeview.append_column(
gtk.TreeViewColumn(
'Horaire',
gtk.CellRendererText(),
text=1
))
treeview.append_column(
gtk.TreeViewColumn(
'Destination',
gtk.CellRendererText(),
text=2
))
treeview.append_column(
gtk.TreeViewColumn(
'Voie',
gtk.CellRendererText(),
text=3
))
treeview.append_column(
gtk.TreeViewColumn(
'Information',
gtk.CellRendererText(),
text=4
))
self.combo_source = hildon.TouchSelectorEntry(text=True)
self.combo_dest = hildon.TouchSelectorEntry(text=True)
self.picker_button_source = hildon.PickerButton(
gtk.HILDON_SIZE_AUTO,
hildon.BUTTON_ARRANGEMENT_VERTICAL)
self.picker_button_dest = hildon.PickerButton(
gtk.HILDON_SIZE_AUTO,
hildon.BUTTON_ARRANGEMENT_VERTICAL
)
self.picker_button_source.set_sensitive(False)
self.picker_button_dest.set_sensitive(False)
self.picker_button_source.set_title("Gare de Depart")
self.picker_button_dest.set_title("Gare d'arrivee")
self.picker_button_source.set_selector(self.combo_source)
self.picker_button_dest.set_selector(self.combo_dest)
vertical_box = gtk.VBox()
horizontal_box = gtk.HBox()
vertical_box.pack_start(horizontal_box)
horizontal_box.pack_start(self.picker_button_source)
horizontal_box.pack_start(self.picker_button_dest)
horizontal_box.pack_start(self.retour_button)
vertical_box.pack_start(treeview)
vertical_box.pack_start(self.refresh_button)
main_window.add(vertical_box)
main_window.show_all()
self.picker_button_source.connect("value-changed",
self.check_station_input,
self.picker_button_source)
self.picker_button_dest.connect("value-changed",
self.check_station_input,
self.picker_button_dest)
def fill_touch_selector_entry(self):
liste = []
for backend in self.weboob.iter_backends():
for station in backend.iter_station_search(""):
liste.append(station.name.capitalize())
liste.sort()
for station in liste:
self.combo_source.append_text(station)
self.combo_dest.append_text(station)
self.touch_selector_entry_filled = True
self.picker_button_source.set_sensitive(True)
def on_main_window_destroy(self, widget):
"exit application at the window close"
gtk.main_quit()
def on_main_window_show(self, param):
self.fill_touch_selector_entry()
def on_retour_button_clicked(self, widget):
"the button is clicked"
self.refresh_in_progress = True
col_source = self.combo_source.get_active(0)
col_dest = self.combo_dest.get_active(0)
self.combo_source.set_active(0, col_dest)
self.combo_dest.set_active(0, col_source)
self.refresh()
def on_refresh_button_clicked(self, widget):
"the refresh button is clicked"
self.refresh_in_progress = True
self.connection.request_connection(conic.CONNECT_FLAG_NONE)
def check_station_input(self, widget, user_data):
if self.combo_source.get_current_text() is None :
self.picker_button_dest.set_sensitive(False)
self.refresh_button.set_sensitive(False)
self.retour_button.set_sensitive(False)
else:
self.picker_button_dest.set_sensitive(True)
if self.combo_dest.get_current_text() is None:
self.refresh_button.set_sensitive(False)
self.retour_button.set_sensitive(False)
else:
self.refresh_button.set_sensitive(True)
self.retour_button.set_sensitive(True)
def refresh(self):
"update departures"
self.treestore.clear()
for backend in self.weboob.iter_backends():
for station in \
backend.iter_station_search(self.combo_source.get_current_text()):
for arrival in \
backend.iter_station_search(self.combo_dest.get_current_text()):
for departure in \
backend.iter_station_departures(station.id, arrival.id):
self.treestore.append(None,
[departure.type,
departure.time,
departure.arrival_station,
departure.plateform,
departure.information])
self.refresh_in_progress = False
class Masstransit(BaseApplication):
"Application Class"
APPNAME = 'masstransit'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Julien Hébert'
def main(self, argv):
"main fonction"
self.load_modules(ICapTravel)
MasstransitHildon(self.weboob)
gtk.main()

View file

@ -1,46 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from setuptools import setup
import os
setup(
name='weboob-masstransit',
version='0.1',
description='Masstransit, the Weboob travel swiss-knife, Hildon version (Maemo OS)',
long_description='Search for train stations and departure timegrids',
author='Julien Hébert',
author_email='weboob@lists.symlink.me',
license='GPLv3',
url='http://weboob.org/Masstransit',
namespace_packages = ['weboob', 'weboob.frontends'],
packages=[
'weboob',
'weboob.frontends',
'weboob.frontends.masstransit',
],
scripts=[
'scripts/masstransit',
],
install_requires=[
'weboob-travel-backends',
],
)

View file

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from .monboob import Monboob

View file

@ -1,265 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2009-2010 Romain Bignon, Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from email.mime.text import MIMEText
from smtplib import SMTP
from email.Header import Header, decode_header
from email.Utils import parseaddr, formataddr, formatdate
from email import message_from_file, message_from_string
from smtpd import SMTPServer
import time
import re
import sys
import logging
import asyncore
from weboob.core.engine import Weboob
from weboob.core.scheduler import Scheduler
from weboob.capabilities.messages import ICapMessages, ICapMessagesReply, Message
from weboob.tools.application import ConsoleApplication
from weboob.tools.misc import html2text, get_backtrace, utc2local
__all__ = ['Monboob']
class FakeSMTPD(SMTPServer):
def __init__(self, app, bindaddr, port):
SMTPServer.__init__(self, (bindaddr, port), None)
self.app = app
def process_message(self, peer, mailfrom, rcpttos, data):
msg = message_from_string(data)
self.app.process_incoming_mail(msg)
class MonboobScheduler(Scheduler):
def __init__(self, app):
Scheduler.__init__(self)
self.app = app
def run(self):
if self.app.options.smtpd:
if ':' in self.app.options.smtpd:
host, port = self.app.options.smtpd.split(':', 1)
else:
host = '127.0.0.1'
port = self.app.options.smtpd
FakeSMTPD(self.app, host, int(port))
# XXX Fuck, we shouldn't copy this piece of code from
# weboob.scheduler.Scheduler.run().
try:
while 1:
self.stop_event.wait(0.1)
if self.app.options.smtpd:
asyncore.loop(timeout=0.1, count=1)
except KeyboardInterrupt:
self._wait_to_stop()
raise
else:
self._wait_to_stop()
return True
class Monboob(ConsoleApplication):
APPNAME = 'monboob'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
CONFIG = {'interval': 15,
'domain': 'weboob.example.org',
'recipient': 'weboob@example.org',
'smtp': 'localhost',
'html': 0}
def add_application_options(self, group):
group.add_option('-S', '--smtpd', help='run a fake smtpd server and set the port')
def create_weboob(self):
return Weboob(scheduler=MonboobScheduler(self))
def main(self, argv):
self.load_config()
self.load_backends(ICapMessages, storage=self.create_storage())
return self.process_command(*argv[1:])
def get_email_address_ident(self, msg, header):
s = msg.get(header)
m = re.match('.*<(.*)@(.*)>', s)
if m:
return m.group(1)
else:
try:
return s.split('@')[0]
except IndexError:
return s
@ConsoleApplication.command("pipe with a mail to post message")
def command_post(self):
msg = message_from_file(sys.stdin)
return self.process_incoming_mail(msg)
def process_incoming_mail(self, msg):
to = self.get_email_address_ident(msg, 'To')
reply_to = self.get_email_address_ident(msg, 'In-Reply-To')
if not reply_to:
print >>sys.stderr, 'This is not a reply (no Reply-To field)'
return 1
title = msg.get('Subject')
if title:
new_title = u''
for part in decode_header(title):
if part[1]:
new_title += unicode(part[0], part[1])
else:
new_title += unicode(part[0])
title = new_title
content = u''
for part in msg.walk():
if part.get_content_type() == 'text/plain':
s = part.get_payload(decode=True)
charsets = part.get_charsets() + msg.get_charsets()
for charset in charsets:
try:
content += unicode(s, charset)
except:
continue
else:
break
# remove signature
content = content.split(u'\n-- \n')[0]
bname, id = reply_to.split('.', 1)
# Default use the To header field to know the backend to use.
if to and bname != to:
bname = to
try:
backend = self.weboob.backends[bname]
except KeyError:
print >>sys.stderr, 'Backend %s not found' % bname
return 1
if not backend.has_caps(ICapMessagesReply):
print >>sys.stderr, 'The backend %s does not implement ICapMessagesReply' % bname
return 1
thread_id, msg_id = id.rsplit('.', 1)
try:
backend.post_reply(thread_id, msg_id, title, content)
except Exception, e:
content = u'Unable to send message to %s:\n' % thread_id
content += '\n\t%s\n' % e
if logging.root.level == logging.DEBUG:
content += '\n%s\n' % get_backtrace(e)
self.send_email(backend, Message(thread_id,
0,
title='Unable to send message',
sender='Monboob',
reply_id=msg_id,
content=content))
@ConsoleApplication.command("run daemon")
def command_run(self):
self.weboob.repeat(int(self.config.get('interval')), self.process)
self.weboob.loop()
def process(self):
for backend, message in self.weboob.do('iter_new_messages'):
self.send_email(backend, message)
def send_email(self, backend, mail):
domain = self.config.get('domain')
recipient = self.config.get('recipient')
reply_id = ''
if mail.get_reply_id():
reply_id = u'<%s.%s@%s>' % (backend.name, mail.get_full_reply_id(), domain)
subject = mail.get_title()
sender = u'"%s" <%s@%s>' % (mail.get_from().replace('"', '""'), backend.name, domain)
# assume that get_date() returns an UTC datetime
date = formatdate(time.mktime(utc2local(mail.get_date()).timetuple()), localtime=True)
msg_id = u'<%s.%s@%s>' % (backend.name, mail.get_full_id(), domain)
if int(self.config.get('html')) and mail.is_html:
body = mail.get_content()
content_type = 'html'
else:
if mail.is_html:
body = html2text(mail.get_content())
else:
body = mail.get_content()
content_type = 'plain'
if mail.get_signature():
if int(self.config.get('html')) and mail.is_html:
body += u'<p>-- <br />%s</p>' % mail.get_signature()
else:
body += u'\n\n-- \n'
if mail.is_html:
body += html2text(mail.get_signature())
else:
body += mail.get_signature()
# Header class is smart enough to try US-ASCII, then the charset we
# provide, then fall back to UTF-8.
header_charset = 'ISO-8859-1'
# We must choose the body charset manually
for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
try:
body.encode(body_charset)
except UnicodeError:
pass
else:
break
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
recipient_name, recipient_addr = parseaddr(recipient)
# We must always pass Unicode strings to Header, otherwise it will
# use RFC 2047 encoding even on plain ASCII strings.
sender_name = str(Header(unicode(sender_name), header_charset))
recipient_name = str(Header(unicode(recipient_name), header_charset))
# Make sure email addresses do not contain non-ASCII characters
sender_addr = sender_addr.encode('ascii')
recipient_addr = recipient_addr.encode('ascii')
# Create the message ('plain' stands for Content-Type: text/plain)
msg = MIMEText(body.encode(body_charset), content_type, body_charset)
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = formataddr((recipient_name, recipient_addr))
msg['Subject'] = Header(unicode(subject), header_charset)
msg['Message-Id'] = msg_id
msg['Date'] = date
if reply_id:
msg['In-Reply-To'] = reply_id
# Send the message via SMTP to localhost:25
smtp = SMTP(self.config.get('smtp'))
print 'Send mail from <%s> to <%s>' % (sender, recipient)
smtp.sendmail(sender, recipient, msg.as_string())
smtp.quit()
return msg['Message-Id']

View file

@ -1,45 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from setuptools import setup
import os
setup(
name='weboob-monboob',
version='0.1',
description='Monboob, the Weboob e-mail swiss-knife',
author='Romain Bignon',
author_email='weboob@lists.symlink.me',
license='GPLv3',
url='http://weboob.org/Monboob',
namespace_packages = ['weboob', 'weboob.frontends'],
packages=[
'weboob',
'weboob.frontends',
'weboob.frontends.monboob',
],
scripts=[
'scripts/monboob',
],
install_requires=[
'weboob-messages-backends',
],
)

View file

@ -1 +0,0 @@
from .qboobmsg import QBoobMsg

View file

@ -1,47 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from PyQt4.QtCore import SIGNAL
from weboob.tools.application.qt import QtMainWindow
from weboob.tools.application.qt.backendcfg import BackendCfg
from weboob.capabilities.messages import ICapMessages
from .ui.main_window_ui import Ui_MainWindow
from .messages_manager import MessagesManager
class MainWindow(QtMainWindow):
def __init__(self, config, weboob, parent=None):
QtMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.config = config
self.weboob = weboob
self.manager = MessagesManager(weboob, self)
self.setCentralWidget(self.manager)
self.connect(self.ui.actionModules, SIGNAL("triggered()"), self.modulesConfig)
self.connect(self.ui.actionRefresh, SIGNAL("triggered()"), self.refresh)
def modulesConfig(self):
bckndcfg = BackendCfg(self.weboob, (ICapMessages,), self)
bckndcfg.show()
def refresh(self):
self.centralWidget().refresh()

View file

@ -1,134 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import time
from PyQt4.QtGui import QWidget, QTreeWidgetItem, QListWidgetItem
from PyQt4.QtCore import SIGNAL, Qt
from weboob.capabilities.messages import ICapMessages
from weboob.tools.application.qt import QtDo
from .ui.messages_manager_ui import Ui_MessagesManager
class MessagesManager(QWidget):
def __init__(self, weboob, parent=None):
QWidget.__init__(self, parent)
self.ui = Ui_MessagesManager()
self.ui.setupUi(self)
self.weboob = weboob
self.ui.backendsList.addItem('(All)')
for backend in self.weboob.iter_backends():
if not backend.has_caps(ICapMessages):
continue
item = QListWidgetItem(backend.name.capitalize())
item.setData(Qt.UserRole, backend)
self.ui.backendsList.addItem(item)
self.ui.backendsList.setCurrentRow(0)
self.backend = None
self.connect(self.ui.backendsList, SIGNAL('itemSelectionChanged()'), self._backendChanged)
self.connect(self.ui.messagesTree, SIGNAL('itemClicked(QTreeWidgetItem *, int)'), self._messageSelected)
self.connect(self.ui.messagesTree, SIGNAL('itemActivated(QTreeWidgetItem *, int)'), self._messageSelected)
self.connect(self, SIGNAL('gotMessage'), self._gotMessage)
def load(self):
self.refresh()
def _backendChanged(self):
selection = self.ui.backendsList.selectedItems()
if not selection:
self.backend = None
return
self.backend = selection[0].data(Qt.UserRole).toPyObject()
self.ui.messagesTree.clear()
self.refresh()
def refresh(self):
if self.ui.messagesTree.topLevelItemCount() > 0:
command = 'iter_new_messages'
else:
command = 'iter_messages'
self.ui.backendsList.setEnabled(False)
self.process = QtDo(self.weboob, self._gotMessage)
if self.backend:
self.process.do_backends(self.backend.name, command)
else:
self.process.do_caps(ICapMessages, command)
def _gotMessage(self, backend, message):
if message is None:
self.ui.backendsList.setEnabled(True)
return
item = QTreeWidgetItem(None, [time.strftime('%Y-%m-%d %H:%M:%S', message.get_date().timetuple()),
message.sender, message.title])
item.setData(0, Qt.UserRole, message)
root = self.ui.messagesTree.invisibleRootItem()
# try to find a message which would be my parent.
# if no one is found, insert it on top level.
if not self._insertMessage(root, item):
self.ui.messagesTree.addTopLevelItem(item)
# Check orphaned items which are child of this new one to put
# in.
to_remove = []
for i in xrange(root.childCount()):
sub = root.child(i)
sub_message = sub.data(0, Qt.UserRole).toPyObject()
if sub_message.thread_id == message.thread_id and sub_message.reply_id == message.id:
# do not remove it now because childCount() would change.
to_remove.append(sub)
for sub in to_remove:
root.removeChild(sub)
item.addChild(sub)
def _insertMessage(self, top, item):
top_message = top.data(0, Qt.UserRole).toPyObject()
item_message = item.data(0, Qt.UserRole).toPyObject()
if top_message and top_message.thread_id == item_message.thread_id and top_message.id == item_message.reply_id:
# it's my parent
top.addChild(item)
return True
else:
# check the children
for i in xrange(top.childCount()):
sub = top.child(i)
if self._insertMessage(sub, item):
return True
return False
def _messageSelected(self, item, column):
message = item.data(0, Qt.UserRole).toPyObject()
self.ui.messageBody.setText("<h1>%s</h1>"
"<b>Date</b>: %s<br />"
"<b>From</b>: %s<br />"
"<p>%s</p>"
% (message.title, str(message.date), message.sender, message.content))

View file

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Romain Bignon
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from weboob.capabilities.messages import ICapMessages
from weboob.tools.application import QtApplication
from .main_window import MainWindow
class QBoobMsg(QtApplication):
APPNAME = 'qboobmsg'
VERSION = '0.1'
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
def main(self, argv):
self.load_backends(ICapMessages, storage=self.create_storage())
self.main_window = MainWindow(self.config, self.weboob)
self.main_window.show()
return self.weboob.loop()

View file

@ -1,49 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2010 Christophe Benz
#
# This program 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, version 3 of the License.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from setuptools import setup
import os
os.system('make -C %s/ui' % os.path.dirname(__file__))
setup(
name='weboob-qboobmsg',
version='0.1',
description='QBoobMsg, the Weboob e-mail swiss-knife, Qt version',
author='Romain Bignon',
author_email='weboob@lists.symlink.me',
license='GPLv3',
url='http://weboob.org/QBoobMsg',
namespace_packages = ['weboob', 'weboob.frontends'],
packages=[
'weboob',
'weboob.frontends',
'weboob.frontends.qboobmsg',
'weboob.frontends.qboobmsg.ui',
],
scripts=[
'scripts/qboobmsg',
],
install_requires=[
'weboob-core-qt',
'weboob-messages-backends',
],
)

View file

@ -1,13 +0,0 @@
UI_FILES = $(wildcard *.ui)
UI_PY_FILES = $(UI_FILES:%.ui=%_ui.py)
PYUIC = pyuic4
all: $(UI_PY_FILES)
%_ui.py: %.ui
$(PYUIC) -o $@ $^
clean:
rm -f *.pyc
rm -f $(UI_PY_FILES)

Some files were not shown because too many files have changed in this diff Show more