global s/frontends/applications/
This commit is contained in:
parent
423bc10f33
commit
3bf9c2518b
88 changed files with 4387 additions and 28 deletions
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.boobank import Boobank
|
||||
from weboob.applications.boobank import Boobank
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.chatoob import Chatoob
|
||||
from weboob.applications.chatoob import Chatoob
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.havesex import HaveSex
|
||||
from weboob.applications.havesex import HaveSex
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.masstransit import Masstransit
|
||||
from weboob.applications.masstransit import Masstransit
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.monboob import Monboob
|
||||
from weboob.applications.monboob import Monboob
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.qboobmsg import QBoobMsg
|
||||
from weboob.applications.qboobmsg import QBoobMsg
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.qhavesex import QHaveSex
|
||||
from weboob.applications.qhavesex import QHaveSex
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.qvideoob import QVideoob
|
||||
from weboob.applications.qvideoob import QVideoob
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.travel import Travel
|
||||
from weboob.applications.travel import Travel
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.videoob import Videoob
|
||||
from weboob.applications.videoob import Videoob
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.videoob_web import VideoobWeb
|
||||
from weboob.applications.videoob_web import VideoobWeb
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.weboobdebug import WeboobDebug
|
||||
from weboob.applications.weboobdebug import WeboobDebug
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.weboobtests import WeboobTests
|
||||
from weboob.applications.weboobtests import WeboobTests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.weboobcfg import WeboobCfg
|
||||
from weboob.applications.weboobcfg import WeboobCfg
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.weboorrents import Weboorrents
|
||||
from weboob.applications.weboorrents import Weboorrents
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
from weboob.frontends.wetboobs import WetBoobs
|
||||
from weboob.applications.wetboobs import WetBoobs
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ COMMAND="$1"
|
|||
SETUP_PY_LIST="
|
||||
weboob/setup.py
|
||||
weboob/backends/setup.py
|
||||
weboob/frontends/boobank/setup.py
|
||||
weboob/frontends/masstransit/setup.py
|
||||
weboob/frontends/monboob/setup.py
|
||||
weboob/frontends/qboobmsg/setup.py
|
||||
weboob/frontends/qhavesex/setup.py
|
||||
weboob/frontends/qvideoob/setup.py
|
||||
weboob/frontends/travel/setup.py
|
||||
weboob/frontends/videoob/setup.py
|
||||
weboob/frontends/videoob_web/setup.py
|
||||
weboob/frontends/weboorrents/setup.py
|
||||
weboob/frontends/wetboobs/setup.py
|
||||
weboob/applications/boobank/setup.py
|
||||
weboob/applications/masstransit/setup.py
|
||||
weboob/applications/monboob/setup.py
|
||||
weboob/applications/qboobmsg/setup.py
|
||||
weboob/applications/qhavesex/setup.py
|
||||
weboob/applications/qvideoob/setup.py
|
||||
weboob/applications/travel/setup.py
|
||||
weboob/applications/videoob/setup.py
|
||||
weboob/applications/videoob_web/setup.py
|
||||
weboob/applications/weboorrents/setup.py
|
||||
weboob/applications/wetboobs/setup.py
|
||||
"
|
||||
|
||||
|
||||
|
|
|
|||
1
weboob/applications/__init__.py
Normal file
1
weboob/applications/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
19
weboob/applications/boobank/__init__.py
Normal file
19
weboob/applications/boobank/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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
|
||||
70
weboob/applications/boobank/boobank.py
Normal file
70
weboob/applications/boobank/boobank.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#!/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))
|
||||
46
weboob/applications/boobank/setup.py
Executable file
46
weboob/applications/boobank/setup.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#! /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',
|
||||
],
|
||||
)
|
||||
18
weboob/applications/chatoob/__init__.py
Normal file
18
weboob/applications/chatoob/__init__.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- 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
|
||||
61
weboob/applications/chatoob/chatoob.py
Normal file
61
weboob/applications/chatoob/chatoob.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# -*- 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))
|
||||
19
weboob/applications/havesex/__init__.py
Normal file
19
weboob/applications/havesex/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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
|
||||
91
weboob/applications/havesex/havesex.py
Normal file
91
weboob/applications/havesex/havesex.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# -*- 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)
|
||||
20
weboob/applications/masstransit/__init__.py
Normal file
20
weboob/applications/masstransit/__init__.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# -*- 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
|
||||
239
weboob/applications/masstransit/masstransit.py
Normal file
239
weboob/applications/masstransit/masstransit.py
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
# -*- 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()
|
||||
46
weboob/applications/masstransit/setup.py
Executable file
46
weboob/applications/masstransit/setup.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#! /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',
|
||||
],
|
||||
)
|
||||
19
weboob/applications/monboob/__init__.py
Normal file
19
weboob/applications/monboob/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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
|
||||
265
weboob/applications/monboob/monboob.py
Normal file
265
weboob/applications/monboob/monboob.py
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
# -*- 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']
|
||||
45
weboob/applications/monboob/setup.py
Executable file
45
weboob/applications/monboob/setup.py
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
#! /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',
|
||||
],
|
||||
)
|
||||
1
weboob/applications/qboobmsg/__init__.py
Normal file
1
weboob/applications/qboobmsg/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .qboobmsg import QBoobMsg
|
||||
47
weboob/applications/qboobmsg/main_window.py
Normal file
47
weboob/applications/qboobmsg/main_window.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# -*- 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()
|
||||
134
weboob/applications/qboobmsg/messages_manager.py
Normal file
134
weboob/applications/qboobmsg/messages_manager.py
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# -*- 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))
|
||||
34
weboob/applications/qboobmsg/qboobmsg.py
Normal file
34
weboob/applications/qboobmsg/qboobmsg.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# -*- 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()
|
||||
49
weboob/applications/qboobmsg/setup.py
Executable file
49
weboob/applications/qboobmsg/setup.py
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
#! /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',
|
||||
],
|
||||
)
|
||||
13
weboob/applications/qboobmsg/ui/Makefile
Normal file
13
weboob/applications/qboobmsg/ui/Makefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
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)
|
||||
|
||||
0
weboob/applications/qboobmsg/ui/__init__.py
Normal file
0
weboob/applications/qboobmsg/ui/__init__.py
Normal file
91
weboob/applications/qboobmsg/ui/main_window.ui
Normal file
91
weboob/applications/qboobmsg/ui/main_window.ui
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>QBoobMsg</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionModules"/>
|
||||
<addaction name="actionRefresh"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionQuit"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionModules"/>
|
||||
<addaction name="actionRefresh"/>
|
||||
</widget>
|
||||
<action name="actionModules">
|
||||
<property name="text">
|
||||
<string>Modules</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionQuit">
|
||||
<property name="text">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRefresh">
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionQuit</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>381</x>
|
||||
<y>289</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
192
weboob/applications/qboobmsg/ui/messages_manager.ui
Normal file
192
weboob/applications/qboobmsg/ui/messages_manager.ui
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MessagesManager</class>
|
||||
<widget class="QWidget" name="MessagesManager">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>767</width>
|
||||
<height>591</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QListWidget" name="backendsList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="messagesTree">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>100</number>
|
||||
</attribute>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>100</number>
|
||||
</attribute>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignLeft|AlignVCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>From</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="messageBody">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="expandButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="collapseButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>−</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>expandButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>messagesTree</receiver>
|
||||
<slot>expandAll()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>733</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>527</x>
|
||||
<y>150</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>collapseButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>messagesTree</receiver>
|
||||
<slot>collapseAll()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>733</x>
|
||||
<y>60</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>527</x>
|
||||
<y>150</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
1
weboob/applications/qhavesex/__init__.py
Normal file
1
weboob/applications/qhavesex/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .qhavesex import QHaveSex
|
||||
203
weboob/applications/qhavesex/contacts.py
Normal file
203
weboob/applications/qhavesex/contacts.py
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
# -*- 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 urllib2
|
||||
import time
|
||||
import logging
|
||||
from PyQt4.QtGui import QWidget, QListWidgetItem, QImage, QIcon, QPixmap, QFrame, QMessageBox
|
||||
from PyQt4.QtCore import SIGNAL, Qt
|
||||
|
||||
from weboob.tools.application.qt import QtDo, HTMLDelegate
|
||||
from weboob.capabilities.contact import ICapContact, Contact
|
||||
from weboob.capabilities.chat import ICapChat
|
||||
from weboob.capabilities.messages import ICapMessages
|
||||
|
||||
from .ui.contacts_ui import Ui_Contacts
|
||||
from .ui.contact_thread_ui import Ui_ContactThread
|
||||
from .ui.thread_message_ui import Ui_ThreadMessage
|
||||
|
||||
class ThreadMessage(QFrame):
|
||||
def __init__(self, message, parent=None):
|
||||
QFrame.__init__(self, parent)
|
||||
self.ui = Ui_ThreadMessage()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.date = message.get_date()
|
||||
|
||||
self.ui.nameLabel.setText(message.sender)
|
||||
self.ui.headerLabel.setText(time.strftime('%Y-%m-%d %H:%M:%S', message.get_date().timetuple()))
|
||||
if message.is_html:
|
||||
content = message.content
|
||||
else:
|
||||
content = message.content.replace('&', '&').replace('<', '<').replace('>', '>').replace('\n', '<br />')
|
||||
self.ui.contentLabel.setText(content)
|
||||
|
||||
class ContactThread(QWidget):
|
||||
def __init__(self, weboob, contact, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.ui = Ui_ContactThread()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.weboob = weboob
|
||||
self.contact = contact
|
||||
self.messages = []
|
||||
|
||||
self.connect(self.ui.sendButton, SIGNAL('clicked()'), self.postReply)
|
||||
|
||||
self.refreshMessages()
|
||||
|
||||
def refreshMessages(self):
|
||||
if self.ui.scrollAreaContent.layout().count() > 0:
|
||||
command = 'iter_new_messages'
|
||||
else:
|
||||
command = 'iter_messages'
|
||||
|
||||
self.process = QtDo(self.weboob, self.gotMessage)
|
||||
self.process.do_backends(self.contact.backend, command, thread=self.contact.id)
|
||||
|
||||
def gotMessage(self, backend, message):
|
||||
if not message:
|
||||
v = self.ui.scrollArea.verticalScrollBar()
|
||||
print v.minimum(), v.value(), v.maximum(), v.sliderPosition()
|
||||
self.ui.scrollArea.verticalScrollBar().setValue(self.ui.scrollArea.verticalScrollBar().maximum())
|
||||
return
|
||||
|
||||
widget = ThreadMessage(message)
|
||||
for i, m in enumerate(self.messages):
|
||||
if widget.date < m.date:
|
||||
self.ui.scrollAreaContent.layout().insertWidget(i, widget)
|
||||
self.messages.insert(i, widget)
|
||||
return
|
||||
|
||||
self.ui.scrollAreaContent.layout().addWidget(widget)
|
||||
self.messages.append(widget)
|
||||
|
||||
def postReply(self):
|
||||
text = unicode(self.ui.textEdit.toPlainText())
|
||||
self.ui.textEdit.setEnabled(False)
|
||||
self.ui.sendButton.setEnabled(False)
|
||||
self.process = QtDo(self.weboob, self.replyPosted, self.replyNotPosted)
|
||||
self.process.do_backends(self.contact.backend, 'post_reply', self.contact.id, 0, '', text)
|
||||
|
||||
def replyPosted(self, backend, ignored):
|
||||
self.ui.textEdit.clear()
|
||||
self.ui.textEdit.setEnabled(True)
|
||||
self.ui.sendButton.setEnabled(True)
|
||||
self.refreshMessages()
|
||||
|
||||
def replyNotPosted(self, backend, error, backtrace):
|
||||
content = unicode(self.tr('Unable to send message:\n%s\n')) % error
|
||||
if logging.root.level == logging.DEBUG:
|
||||
content += '\n%s\n' % backtrace
|
||||
QMessageBox.critical(self, self.tr('Error while posting reply'),
|
||||
content, QMessageBox.Ok)
|
||||
|
||||
|
||||
class IGroup(object):
|
||||
def __init__(self, weboob, id, name):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.weboob = weboob
|
||||
|
||||
def iter_contacts(self, cb):
|
||||
raise NotImplementedError()
|
||||
|
||||
class MetaGroup(IGroup):
|
||||
def iter_contacts(self, cb):
|
||||
if self.id == 'online':
|
||||
status = Contact.STATUS_ONLINE
|
||||
elif self.id == 'offline':
|
||||
status = Contact.STATUS_OFFLINE
|
||||
else:
|
||||
status = Contact.STATUS_ALL
|
||||
|
||||
self.process = QtDo(self.weboob, lambda b, d: self.cb(cb, b, d))
|
||||
self.process.do_caps(ICapContact, 'iter_contacts', status)
|
||||
|
||||
def cb(self, cb, backend, contact):
|
||||
if contact:
|
||||
contact.backend = backend
|
||||
cb(contact)
|
||||
|
||||
class ContactsWidget(QWidget):
|
||||
def __init__(self, weboob, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.ui = Ui_Contacts()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.weboob = weboob
|
||||
self.contact = None
|
||||
self.ui.contactList.setItemDelegate(HTMLDelegate())
|
||||
|
||||
self.ui.groupBox.addItem('All', MetaGroup(self.weboob, 'all', self.tr('All')))
|
||||
self.ui.groupBox.addItem('Onlines', MetaGroup(self.weboob, 'online', self.tr('Online')))
|
||||
self.ui.groupBox.addItem('Offlines', MetaGroup(self.weboob, 'offline', self.tr('Offline')))
|
||||
|
||||
self.connect(self.ui.groupBox, SIGNAL('currentIndexChanged(int)'), self.groupChanged)
|
||||
self.connect(self.ui.contactList, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.contactChanged)
|
||||
self.connect(self.ui.refreshButton, SIGNAL('clicked()'), self.refreshContactList)
|
||||
|
||||
def load(self):
|
||||
self.ui.groupBox.setCurrentIndex(1)
|
||||
|
||||
def groupChanged(self, i):
|
||||
self.refreshContactList()
|
||||
|
||||
def refreshContactList(self):
|
||||
self.ui.contactList.clear()
|
||||
i = self.ui.groupBox.currentIndex()
|
||||
group = self.ui.groupBox.itemData(i).toPyObject()
|
||||
group.iter_contacts(self.addContact)
|
||||
|
||||
def addContact(self, contact):
|
||||
if not contact:
|
||||
return
|
||||
|
||||
data = urllib2.urlopen(contact.thumbnail_url).read()
|
||||
img = QImage.fromData(data)
|
||||
|
||||
status = ''
|
||||
if contact.status == Contact.STATUS_ONLINE:
|
||||
status = 'Online'
|
||||
status_color = 0x00aa00
|
||||
elif contact.status == Contact.STATUS_OFFLINE:
|
||||
status = 'Offline'
|
||||
status_color = 0xff0000
|
||||
|
||||
item = QListWidgetItem()
|
||||
item.setText('<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (contact.name, status_color, status, contact.backend.name))
|
||||
item.setIcon(QIcon(QPixmap.fromImage(img)))
|
||||
item.setData(Qt.UserRole, contact)
|
||||
|
||||
self.ui.contactList.addItem(item)
|
||||
|
||||
def contactChanged(self, current, previous):
|
||||
self.ui.tabWidget.clear()
|
||||
self.contact = None
|
||||
|
||||
if not current:
|
||||
return
|
||||
|
||||
self.contact = current.data(Qt.UserRole).toPyObject()
|
||||
|
||||
self.ui.tabWidget.addTab(QWidget(), self.tr('Profile'))
|
||||
if self.contact.backend.has_caps(ICapMessages):
|
||||
self.ui.tabWidget.addTab(ContactThread(self.weboob, self.contact), self.tr('Messages'))
|
||||
if self.contact.backend.has_caps(ICapChat):
|
||||
self.ui.tabWidget.addTab(QWidget(), self.tr('Chat'))
|
||||
self.ui.tabWidget.addTab(QWidget(), self.tr('Calendar'))
|
||||
self.ui.tabWidget.addTab(QWidget(), self.tr('Notes'))
|
||||
59
weboob/applications/qhavesex/main_window.py
Normal file
59
weboob/applications/qhavesex/main_window.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# -*- 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.QtGui import QWidget
|
||||
from PyQt4.QtCore import SIGNAL
|
||||
|
||||
from weboob.tools.application.qt import QtMainWindow
|
||||
from weboob.tools.application.qt.backendcfg import BackendCfg
|
||||
from weboob.capabilities.dating import ICapDating
|
||||
|
||||
from weboob.frontends.qboobmsg.messages_manager import MessagesManager
|
||||
|
||||
from .ui.main_window_ui import Ui_MainWindow
|
||||
from .status import AccountsStatus
|
||||
from .contacts import ContactsWidget
|
||||
|
||||
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.loaded_tabs = {}
|
||||
|
||||
self.ui.tabWidget.addTab(AccountsStatus(self.weboob), self.tr('Status'))
|
||||
self.ui.tabWidget.addTab(MessagesManager(self.weboob), self.tr('Messages'))
|
||||
self.ui.tabWidget.addTab(ContactsWidget(self.weboob), self.tr('Contacts'))
|
||||
self.ui.tabWidget.addTab(QWidget(), self.tr('Calendar'))
|
||||
|
||||
self.connect(self.ui.actionModules, SIGNAL("triggered()"), self.modulesConfig)
|
||||
self.connect(self.ui.tabWidget, SIGNAL('currentChanged(int)'), self.tabChanged)
|
||||
|
||||
def modulesConfig(self):
|
||||
bckndcfg = BackendCfg(self.weboob, (ICapDating,), self)
|
||||
bckndcfg.show()
|
||||
|
||||
def tabChanged(self, i):
|
||||
widget = self.ui.tabWidget.currentWidget()
|
||||
|
||||
if hasattr(widget, 'load') and not i in self.loaded_tabs:
|
||||
widget.load()
|
||||
self.loaded_tabs[i] = True
|
||||
35
weboob/applications/qhavesex/qhavesex.py
Normal file
35
weboob/applications/qhavesex/qhavesex.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# -*- 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.dating import ICapDating
|
||||
from weboob.tools.application import QtApplication
|
||||
|
||||
from .main_window import MainWindow
|
||||
|
||||
class QHaveSex(QtApplication):
|
||||
APPNAME = 'qhavesex'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
STORAGE_FILENAME = 'dating.storage'
|
||||
|
||||
def main(self, argv):
|
||||
self.load_backends(ICapDating, storage=self.create_storage())
|
||||
|
||||
self.main_window = MainWindow(self.config, self.weboob)
|
||||
self.main_window.show()
|
||||
return self.weboob.loop()
|
||||
50
weboob/applications/qhavesex/setup.py
Executable file
50
weboob/applications/qhavesex/setup.py
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#! /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-qhavesex',
|
||||
version='0.1',
|
||||
description='QHaveSex, the Weboob sexual life swiss-knife, Qt version',
|
||||
long_description='Optimize your probabilities to have sex on dating websites',
|
||||
author='Romain Bignon',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/QHaveSex',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.qhavesex',
|
||||
'weboob.frontends.qhavesex.ui',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/qhavesex',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-core-qt',
|
||||
'weboob-dating-backends',
|
||||
],
|
||||
)
|
||||
102
weboob/applications/qhavesex/status.py
Normal file
102
weboob/applications/qhavesex/status.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# -*- 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
|
||||
|
||||
from PyQt4.QtGui import QWidget, QHBoxLayout, QVBoxLayout, QFrame, QLabel, QImage, QPixmap
|
||||
from PyQt4.QtCore import SIGNAL, QTimer
|
||||
|
||||
from weboob.capabilities.dating import StatusField
|
||||
|
||||
class Account(QFrame):
|
||||
def __init__(self, backend, parent=None):
|
||||
QFrame.__init__(self, parent)
|
||||
|
||||
self.setFrameShape(QFrame.StyledPanel)
|
||||
self.setFrameShadow(QFrame.Raised)
|
||||
|
||||
self.backend = backend
|
||||
self.setLayout(QVBoxLayout())
|
||||
|
||||
head = QHBoxLayout()
|
||||
headw = QWidget()
|
||||
headw.setLayout(head)
|
||||
|
||||
self.title = QLabel(u'<h1>%s — %s</h1>' % (backend.name, backend.DESCRIPTION))
|
||||
|
||||
if backend.ICON:
|
||||
self.icon = QLabel()
|
||||
img = QImage(backend.ICON)
|
||||
self.icon.setPixmap(QPixmap.fromImage(img))
|
||||
head.addWidget(self.icon)
|
||||
|
||||
head.addWidget(self.title)
|
||||
head.addStretch()
|
||||
|
||||
self.body = QLabel()
|
||||
|
||||
self.layout().addWidget(headw)
|
||||
self.layout().addWidget(self.body)
|
||||
|
||||
self.timer = QTimer()
|
||||
self.timer.setSingleShot(False)
|
||||
self.timer.setInterval(60)
|
||||
self.connect(self.timer, SIGNAL('timeout()'), self.updateStats)
|
||||
|
||||
self.updateStats()
|
||||
|
||||
def updateStats(self):
|
||||
with self.backend:
|
||||
body = u''
|
||||
in_p = False
|
||||
for field in self.backend.get_status():
|
||||
if field.flags & StatusField.FIELD_HTML:
|
||||
value = field.value.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
else:
|
||||
value = '%s' % field.value
|
||||
|
||||
if field.flags & StatusField.FIELD_TEXT:
|
||||
if in_p:
|
||||
body += '</p>'
|
||||
body += '<p>%s</p>' % value
|
||||
in_p = False
|
||||
else:
|
||||
if not in_p:
|
||||
body += "<p>"
|
||||
in_p = True
|
||||
else:
|
||||
body += "<br />"
|
||||
|
||||
body += '<b>%s</b>: %s' % (field.label, field.value)
|
||||
if in_p:
|
||||
body += "</p>"
|
||||
|
||||
self.body.setText(body)
|
||||
|
||||
class AccountsStatus(QWidget):
|
||||
def __init__(self, weboob, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
|
||||
self.weboob = weboob
|
||||
|
||||
self.setLayout(QVBoxLayout())
|
||||
|
||||
for backend in self.weboob.iter_backends():
|
||||
account = Account(backend)
|
||||
self.layout().addWidget(account)
|
||||
|
||||
self.layout().addStretch()
|
||||
13
weboob/applications/qhavesex/ui/Makefile
Normal file
13
weboob/applications/qhavesex/ui/Makefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
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)
|
||||
|
||||
0
weboob/applications/qhavesex/ui/__init__.py
Normal file
0
weboob/applications/qhavesex/ui/__init__.py
Normal file
90
weboob/applications/qhavesex/ui/contact_thread.ui
Normal file
90
weboob/applications/qhavesex/ui/contact_thread.ui
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ContactThread</class>
|
||||
<widget class="QWidget" name="ContactThread">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>578</width>
|
||||
<height>429</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaContent">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>556</width>
|
||||
<height>187</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QWidget#scrollAreaContent {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2"/>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sendButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
89
weboob/applications/qhavesex/ui/contacts.ui
Normal file
89
weboob/applications/qhavesex/ui/contacts.ui
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Contacts</class>
|
||||
<widget class="QWidget" name="Contacts">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>482</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="groupBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="refreshButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../../../../../../../../usr/share/icons/oxygen/16x16/actions/view-refresh.png</normaloff>../../../../../../../../usr/share/icons/oxygen/16x16/actions/view-refresh.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="contactList">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionRectVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
92
weboob/applications/qhavesex/ui/main_window.ui
Normal file
92
weboob/applications/qhavesex/ui/main_window.ui
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>QHaveSex</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionModules"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionQuit"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionModules"/>
|
||||
</widget>
|
||||
<action name="actionModules">
|
||||
<property name="text">
|
||||
<string>Modules</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionQuit">
|
||||
<property name="text">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionQuit</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>381</x>
|
||||
<y>289</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
109
weboob/applications/qhavesex/ui/thread_message.ui
Normal file
109
weboob/applications/qhavesex/ui/thread_message.ui
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ThreadMessage</class>
|
||||
<widget class="QFrame" name="ThreadMessage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>552</width>
|
||||
<height>76</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Frame</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="imageLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="headerLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="contentLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
1
weboob/applications/qvideoob/__init__.py
Normal file
1
weboob/applications/qvideoob/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .qvideoob import QVideoob
|
||||
116
weboob/applications/qvideoob/main_window.py
Normal file
116
weboob/applications/qvideoob/main_window.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# -*- 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, QtDo
|
||||
|
||||
from weboob.frontends.qvideoob.ui.main_window_ui import Ui_MainWindow
|
||||
|
||||
from .video import Video
|
||||
from .minivideo import MiniVideo
|
||||
|
||||
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.minivideos = []
|
||||
|
||||
self.ui.backendEdit.addItem('All backends', '')
|
||||
for i, backend in enumerate(self.weboob.iter_backends()):
|
||||
self.ui.backendEdit.addItem(backend.name, backend.name)
|
||||
if backend.name == self.config.get('settings', 'backend'):
|
||||
self.ui.backendEdit.setCurrentIndex(i+1)
|
||||
self.ui.sortbyEdit.setCurrentIndex(int(self.config.get('settings', 'sortby')))
|
||||
self.ui.nsfwCheckBox.setChecked(int(self.config.get('settings', 'nsfw')))
|
||||
self.ui.sfwCheckBox.setChecked(int(self.config.get('settings', 'sfw')))
|
||||
|
||||
self.connect(self.ui.searchEdit, SIGNAL("returnPressed()"), self.search)
|
||||
self.connect(self.ui.urlEdit, SIGNAL("returnPressed()"), self.openURL)
|
||||
self.connect(self.ui.nsfwCheckBox, SIGNAL("stateChanged(int)"), self.nsfwChanged)
|
||||
self.connect(self.ui.sfwCheckBox, SIGNAL("stateChanged(int)"), self.sfwChanged)
|
||||
|
||||
def nsfwChanged(self, state):
|
||||
self.config.set('settings', 'nsfw', int(self.ui.nsfwCheckBox.isChecked()))
|
||||
self.updateVideosDisplay()
|
||||
|
||||
def sfwChanged(self, state):
|
||||
self.config.set('settings', 'sfw', int(self.ui.sfwCheckBox.isChecked()))
|
||||
self.updateVideosDisplay()
|
||||
|
||||
def updateVideosDisplay(self):
|
||||
for minivideo in self.minivideos:
|
||||
if (minivideo.video.nsfw and self.ui.nsfwCheckBox.isChecked() or
|
||||
not minivideo.video.nsfw and self.ui.sfwCheckBox.isChecked()):
|
||||
minivideo.show()
|
||||
else:
|
||||
minivideo.hide()
|
||||
|
||||
def search(self):
|
||||
pattern = unicode(self.ui.searchEdit.text())
|
||||
if not pattern:
|
||||
return
|
||||
|
||||
for minivideo in self.minivideos:
|
||||
self.ui.scrollAreaContent.layout().removeWidget(minivideo)
|
||||
minivideo.hide()
|
||||
|
||||
self.minivideos = []
|
||||
self.ui.searchEdit.setEnabled(False)
|
||||
|
||||
backend_name = str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString())
|
||||
|
||||
self.process = QtDo(self.weboob, self.addVideo)
|
||||
if backend_name:
|
||||
self.process.do_backends(backend_name, 'iter_search_results', pattern, self.ui.sortbyEdit.currentIndex(), nsfw=True)
|
||||
else:
|
||||
self.process.do('iter_search_results', pattern, self.ui.sortbyEdit.currentIndex(), nsfw=True)
|
||||
|
||||
def addVideo(self, backend, video):
|
||||
if not backend:
|
||||
self.ui.searchEdit.setEnabled(True)
|
||||
return
|
||||
minivideo = MiniVideo(backend, video)
|
||||
self.ui.scrollAreaContent.layout().addWidget(minivideo)
|
||||
self.minivideos.append(minivideo)
|
||||
if (video.nsfw and not self.ui.nsfwCheckBox.isChecked() or
|
||||
not video.nsfw and not self.ui.sfwCheckBox.isChecked()):
|
||||
minivideo.hide()
|
||||
|
||||
def openURL(self):
|
||||
url = unicode(self.ui.urlEdit.text())
|
||||
if not url:
|
||||
return
|
||||
|
||||
for backend in self.weboob.iter_backends():
|
||||
video = backend.get_video(url)
|
||||
if video:
|
||||
video_widget = Video(video, self)
|
||||
video_widget.show()
|
||||
|
||||
self.ui.urlEdit.clear()
|
||||
|
||||
def closeEvent(self, ev):
|
||||
self.config.set('settings', 'backend', str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString()))
|
||||
self.config.set('settings', 'sortby', self.ui.sortbyEdit.currentIndex())
|
||||
self.config.save()
|
||||
ev.accept()
|
||||
62
weboob/applications/qvideoob/minivideo.py
Normal file
62
weboob/applications/qvideoob/minivideo.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# -*- 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 urllib2
|
||||
from PyQt4.QtGui import QFrame, QImage, QPixmap
|
||||
|
||||
from weboob.frontends.qvideoob.ui.minivideo_ui import Ui_MiniVideo
|
||||
from .video import Video
|
||||
|
||||
class MiniVideo(QFrame):
|
||||
def __init__(self, backend, video, parent=None):
|
||||
QFrame.__init__(self, parent)
|
||||
self.ui = Ui_MiniVideo()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.backend = backend
|
||||
self.video = video
|
||||
self.ui.titleLabel.setText(video.title)
|
||||
self.ui.backendLabel.setText(backend.name)
|
||||
self.ui.durationLabel.setText('%d:%02d:%02d' % (video.duration/3600, (video.duration%3600)/60, video.duration%60))
|
||||
self.ui.authorLabel.setText(unicode(video.author))
|
||||
self.ui.dateLabel.setText(video.date and unicode(video.date) or '')
|
||||
if video.rating_max:
|
||||
self.ui.ratingLabel.setText('%s / %s' % (video.rating, video.rating_max))
|
||||
else:
|
||||
self.ui.ratingLabel.setText('%s' % video.rating)
|
||||
|
||||
if video.thumbnail_url:
|
||||
data = urllib2.urlopen(video.thumbnail_url).read()
|
||||
img = QImage.fromData(data)
|
||||
self.ui.imageLabel.setPixmap(QPixmap.fromImage(img))
|
||||
|
||||
def enterEvent(self, event):
|
||||
self.setFrameShadow(self.Sunken)
|
||||
QFrame.enterEvent(self, event)
|
||||
|
||||
def leaveEvent(self, event):
|
||||
self.setFrameShadow(self.Raised)
|
||||
QFrame.leaveEvent(self, event)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
QFrame.mousePressEvent(self, event)
|
||||
|
||||
video = self.backend.get_video(self.video.id)
|
||||
if video:
|
||||
video_widget = Video(video, self)
|
||||
video_widget.show()
|
||||
40
weboob/applications/qvideoob/qvideoob.py
Normal file
40
weboob/applications/qvideoob/qvideoob.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# -*- 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.video import ICapVideo
|
||||
from weboob.tools.application import QtApplication
|
||||
|
||||
from .main_window import MainWindow
|
||||
|
||||
class QVideoob(QtApplication):
|
||||
APPNAME = 'qvideoob'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
CONFIG = {'settings': {'nsfw': 1,
|
||||
'sfw': 1,
|
||||
'sortby': 0,
|
||||
'backend': ''
|
||||
}
|
||||
}
|
||||
def main(self, argv):
|
||||
self.load_modules(ICapVideo)
|
||||
self.load_config()
|
||||
|
||||
self.main_window = MainWindow(self.config, self.weboob)
|
||||
self.main_window.show()
|
||||
return self.weboob.loop()
|
||||
50
weboob/applications/qvideoob/setup.py
Executable file
50
weboob/applications/qvideoob/setup.py
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#! /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-qvideoob',
|
||||
version='0.1',
|
||||
description='QVideoob, the Weboob video swiss-knife, Qt version',
|
||||
long_description='Search for videos on many websites, and get info about them',
|
||||
author='Romain Bignon',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/QVideoob',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.qvideoob',
|
||||
'weboob.frontends.qvideoob.ui',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/qvideoob',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-core-qt',
|
||||
'weboob-video-backends',
|
||||
],
|
||||
)
|
||||
13
weboob/applications/qvideoob/ui/Makefile
Normal file
13
weboob/applications/qvideoob/ui/Makefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
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)
|
||||
|
||||
0
weboob/applications/qvideoob/ui/__init__.py
Normal file
0
weboob/applications/qvideoob/ui/__init__.py
Normal file
193
weboob/applications/qvideoob/ui/main_window.ui
Normal file
193
weboob/applications/qvideoob/ui/main_window.ui
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>785</width>
|
||||
<height>594</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>QVideoob</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Search: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="sortbyEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Relevance</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Rating</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="backendEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sfwCheckBox">
|
||||
<property name="text">
|
||||
<string>SFW</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="nsfwCheckBox">
|
||||
<property name="text">
|
||||
<string>NSFW</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaContent">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>391</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QWidget#scrollAreaContent {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>URL: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="urlEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>785</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
189
weboob/applications/qvideoob/ui/minivideo.ui
Normal file
189
weboob/applications/qvideoob/ui/minivideo.ui
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MiniVideo</class>
|
||||
<widget class="QFrame" name="MiniVideo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>464</width>
|
||||
<height>132</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="imageLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<italic>true</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="durationLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="authorLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="dateLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rating</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="ratingLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Where</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="backendLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
224
weboob/applications/qvideoob/ui/video.ui
Normal file
224
weboob/applications/qvideoob/ui/video.ui
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Video</class>
|
||||
<widget class="QDialog" name="Video">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>647</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="Phonon::VideoPlayer" name="videoPlayer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Phonon::SeekSlider" name="seekSlider">
|
||||
<property name="iconVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="tracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>URL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="urlEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>ArrowCursor</cursorShape>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="durationLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="authorLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="dateLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rating</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="ratingLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Phonon::VideoPlayer</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">phonon/videoplayer.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Phonon::SeekSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">phonon/seekslider.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
49
weboob/applications/qvideoob/video.py
Normal file
49
weboob/applications/qvideoob/video.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# -*- 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 QUrl
|
||||
from PyQt4.QtGui import QDialog
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
from weboob.frontends.qvideoob.ui.video_ui import Ui_Video
|
||||
|
||||
class Video(QDialog):
|
||||
def __init__(self, video, parent=None):
|
||||
QDialog.__init__(self, parent)
|
||||
self.ui = Ui_Video()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.video = video
|
||||
self.setWindowTitle("Video - %s" % video.title)
|
||||
self.ui.urlEdit.setText(video.url)
|
||||
self.ui.titleLabel.setText(video.title)
|
||||
self.ui.durationLabel.setText('%d:%02d:%02d' % (video.duration/3600, (video.duration%3600)/60, video.duration%60))
|
||||
self.ui.authorLabel.setText(unicode(video.author))
|
||||
self.ui.dateLabel.setText(unicode(video.date))
|
||||
if video.rating_max:
|
||||
self.ui.ratingLabel.setText('%s / %s' % (video.rating, video.rating_max))
|
||||
else:
|
||||
self.ui.ratingLabel.setText('%s' % video.rating)
|
||||
|
||||
self.ui.seekSlider.setMediaObject(self.ui.videoPlayer.mediaObject())
|
||||
self.ui.videoPlayer.load(Phonon.MediaSource(QUrl(video.url)))
|
||||
self.ui.videoPlayer.play()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.ui.videoPlayer.stop()
|
||||
event.accept()
|
||||
20
weboob/applications/travel/__init__.py
Normal file
20
weboob/applications/travel/__init__.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# -*- 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 .application import Travel
|
||||
44
weboob/applications/travel/application.py
Normal file
44
weboob/applications/travel/application.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright(C) 2010 Romain Bignon, 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 ConsoleApplication
|
||||
|
||||
|
||||
__all__ = ['Travel']
|
||||
|
||||
|
||||
class Travel(ConsoleApplication):
|
||||
APPNAME = 'travel'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
|
||||
def main(self, argv):
|
||||
self.load_modules(ICapTravel)
|
||||
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('Search stations')
|
||||
def command_stations(self, pattern):
|
||||
for backend, station in self.weboob.do('iter_station_search', pattern):
|
||||
self.format(station, backend.name)
|
||||
|
||||
@ConsoleApplication.command('List all departures for a given station')
|
||||
def command_departures(self, station, arrival=None):
|
||||
for backend, departure in self.weboob.do('iter_station_departures', station, arrival):
|
||||
self.format(departure, backend.name)
|
||||
46
weboob/applications/travel/setup.py
Executable file
46
weboob/applications/travel/setup.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#! /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-travel',
|
||||
version='0.1',
|
||||
description='The Weboob travel swiss-knife',
|
||||
long_description='Search for train stations and departure timegrids',
|
||||
author='Romain Bignon',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/Travel',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.travel',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/travel',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-travel-backends',
|
||||
],
|
||||
)
|
||||
19
weboob/applications/videoob/__init__.py
Normal file
19
weboob/applications/videoob/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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 .videoob import Videoob
|
||||
46
weboob/applications/videoob/setup.py
Executable file
46
weboob/applications/videoob/setup.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#! /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-videoob',
|
||||
version='0.1',
|
||||
description='Videoob, the Weboob video swiss-knife',
|
||||
long_description='Search for videos on many websites, and get info about them',
|
||||
author='Christophe Benz',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/Videoob',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.videoob',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/videoob',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-video-backends',
|
||||
],
|
||||
)
|
||||
54
weboob/applications/videoob/videoob.py
Normal file
54
weboob/applications/videoob/videoob.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
# Copyright(C) 2010 Christophe Benz, 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.video import ICapVideo
|
||||
from weboob.tools.application import ConsoleApplication
|
||||
|
||||
|
||||
__all__ = ['Videoob']
|
||||
|
||||
|
||||
class Videoob(ConsoleApplication):
|
||||
APPNAME = 'videoob'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Christophe Benz, Romain Bignon'
|
||||
CONFIG = {}
|
||||
|
||||
def add_application_options(self, group):
|
||||
group.add_option('--nsfw', action='store_true', help='enable non-suitable for work videos')
|
||||
|
||||
def main(self, argv):
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('Get video information (accept ID or URL)')
|
||||
def command_info(self, _id):
|
||||
_id, backend_name = self.parse_id(_id)
|
||||
names = (backend_name,) if backend_name is not None else None
|
||||
self.load_modules(ICapVideo, names=names)
|
||||
for backend, video in self.weboob.do('get_video', _id):
|
||||
if video is None:
|
||||
continue
|
||||
self.format(video, backend.name)
|
||||
|
||||
@ConsoleApplication.command('Search videos')
|
||||
def command_search(self, pattern=None):
|
||||
self.load_modules(ICapVideo)
|
||||
self.set_header(u'Search pattern: %s' % pattern if pattern else u'Last videos')
|
||||
for backend, video in self.weboob.do('iter_search_results', pattern=pattern, nsfw=self.options.nsfw):
|
||||
self.format(video, backend.name)
|
||||
19
weboob/applications/videoob_web/__init__.py
Normal file
19
weboob/applications/videoob_web/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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 .videoob_web import VideoobWeb
|
||||
5
weboob/applications/videoob_web/public/style.css
Normal file
5
weboob/applications/videoob_web/public/style.css
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.video-item
|
||||
{
|
||||
margin-bottom: 5ex;
|
||||
margin-left: 2em;
|
||||
}
|
||||
48
weboob/applications/videoob_web/setup.py
Executable file
48
weboob/applications/videoob_web/setup.py
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#! /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-videoob-web',
|
||||
version='0.1',
|
||||
description='Videoob-web, the Weboob video swiss-knife, web server version',
|
||||
long_description='Search for videos on many websites, and get info about them',
|
||||
author='Christophe Benz',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/VideoobWeb',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.videoob_web',
|
||||
'weboob.frontends.videoob_web.public',
|
||||
'weboob.frontends.videoob_web.templates',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/videoob-web-server',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-video-backends',
|
||||
],
|
||||
)
|
||||
17
weboob/applications/videoob_web/templates/base.mako
Normal file
17
weboob/applications/videoob_web/templates/base.mako
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
## -*- coding: utf-8 -*-
|
||||
|
||||
<%def name="title()" filter="trim">
|
||||
Videoob Web
|
||||
</%def>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>${self.title()}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
${next.css()}
|
||||
</head>
|
||||
<body>
|
||||
${next.body()}
|
||||
</body>
|
||||
</html>
|
||||
43
weboob/applications/videoob_web/templates/index.mako
Normal file
43
weboob/applications/videoob_web/templates/index.mako
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
## -*- coding: utf-8 -*-
|
||||
|
||||
<%inherit file="base.mako"/>
|
||||
|
||||
<%def name="css()" filter="trim">
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
</%def>
|
||||
|
||||
<%def name="video_item(item)">
|
||||
<div class="video-item">
|
||||
<a href="${item['page_url']}">
|
||||
<img src="${item['thumbnail_url']}" alt="${item['title']}"/>
|
||||
<br/>
|
||||
${item['title']}
|
||||
</a>
|
||||
## (<a href="${item['url']}"><em>download</em></a>)
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="body()">
|
||||
<h1>Videoob Web</h1>
|
||||
<div id="search">
|
||||
<form action="/" method="get">
|
||||
<label for="q">Search pattern:</label>
|
||||
<input id="q" type="text" name="q" value="${form_data['q']}" />
|
||||
<input type="submit" value="Search" />
|
||||
</form>
|
||||
</div>
|
||||
<div id="results">
|
||||
% if merge:
|
||||
% for item in results:
|
||||
${video_item(item)}
|
||||
% endfor
|
||||
% else:
|
||||
% for backend, items in sorted(results.iteritems()):
|
||||
<h2>${backend}</h2>
|
||||
% for item in items:
|
||||
${video_item(item)}
|
||||
% endfor
|
||||
% endfor
|
||||
% endif
|
||||
</div>
|
||||
</%def>
|
||||
110
weboob/applications/videoob_web/videoob_web.py
Normal file
110
weboob/applications/videoob_web/videoob_web.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# -*- 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 os
|
||||
|
||||
from mako.lookup import TemplateLookup
|
||||
from mako.runtime import Context
|
||||
from routes import Mapper
|
||||
from StringIO import StringIO
|
||||
from webob.dec import wsgify
|
||||
from webob import exc
|
||||
from wsgiref.simple_server import make_server
|
||||
|
||||
from weboob.capabilities.video import ICapVideo
|
||||
from weboob.tools.application import BaseApplication
|
||||
|
||||
|
||||
__all__ = ['VideoobWeb']
|
||||
|
||||
|
||||
template_lookup = TemplateLookup(directories=[os.path.join(os.path.dirname(__file__), 'templates')],
|
||||
output_encoding='utf-8', encoding_errors='replace')
|
||||
|
||||
|
||||
class VideoobWeb(BaseApplication):
|
||||
APPNAME = 'videoob-web'
|
||||
CONFIG = dict(host='localhost', port=8080)
|
||||
|
||||
@wsgify
|
||||
def make_app(self, req):
|
||||
map = Mapper()
|
||||
map.connect('index', '/', method='index')
|
||||
|
||||
results = map.routematch(environ=req.environ)
|
||||
if results:
|
||||
match, route = results
|
||||
req.urlvars = ((), match)
|
||||
kwargs = match.copy()
|
||||
method = kwargs.pop('method')
|
||||
return getattr(self, method)(req, **kwargs)
|
||||
else:
|
||||
public_path = os.path.join(os.path.dirname(__file__), 'public')
|
||||
if not os.path.exists(public_path):
|
||||
return exc.HTTPNotFound()
|
||||
path = req.path
|
||||
if path.startswith('/'):
|
||||
path = path[1:]
|
||||
public_file_path = os.path.join(public_path, path)
|
||||
if os.path.exists(public_file_path):
|
||||
if path.endswith('.css'):
|
||||
req.response.content_type = 'text/css'
|
||||
elif path.endswith('.js'):
|
||||
req.response.content_type = 'text/javascript'
|
||||
return open(public_file_path, 'r').read().strip()
|
||||
else:
|
||||
return exc.HTTPNotFound()
|
||||
|
||||
def main(self, argv):
|
||||
self.load_config()
|
||||
self.weboob.load_modules(ICapVideo)
|
||||
print 'Web server created. Listening on http://%s:%s' % (
|
||||
self.config.get('host'), int(self.config.get('port')))
|
||||
srv = make_server(self.config.get('host'), int(self.config.get('port')), self.make_app)
|
||||
srv.serve_forever()
|
||||
|
||||
def index(self, req):
|
||||
c = {}
|
||||
nsfw = req.params.get('nsfw')
|
||||
nsfw = False if not nsfw or nsfw == '0' else True
|
||||
q = req.params.get('q', u'')
|
||||
merge = req.params.get('merge')
|
||||
merge = False if not merge or merge == '0' else True
|
||||
c['merge'] = merge
|
||||
c['form_data'] = dict(q=q)
|
||||
c['results'] = [] if merge else {}
|
||||
if q:
|
||||
for backend in self.weboob.iter_backends():
|
||||
videos = [dict(title=video.title,
|
||||
page_url=video.page_url,
|
||||
url=video.url if video.url else '/download?id=%s' % video.id,
|
||||
thumbnail_url=video.thumbnail_url,
|
||||
) \
|
||||
for video in backend.iter_search_results(pattern=q, nsfw=nsfw)]
|
||||
if videos:
|
||||
if merge:
|
||||
c['results'].extend(videos)
|
||||
else:
|
||||
c['results'][backend.name] = videos
|
||||
if merge:
|
||||
c['results'] = sorted(c['results'], key=lambda video: video['title'].lower())
|
||||
template = template_lookup.get_template('index.mako')
|
||||
buf = StringIO()
|
||||
ctx = Context(buf, **c)
|
||||
template.render_context(ctx)
|
||||
return buf.getvalue().strip()
|
||||
19
weboob/applications/weboobcfg/__init__.py
Normal file
19
weboob/applications/weboobcfg/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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 .weboobcfg import WeboobCfg
|
||||
178
weboob/applications/weboobcfg/weboobcfg.py
Normal file
178
weboob/applications/weboobcfg/weboobcfg.py
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright(C) 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.
|
||||
|
||||
import ConfigParser
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
from weboob.tools.application import ConsoleApplication
|
||||
|
||||
|
||||
__all__ = ['WeboobCfg']
|
||||
|
||||
|
||||
class WeboobCfg(ConsoleApplication):
|
||||
APPNAME = 'weboobcfg'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
|
||||
def main(self, argv):
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
def caps_included(self, modcaps, caps):
|
||||
modcaps = [x.__name__ for x in modcaps]
|
||||
for cap in caps:
|
||||
if not cap in modcaps:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ConsoleApplication.command('List modules')
|
||||
def command_modules(self, *caps):
|
||||
print ' Name Capabilities Description '
|
||||
print '+--------------+----------------------+----------------------------------------+'
|
||||
self.weboob.modules_loader.load()
|
||||
for name, module in self.weboob.modules_loader.modules.iteritems():
|
||||
if caps and not self.caps_included(module.iter_caps(), caps):
|
||||
continue
|
||||
|
||||
first_line = True
|
||||
for cap in module.iter_caps():
|
||||
if first_line:
|
||||
print ' %-14s %-21s %s' % (name, cap.__name__, module.get_description())
|
||||
first_line = False
|
||||
else:
|
||||
print ' %s' % cap.__name__
|
||||
|
||||
@ConsoleApplication.command('List applications')
|
||||
def command_applications(self, *caps):
|
||||
import weboob.frontends
|
||||
path = weboob.frontends.__path__[0]
|
||||
frontends = []
|
||||
regexp = re.compile('^%s/([\w\d_]+)$' % path)
|
||||
for root, dirs, files in os.walk(path):
|
||||
m = regexp.match(root)
|
||||
if m and '__init__.py' in files:
|
||||
frontends.append(m.group(1))
|
||||
|
||||
print ' '.join(frontends)
|
||||
|
||||
@ConsoleApplication.command('Display a module')
|
||||
def command_modinfo(self, name):
|
||||
try:
|
||||
module = self.weboob.modules_loader.get_or_load_module(name)
|
||||
except KeyError:
|
||||
logging.error('No such module: %s' % name)
|
||||
return 1
|
||||
|
||||
print '.------------------------------------------------------------------------------.'
|
||||
print '| Module %-69s |' % module.get_name()
|
||||
print "+-----------------.------------------------------------------------------------'"
|
||||
print '| Version | %s' % module.get_version()
|
||||
print '| Maintainer | %s' % module.get_maintainer()
|
||||
print '| License | %s' % module.get_license()
|
||||
print '| Description | %s' % module.get_description()
|
||||
print '| Capabilities | %s' % ', '.join([cap.__name__ for cap in module.iter_caps()])
|
||||
first = True
|
||||
for key, field in module.get_config().iteritems():
|
||||
value = field.description
|
||||
if not field.default is None:
|
||||
value += ' (default: %s)' % field.default
|
||||
if first:
|
||||
print '| | '
|
||||
print '| Configuration | %s: %s' % (key, value)
|
||||
first = False
|
||||
else:
|
||||
print '| | %s: %s' % (key, value)
|
||||
print "'-----------------' "
|
||||
|
||||
|
||||
@ConsoleApplication.command('Add a configured backend')
|
||||
def command_add(self, name, *options):
|
||||
self.weboob.modules_loader.load()
|
||||
if name not in [module_name for module_name, module in self.weboob.modules_loader.modules.iteritems()]:
|
||||
logging.error(u'Backend "%s" does not exist.' % name)
|
||||
return 1
|
||||
|
||||
params = {}
|
||||
# set backend params from command-line arguments
|
||||
for option in options:
|
||||
try:
|
||||
key, value = option.split('=', 1)
|
||||
except ValueError:
|
||||
logging.error(u'Parameters have to be formatted "key=value"')
|
||||
return 1
|
||||
params[key] = value
|
||||
# ask for params non-specified on command-line arguments
|
||||
module = self.weboob.modules_loader.get_or_load_module(name)
|
||||
asked_config = False
|
||||
for key, value in module.get_config().iteritems():
|
||||
if not asked_config:
|
||||
asked_config = True
|
||||
print u'Configuration of backend'
|
||||
print u'------------------------'
|
||||
if key not in params:
|
||||
params[key] = self.ask(' [%s] %s' % (key, value.description),
|
||||
default=value.default,
|
||||
masked=value.is_masked,
|
||||
regexp=value.regexp)
|
||||
else:
|
||||
print u' [%s] %s: %s' % (key, value.description, '(masked)' if value.is_masked else params[key])
|
||||
if asked_config:
|
||||
print u'------------------------'
|
||||
|
||||
try:
|
||||
self.weboob.backends_config.add_backend(name, name, params)
|
||||
print u'Backend "%s" successfully added to file "%s".\n'\
|
||||
'Please check configuration parameters values with "weboobcfg edit".' % (
|
||||
name, self.weboob.backends_config.confpath)
|
||||
except ConfigParser.DuplicateSectionError:
|
||||
print u'Backend "%s" is already configured in file "%s"' % (name, self.weboob.backends_config.confpath)
|
||||
response = raw_input(u'Add new instance of "%s" backend? [yN] ' % name)
|
||||
if response.lower() == 'y':
|
||||
while True:
|
||||
new_name = raw_input(u'Please give new instance name (could be "%s_1"): ' % name)
|
||||
if not new_name:
|
||||
continue
|
||||
try:
|
||||
self.weboob.backends_config.add_backend(new_name, name, params)
|
||||
print u'Backend "%s" successfully added to file "%s".\n'\
|
||||
'Please check configuration parameters values with "weboobcfg edit".' % (
|
||||
name, self.weboob.backends_config.confpath)
|
||||
break
|
||||
except ConfigParser.DuplicateSectionError:
|
||||
print u'Instance "%s" already exists for backend "%s".' % (new_name, name)
|
||||
|
||||
@ConsoleApplication.command('List backends')
|
||||
def command_list(self):
|
||||
print ' Instance Name Name Params '
|
||||
print '+---------------+--------------+------------------------------------------------+'
|
||||
for instance_name, name, params in self.weboob.backends_config.iter_backends():
|
||||
print ' %-15s %-14s %-47s' % (instance_name, name, ', '.join('%s=%s' % (key, value) for key, value in params.iteritems()))
|
||||
|
||||
@ConsoleApplication.command('Remove a backend')
|
||||
def command_remove(self, instance_name):
|
||||
try:
|
||||
self.weboob.backends_config.remove_backend(instance_name)
|
||||
except ConfigParser.NoSectionError:
|
||||
logging.error("Backend '%s' does not exist" % instance_name)
|
||||
return 1
|
||||
|
||||
@ConsoleApplication.command('Edit configuration file')
|
||||
def command_edit(self):
|
||||
subprocess.call([os.environ.get('EDITOR', 'vi'), self.weboob.backends_config.confpath])
|
||||
18
weboob/applications/weboobdebug/__init__.py
Normal file
18
weboob/applications/weboobdebug/__init__.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- 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 .weboobdebug import WeboobDebug
|
||||
45
weboob/applications/weboobdebug/weboobdebug.py
Normal file
45
weboob/applications/weboobdebug/weboobdebug.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# -*- 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
|
||||
|
||||
|
||||
class WeboobDebug(ConsoleApplication):
|
||||
APPNAME = 'weboobdebug'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Christophe Benz'
|
||||
|
||||
def main(self, argv):
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('Debug backend')
|
||||
def command_shell(self, backend_name):
|
||||
try:
|
||||
backend = self.weboob.load_modules(names=[backend_name])[backend_name]
|
||||
except KeyError:
|
||||
logging.error(u'Unable to load backend "%s"' % backend_name)
|
||||
return 1
|
||||
browser = backend.browser
|
||||
from IPython.Shell import IPShellEmbed
|
||||
shell = IPShellEmbed(argv=[])
|
||||
locs = dict(backend=backend, browser=browser, frontend=self, weboob=self.weboob)
|
||||
banner = 'Weboob debug shell\nBackend "%s" loaded.\nAvailable variables: %s' % (backend_name, locs)
|
||||
shell.set_banner(shell.IP.BANNER + '\n\n' + banner)
|
||||
shell(local_ns=locs, global_ns={})
|
||||
18
weboob/applications/weboobtests/__init__.py
Normal file
18
weboob/applications/weboobtests/__init__.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- 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 .weboobtests import WeboobTests
|
||||
44
weboob/applications/weboobtests/weboobtests.py
Normal file
44
weboob/applications/weboobtests/weboobtests.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# -*- 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 nose import run
|
||||
|
||||
from weboob.tools.application import ConsoleApplication
|
||||
|
||||
__all__ = ['WeboobTests']
|
||||
|
||||
|
||||
class WeboobTests(ConsoleApplication):
|
||||
APPNAME = 'weboobtests'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
|
||||
def main(self, argv):
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('Run tests')
|
||||
def command_run(self):
|
||||
self.load_modules()
|
||||
self.load_backends()
|
||||
|
||||
suite = []
|
||||
for backend in self.weboob.iter_backends():
|
||||
t = backend.get_test()
|
||||
if t:
|
||||
suite.append(t)
|
||||
|
||||
return run(suite=suite)
|
||||
19
weboob/applications/weboorrents/__init__.py
Normal file
19
weboob/applications/weboorrents/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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 .weboorrents import Weboorrents
|
||||
46
weboob/applications/weboorrents/setup.py
Executable file
46
weboob/applications/weboorrents/setup.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#! /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-weboorrents',
|
||||
version='0.1',
|
||||
description='Weboorrents, the Weboob bittorrent swiss-knife',
|
||||
long_description='Search for torrents on many websites, and get info about them',
|
||||
author='Romain Bignon',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/Weboorrents',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.weboorrents',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/weboorrents',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-torrent-backends',
|
||||
],
|
||||
)
|
||||
71
weboob/applications/weboorrents/weboorrents.py
Normal file
71
weboob/applications/weboorrents/weboorrents.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# -*- 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
|
||||
|
||||
from weboob.capabilities.torrent import ICapTorrent
|
||||
from weboob.tools.application import ConsoleApplication
|
||||
|
||||
|
||||
__all__ = ['Weboorrents']
|
||||
|
||||
|
||||
class Weboorrents(ConsoleApplication):
|
||||
APPNAME = 'weboorrents'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
CONFIG = {}
|
||||
|
||||
def main(self, argv):
|
||||
self.load_backends(ICapTorrent)
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('Get information about a torrent')
|
||||
def command_info(self, id):
|
||||
_id, backend_name = self.parse_id(id)
|
||||
|
||||
found = 0
|
||||
for backend, torrent in self.weboob.do_backends(backend_name, 'get_torrent', _id):
|
||||
if torrent:
|
||||
self.format(torrent, backend.name)
|
||||
found = 1
|
||||
|
||||
if not found:
|
||||
print >>sys.stderr, 'Torrent "%s" not found' % id
|
||||
|
||||
@ConsoleApplication.command('Get the torrent file')
|
||||
def command_getfile(self, id, dest):
|
||||
_id, backend_name = self.parse_id(id)
|
||||
|
||||
for backend, buf in self.weboob.do_backends(backend_name, 'get_torrent_file', _id):
|
||||
if buf:
|
||||
if dest == '-':
|
||||
print buf
|
||||
else:
|
||||
with open(dest, 'w') as f:
|
||||
f.write(buf)
|
||||
return
|
||||
|
||||
print >>sys.stderr, 'Torrent "%s" not found' % id
|
||||
|
||||
@ConsoleApplication.command('Search torrents')
|
||||
def command_search(self, pattern=None):
|
||||
self.set_header(u'Search pattern: %s' % pattern if pattern else u'Last torrents')
|
||||
for backend, torrent in self.weboob.do('iter_torrents', pattern=pattern):
|
||||
self.format(torrent, backend.name)
|
||||
19
weboob/applications/wetboobs/__init__.py
Normal file
19
weboob/applications/wetboobs/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# -*- 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 .wetboobs import WetBoobs
|
||||
45
weboob/applications/wetboobs/setup.py
Executable file
45
weboob/applications/wetboobs/setup.py
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
#! /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-wetboobs',
|
||||
version='0.1',
|
||||
description='Wetboobs, the Weboob weather forecast swiss-knife',
|
||||
author='Romain Bignon',
|
||||
author_email='weboob@lists.symlink.me',
|
||||
license='GPLv3',
|
||||
url='http://weboob.org/Wetboobs',
|
||||
namespace_packages = ['weboob', 'weboob.frontends'],
|
||||
packages=[
|
||||
'weboob',
|
||||
'weboob.frontends',
|
||||
'weboob.frontends.wetboobs',
|
||||
],
|
||||
scripts=[
|
||||
'scripts/wetboobs',
|
||||
],
|
||||
install_requires=[
|
||||
'weboob-weather-backends',
|
||||
],
|
||||
)
|
||||
66
weboob/applications/wetboobs/wetboobs.py
Normal file
66
weboob/applications/wetboobs/wetboobs.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# -*- 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 logging
|
||||
|
||||
from weboob.core import CallErrors
|
||||
from weboob.capabilities.weather import ICapWeather, CityNotFound
|
||||
from weboob.tools.application import ConsoleApplication
|
||||
|
||||
|
||||
__all__ = ['WetBoobs']
|
||||
|
||||
|
||||
class WetBoobs(ConsoleApplication):
|
||||
APPNAME = 'wetboobs'
|
||||
VERSION = '0.1'
|
||||
COPYRIGHT = 'Copyright(C) 2010 Romain Bignon'
|
||||
|
||||
def main(self, argv):
|
||||
self.load_modules(ICapWeather)
|
||||
|
||||
return self.process_command(*argv[1:])
|
||||
|
||||
@ConsoleApplication.command('search cities')
|
||||
def command_search(self, pattern):
|
||||
for backend, city in self.weboob.do('iter_city_search', pattern):
|
||||
self.format(city, backend.name)
|
||||
|
||||
@ConsoleApplication.command('get current weather')
|
||||
def command_current(self, city):
|
||||
try:
|
||||
for backend, current in self.weboob.do('get_current', city):
|
||||
self.format(current, backend.name)
|
||||
except CallErrors, e:
|
||||
for error in e:
|
||||
if isinstance(error, CityNotFound):
|
||||
logging.error('City "%s" not found' % city)
|
||||
else:
|
||||
raise error
|
||||
|
||||
@ConsoleApplication.command('get forecasts')
|
||||
def command_forecasts(self, city):
|
||||
try:
|
||||
for backend, forecast in self.weboob.do('iter_forecast', city):
|
||||
self.format(forecast, backend.name)
|
||||
except CallErrors, e:
|
||||
for error in e:
|
||||
if isinstance(error, CityNotFound):
|
||||
logging.error('City "%s" not found' % city)
|
||||
else:
|
||||
raise error
|
||||
|
|
@ -216,7 +216,7 @@ class ConsoleApplication(BaseApplication):
|
|||
loaded_backends = BaseApplication.load_backends(self, caps, names, *args, **kwargs)
|
||||
if not loaded_backends:
|
||||
logging.error(u'Cannot start application: no configured backend was found.\nHere is a list of all available backends:')
|
||||
from weboob.frontends.weboobcfg import WeboobCfg
|
||||
from weboob.applications.weboobcfg import WeboobCfg
|
||||
weboobcfg = WeboobCfg()
|
||||
if caps is not None:
|
||||
if not isinstance(caps, (list, tuple, set)):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue