"
exit
}
[ -z "$1" ] && usage
pyreverse -p "$1" -a1 -s1 -o pdf "$1"
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/tools/storage_convert.py 0000775 0000000 0000000 00000000436 11415115460 0024463 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
from __future__ import with_statement
import sys
for name in sys.argv[1:]:
with open(name, 'r') as f:
lines = f.readlines()
with open(name, 'w') as f:
f.write('backends:\n')
for line in lines:
f.write(' %s' % line)
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/tools/weboob_bash_completion 0000664 0000000 0000000 00000002463 11415115460 0025332 0 ustar 00root root 0000000 0000000 # Weboob completion for Bash
#
# vim: filetype=sh expandtab softtabstop=4 shiftwidth=4
#
# 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.
#
# This script can be distributed under the same license as the
# weboob or bash packages.
have weboobcfg &&
_weboob()
{
local cur words
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
words="$(${COMP_WORDS[0]} --shell-completion)"
case ${COMP_WORDS[1]} in
*)
COMPREPLY=( $( compgen -W "$words" | grep "^$cur" ) )
;;
esac
return 0
}
[ "$have" ] || return
weboob_applications=$(weboobcfg applications)
for application in $weboob_applications
do
complete -F _weboob $application
done
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/ 0000775 0000000 0000000 00000000000 11415115460 0021014 5 ustar 00root root 0000000 0000000 woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/__init__.py 0000664 0000000 0000000 00000000070 11415115460 0023122 0 ustar 00root root 0000000 0000000 __import__('pkg_resources').declare_namespace(__name__)
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/ 0000775 0000000 0000000 00000000000 11415115460 0022566 5 ustar 00root root 0000000 0000000 woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/__init__.py 0000664 0000000 0000000 00000000070 11415115460 0024674 0 ustar 00root root 0000000 0000000 __import__('pkg_resources').declare_namespace(__name__)
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/ 0000775 0000000 0000000 00000000000 11415115460 0023350 5 ustar 00root root 0000000 0000000 woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/__init__.py 0000664 0000000 0000000 00000001416 11415115460 0025463 0 ustar 00root root 0000000 0000000 # -*- 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 .browser import AdopteUnMec
from .backend import AuMBackend
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/backend.py 0000664 0000000 0000000 00000017754 11415115460 0025327 0 ustar 00root root 0000000 0000000 # -*- 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 datetime import datetime
from dateutil import tz
import os
from logging import warning
from time import sleep
from weboob.core.backend import BaseBackend
from weboob.capabilities.chat import ICapChat
from weboob.capabilities.messages import ICapMessages, ICapMessagesReply, Message
from weboob.capabilities.dating import ICapDating, StatusField
from weboob.capabilities.contact import ICapContact, Contact
from weboob.tools.browser import BrowserUnavailable
from .browser import AdopteUnMec
from .exceptions import AdopteWait
from .optim.profiles_walker import ProfilesWalker
from .optim.visibility import Visibility
__all__ = ['AuMBackend']
class AuMBackend(BaseBackend, ICapMessages, ICapMessagesReply, ICapDating, ICapChat, ICapContact):
NAME = 'aum'
MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@peerfuse.org'
VERSION = '0.1'
LICENSE = 'GPLv3'
DESCRIPTION = u"“Adopte un mec” french dating website"
ICON = os.path.join(os.path.dirname(__file__), 'data/logo.png')
CONFIG = {'username': BaseBackend.ConfigField(description='Username on website'),
'password': BaseBackend.ConfigField(description='Password of account', is_masked=True),
}
STORAGE = {'profiles_walker': {'viewed': []},
'sluts': {},
}
BROWSER = AdopteUnMec
def default_browser(self):
return self.build_browser(self.config['username'], self.config['password'])
# Private
_profiles_walker = None
def get_status(self):
with self.browser:
return (
StatusField('myname', 'My name', self.browser.get_my_name()),
StatusField('score', 'Score', self.browser.score()),
StatusField('avcharms', 'Available charms', self.browser.nb_available_charms()),
)
def iter_messages(self, thread=None):
for message in self._iter_messages(thread, False):
yield message
def iter_new_messages(self, thread=None):
for message in self._iter_messages(thread, True):
yield message
def _get_slut(self, id):
if not id in self.storage.get('sluts'):
slut = {'lastmsg': datetime(1970,1,1),
'msgstatus': ''}
else:
slut = self.storage.get('sluts', id)
slut['lastmsg'] = slut['lastmsg'].replace(tzinfo=tz.tzutc())
return slut
def _iter_messages(self, thread, only_new):
with self.browser:
try:
profiles = {}
if thread:
slut = self._get_slut(int(thread))
for mail in self._iter_thread_messages(thread, only_new, slut['lastmsg'], {}):
if slut['lastmsg'] < mail.get_date():
slut['lastmsg'] = mail.get_date()
yield mail
self.storage.set('sluts', int(thread), slut)
self.storage.save()
else:
contacts = self.browser.get_threads_list()
for contact in contacts:
slut = self._get_slut(contact.get_id())
last_msg = slut['lastmsg']
if only_new and contact.get_lastmsg_date() < last_msg and contact.get_status() == slut['msgstatus'] or \
not thread is None and int(thread) != contact.get_id():
continue
for mail in self._iter_thread_messages(contact.get_id(), only_new, last_msg, profiles):
if last_msg < mail.get_date():
last_msg = mail.get_date()
yield mail
slut['lastmsg'] = last_msg
slut['msgstatus'] = contact.get_status()
self.storage.set('sluts', contact.get_id(), slut)
self.storage.save()
# Send mail when someone added me in her basket.
# XXX possibly race condition if a slut adds me in her basket
# between the aum.nbNewBaskets() and aum.getBaskets().
new_baskets = self.browser.nb_new_baskets()
if new_baskets:
ids = self.browser.get_baskets()
while new_baskets > 0:
new_baskets -= 1
profile = self.browser.get_profile(ids[new_baskets])
yield Message(profile.get_id(), 1,
title='Basket of %s' % profile.get_name(),
sender=profile.get_name(),
content='You are taken in her basket!',
signature=profile.get_profile_text())
except BrowserUnavailable:
pass
def _iter_thread_messages(self, id, only_new, last_msg, profiles):
mails = self.browser.get_thread_mails(id)
for mail in mails:
if only_new and mail.get_date() <= last_msg:
continue
if not mail.profile_link in profiles:
profiles[mail.profile_link] = self.browser.get_profile(mail.profile_link)
mail.signature += u'\n%s' % profiles[mail.profile_link].get_profile_text()
yield mail
def post_reply(self, thread_id, reply_id, title, message):
while 1:
try:
with self.browser:
self.browser.post_mail(thread_id, message)
except AdopteWait:
# If we are on a waiting state, retry every 30 minutes until it is posted.
sleep(60*30)
else:
return
def get_profile(self, _id):
try:
with self.browser:
return self.browser.get_profile(_id)
except BrowserUnavailable:
return None
def init_optimizations(self):
self.OPTIM_PROFILE_WALKER = ProfilesWalker(self.weboob.scheduler, self.storage, self.browser)
self.OPTIM_VISIBILITY = Visibility(self.weboob.scheduler, self.browser)
def iter_contacts(self, status=Contact.STATUS_ALL):
with self.browser:
for contact in self.browser.iter_contacts():
if contact['cat'] == 1:
s = Contact.STATUS_ONLINE
elif contact['cat'] == 3:
s = Contact.STATUS_OFFLINE
else:
warning('Unknown AuM contact status: %s' % contact['cat'])
if not status & s:
continue
# TODO age in contact['birthday']
c = Contact(contact['id'], contact['pseudo'], s)
c.status_msg = u'%s old' % contact['birthday']
c.thumbnail_url = contact['cover']
yield c
def iter_chat_messages(self, _id=None):
with self.browser:
return self.browser.iter_chat_messages(_id)
def send_chat_message(self, _id, message):
with self.browser:
return self.browser.send_chat_message(_id, message)
#def start_chat_polling(self):
#self._profile_walker = ProfilesWalker(self.weboob.scheduler, self.storage, self.browser)
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/browser.py 0000664 0000000 0000000 00000030167 11415115460 0025414 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Copyright(C) 2008-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 datetime
import time
from logging import warning
import random
try:
import json as simplejson
except ImportError:
import simplejson
import urllib
from weboob.tools.browser import BaseBrowser, BrowserUnavailable
from weboob.tools.parsers.html5libparser import Html5libParser
from weboob.backends.aum.exceptions import AdopteWait
from weboob.backends.aum.pages.home import HomePage
from weboob.backends.aum.pages.contact_list import ContactListPage
from weboob.backends.aum.pages.contact_thread import ContactThreadPage
from weboob.backends.aum.pages.baskets import BasketsPage
from weboob.backends.aum.pages.profile import ProfilePage
from weboob.backends.aum.pages.search import SearchPage
from weboob.backends.aum.pages.login import LoginPage, RedirectPage, BanPage, ErrPage, RegisterPage, RegisterWaitPage, RegisterConfirmPage, ShopPage
from weboob.backends.aum.pages.edit import EditPhotoPage, EditPhotoCbPage, EditAnnouncePage, EditDescriptionPage, EditSexPage, EditPersonalityPage
from weboob.backends.aum.pages.wait import WaitPage
from weboob.capabilities.chat import ChatException, ChatMessage
__all__ = ['AdopteUnMec']
class AdopteUnMec(BaseBrowser):
DOMAIN = 'www.adopteunmec.com'
PROTOCOL = 'http'
ENCODING = 'iso-8859-1'
PAGES = {'http://www.adopteunmec.com/': LoginPage,
'http://www.adopteunmec.com/index.html': LoginPage,
'http://www.adopteunmec.com/index.php': LoginPage,
'http://www.adopteunmec.com/loginErr.php.*': ErrPage,
'http://www.adopteunmec.com/bans.php.*': BanPage,
'http://www.adopteunmec.com/redirect.php\?action=login': RedirectPage,
'http://www.adopteunmec.com/wait.php': WaitPage,
'http://www.adopteunmec.com/register2.php': RegisterPage,
'http://www.adopteunmec.com/register3.php.*': RegisterWaitPage,
'http://www.adopteunmec.com/register4.php.*': RegisterConfirmPage,
'http://www.adopteunmec.com/home.php': HomePage,
'http://www.adopteunmec.com/shop2c.php': ShopPage,
'http://www.adopteunmec.com/mails.php': ContactListPage,
'http://www.adopteunmec.com/mails.php\?type=1': BasketsPage,
'http://www.adopteunmec.com/thread.php\?id=([0-9]+)(&see=all)?': ContactThreadPage,
'http://www.adopteunmec.com/edit.php\?type=1': EditPhotoPage,
'http://s\d+.adopteunmec.com/upload\d.php\?.*': EditPhotoCbPage,
'http://www.adopteunmec.com/edit.php\?type=2': EditAnnouncePage,
'http://www.adopteunmec.com/edit.php\?type=3': EditDescriptionPage,
'http://www.adopteunmec.com/edit.php\?type=4': EditSexPage,
'http://www.adopteunmec.com/edit.php\?type=5': EditPersonalityPage,
'http://www.adopteunmec.com/search.php.*': SearchPage,
'http://www.adopteunmec.com/searchRes.php.*': SearchPage,
'http://www.adopteunmec.com/rencontres-femmes/(.*)/([0-9]+)': ProfilePage,
'http://www.adopteunmec.com/catalogue-hommes/(.*)/([0-9]+)': ProfilePage,
'http://www.adopteunmec.com/view2.php': ProfilePage, # my own profile
'http://www.adopteunmec.com/(\w+)': ProfilePage, # a custom profile url
}
def __init__(self, *args, **kwargs):
kwargs['parser'] = Html5libParser(api='dom')
BaseBrowser.__init__(self, *args, **kwargs)
self.my_id = 0
def login(self):
if not self.is_on_page(LoginPage):
self.home()
self.page.login(self.username, self.password)
def is_logged(self):
return not self.is_on_page(LoginPage)
def home(self):
return self.location('http://www.adopteunmec.com/home.php')
def pageaccess(func):
def inner(self, *args, **kwargs):
if self.is_on_page(WaitPage):
if not self.page.check():
raise AdopteWait()
self.home()
if not self.page or self.is_on_page(LoginPage) and self.password:
self.home()
return func(self, *args, **kwargs)
return inner
def register(self, nickname, password, sex, birthday_d, birthday_m, birthday_y, zipcode, country, godfather=''):
if not self.is_on_page(RegisterPage):
self.location('http://www.adopteunmec.com/register2.php')
return self.page.register(nickname, password, sex, birthday_d, birthday_m, birthday_y, zipcode, country, godfather)
@pageaccess
def add_photo(self, name, f):
if not self.is_on_page(EditPhotoPage):
self.location('/edit.php?type=1')
return self.page.add_photo(name, f)
@pageaccess
def set_nickname(self, nickname):
if not self.is_on_page(EditAnnouncePage):
self.location('/edit.php?type=2')
return self.page.set_nickname(nickname)
@pageaccess
def set_announce(self, title=None, description=None, lookingfor=None):
if not self.is_on_page(EditAnnouncePage):
self.location('/edit.php?type=2')
return self.page.set_announce(title, description, lookingfor)
@pageaccess
def set_description(self, **args):
if not self.is_on_page(EditDescriptionPage):
self.location('/edit.php?type=3')
return self.page.set_description(**args)
@pageaccess
def score(self):
if time.time() - self.last_update > 60:
self.home()
return self.page.score()
@pageaccess
def get_my_name(self):
if time.time() - self.last_update > 60:
self.home()
return self.page.get_my_name()
@pageaccess
def get_my_id(self):
if self.my_id:
return self.my_id
if not self.is_on_page(HomePage):
self.home()
self.my_id = self.page.get_my_id()
return self.my_id
@pageaccess
def nb_new_mails(self):
if time.time() - self.last_update > 60:
self.home()
return self.page.nb_new_mails()
@pageaccess
def nb_new_baskets(self):
if time.time() - self.last_update > 60:
self.home()
return self.page.nb_new_baskets()
@pageaccess
def nb_new_visites(self):
if time.time() - self.last_update > 60:
self.home()
return self.page.nb_new_visites()
@pageaccess
def nb_available_charms(self, reload=False):
if reload or not self.is_on_page(HomePage):
self.home()
return self.page.nb_available_charms()
@pageaccess
def get_baskets(self):
self.location('/mails.php?type=1')
return self.page.get_profiles_ids_list()
@pageaccess
def flush_visits(self):
""" Does nothing, only flush new visits to increase my score """
self.openurl('/mails.php?type=3')
@pageaccess
def get_threads_list(self):
if not self.is_on_page(ContactListPage):
self.location('/mails.php')
return self.page.get_contact_list()
@pageaccess
def get_thread_mails(self, id):
if not self.is_on_page(ContactThreadPage) or self.page.get_id() != int(id):
self.page.open_thread_page(id)
return self.page.get_mails()
@pageaccess
def post_mail(self, id, content):
if not self.is_on_page(ContactThreadPage) or self.page.get_id() != int(id):
self.page.open_thread_page(id)
self.page.post(content)
@pageaccess
def send_charm(self, id):
result = self.openurl('http://www.adopteunmec.com/fajax_addBasket.php?id=%s' % id).read()
warning('Charm: %s' % result)
return result.find('noMoreFlashes') < 0
@pageaccess
def add_basket(self, id):
result = self.openurl('http://www.adopteunmec.com/fajax_addBasket.php?id=%s' % id).read()
warning('Basket: %s' % result)
# TODO check if it works (but it should)
return True
def deblock(self, id):
result = self.openurl('http://www.adopteunmec.com/fajax_postMessage.php?action=deblock&to=%s' % id).read()
warning('Deblock: %s' % result)
return True
@pageaccess
def rate(self, id, what, rating):
print 'rate "%s"' % id, what, rating
result = self.openurl('http://www.adopteunmec.com/fajax_vote.php', 'member=%s&what=%s&rating=%s' % (id, what, rating)).read()
print result
return float(result)
@pageaccess
def search_profiles(self, **kwargs):
self.location('/search.php?display=1')
self.page.search(**kwargs)
return self.page.get_profiles_ids()
@pageaccess
def get_profile(self, link):
if isinstance(link, (str,unicode)) and link.startswith('/'):
link = link[1:]
self.location('/%s' % link)
return self.page
@pageaccess
def get_slut_state(self, id):
result = self.openurl('http://www.adopteunmec.com/%s' % id).read()
if result.find('en ligne | ') >= 0:
r = 'online'
elif result.find('Cet utilisateur a quitt\xe9 le site
') >= 0:
r = 'removed'
elif result.find('ce profil a \xe9t\xe9 bloqu\xe9 par l\'\xe9quipe de mod\xe9ration
') >= 0:
r = 'removed'
elif result.find('
Cette personne
vous a bloqu\xe9
') >= 0:
r = 'blocked'
else:
r = 'offline'
print 'getSlutState(%s) = %s' % (id, r)
return r
@pageaccess
def is_slut_online(self, id):
result = self.openurl('http://www.adopteunmec.com/%s' % id).read()
r = result.find('en ligne | ') >= 0
print 'isSlutOnline(%s) = %s' % (id, r)
return r
def _get_chat_infos(self):
try:
json = simplejson.load(self.openurl('http://www.adopteunmec.com/1.1_cht_get.php?anticache=%f' % random.random()))
except simplejson.JSONDecodeError:
raise BrowserUnavailable()
if json['error']:
raise ChatException(u'Error while getting chat infos. json:\n%s' % json)
return json
def iter_contacts(self):
def iter_dedupe(contacts):
yielded_ids = set()
for contact in contacts:
if contact['id'] not in yielded_ids:
yield contact
yielded_ids.add(contact['id'])
json = self._get_chat_infos()
return iter_dedupe(json['contacts'])
def iter_chat_messages(self, _id=None):
json = self._get_chat_infos()
if json['messages'] is not None:
for message in json['messages']:
yield ChatMessage(id_from=message['id_from'], id_to=message['id_to'], message=message['message'], date=message['date'])
def send_chat_message(self, _id, message):
url = 'http://www.adopteunmec.com/1.1_cht_send.php?anticache=%f' % random.random()
data = dict(id=_id, message=message)
headers = {
'Content-type': 'application/x-www-form-urlencoded',
'Accept': 'text/plain',
'Referer': 'http://www.adopteunmec.com/chat.php',
'Origin': 'http://www.adopteunmec.com',
}
request = self.request_class(url, urllib.urlencode(data), headers)
response = self.openurl(request).read()
try:
datetime.datetime.strptime(response, '%Y-%m-%d %H:%M:%S')
return True
except ValueError:
return False
woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/data/ 0000775 0000000 0000000 00000000000 11415115460 0024261 5 ustar 00root root 0000000 0000000 woob-4ae57899af37131dc215a7ed35d1aa7b5a157e5e/weboob/backends/aum/data/logo.png 0000664 0000000 0000000 00000004217 11415115460 0025733 0 ustar 00root root 0000000 0000000 PNG
IHDR @ @ % sRGB pHYs tIME 2 !IDAThip]=!ᒅbFAE.P):J]AjVjGFvZ3.R
U[VK$D,I{O?2%عoy{s"("(Te|D.[)EtV4I?2
+eL'vI?R)FP\0BB.l0AiSN~E0:5KC+O8x>[y}!jpNqx2έ>Y98=eO&n)
oްoFĸ!Aq$~=~BOM_gdZnKa1Eb?{GC!QSeS|7ϩq>*3lL0Ɖx-|O^Ԓ6E[dzV>*=z/zTbxj.ng:4@߫kS:)D]&dؕ!K3IJB/h><B$`+;\M
f!(-G72A=ǹ^䒶F.rOG Uԣc\9]|v'ʹ"|
iJuc>UR}?-(7Ҧ3eWPx!yI ![=n$HUCKe:w%HO?D>(KJ!s7,$~f}7uOC͔.чmp)%`|ZUAdqIO|W($o::hoH%mx9/{^dcʷ'Ħ^ZƓER%
80