support new API (closes #871,#900,#902)

This commit is contained in:
Romain Bignon 2012-08-04 15:51:47 +02:00
commit c383960729
5 changed files with 205 additions and 333 deletions

View file

@ -30,7 +30,7 @@ class AntiSpam(object):
# Check if there is an email address in the offer. # Check if there is an email address in the offer.
if re.match('^[\w\d\.\-_]+@[\w\d\.]+ vous offre la pos', resume): if re.match('^[\w\d\.\-_]+@[\w\d\.]+ vous offre la pos', resume):
return False return False
if thread['member']['pseudo'] == 'Ekaterina': if thread['who']['pseudo'] == 'Ekaterina':
return False return False
return True return True
@ -39,13 +39,13 @@ class AntiSpam(object):
# The name of profile is in form #123456789 # The name of profile is in form #123456789
if profile['pseudo'] == '': if profile['pseudo'] == '':
return False return False
if profile['about1'].startswith('salut! je te donne mon msn'): if profile['announce'].startswith('salut! je te donne mon msn'):
return False return False
if profile['about2'].startswith('cam to cam'): if profile['shopping_list'].startswith('cam to cam'):
return False return False
if profile['about2'].startswith('je suis une femme tres tres belle et je recherche un homme qui aime le sexe'): if profile['shopping_list'].startswith('je suis une femme tres tres belle et je recherche un homme qui aime le sexe'):
return False return False
if profile['about2'].endswith('mmmmmmmmmmmmmmmm'): if profile['shopping_list'].endswith('mmmmmmmmmmmmmmmm'):
return False return False
return True return True

View file

@ -65,7 +65,8 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
CONFIG = BackendConfig(Value('username', label='Username'), CONFIG = BackendConfig(Value('username', label='Username'),
ValueBackendPassword('password', label='Password'), ValueBackendPassword('password', label='Password'),
ValueBool('antispam', label='Enable anti-spam', default=False), ValueBool('antispam', label='Enable anti-spam', default=False),
ValueBool('baskets', label='Get baskets with new messages', default=True)) ValueBool('baskets', label='Get baskets with new messages', default=True),
Value('search_query', label='Search query', default=''))
STORAGE = {'profiles_walker': {'viewed': []}, STORAGE = {'profiles_walker': {'viewed': []},
'queries_queue': {'queue': []}, 'queries_queue': {'queue': []},
'sluts': {}, 'sluts': {},
@ -83,11 +84,14 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
self.antispam = None self.antispam = None
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['username'].get(), self.config['password'].get()) return self.create_browser(self.config['username'].get(),
self.config['password'].get(),
self.config['search_query'].get())
def report_spam(self, id): def report_spam(self, id):
with self.browser: with self.browser:
self.browser.delete_thread(id) pass
#self.browser.delete_thread(id)
# Do not report fakes to website, to let them to other guys :) # Do not report fakes to website, to let them to other guys :)
#self.browser.report_fake(id) #self.browser.report_fake(id)
@ -106,15 +110,12 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
all_events[u'visits'] = (self.browser.get_visits, 'Visited by %s') all_events[u'visits'] = (self.browser.get_visits, 'Visited by %s')
for type, (events, message) in all_events.iteritems(): for type, (events, message) in all_events.iteritems():
for event in events(): for event in events():
try: e = Event(event['who']['id'])
e = Event(event['%sid' % type[0]])
except KeyError:
e = Event(event['id'])
e.date = parse_dt(event['date']) e.date = parse_dt(event['date'])
e.type = type e.type = type
if 'member' in event: if 'who' in event:
e.contact = self._get_partial_contact(event['member']) e.contact = self._get_partial_contact(event['who'])
else: else:
e.contact = self._get_partial_contact(event) e.contact = self._get_partial_contact(event)
@ -134,17 +135,17 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
threads = self.browser.get_threads_list() threads = self.browser.get_threads_list()
for thread in threads: for thread in threads:
if thread['member'].get('isBan', thread['member'].get('dead', False)): #if thread['member'].get('isBan', thread['member'].get('dead', False)):
with self.browser: # with self.browser:
self.browser.delete_thread(thread['member']['id']) # self.browser.delete_thread(thread['member']['id'])
continue # continue
if self.antispam and not self.antispam.check_thread(thread): if self.antispam and not self.antispam.check_thread(thread):
self.logger.info('Skipped a spam-thread from %s' % thread['pseudo']) self.logger.info('Skipped a spam-thread from %s' % thread['pseudo'])
self.report_spam(thread['member']['id']) self.report_spam(thread['who']['id'])
continue continue
t = Thread(int(thread['member']['id'])) t = Thread(int(thread['who']['id']))
t.flags = Thread.IS_DISCUSSION t.flags = Thread.IS_DISCUSSION
t.title = u'Discussion with %s' % to_unicode(thread['member']['pseudo']) t.title = u'Discussion with %s' % to_unicode(thread['who']['pseudo'])
yield t yield t
def get_thread(self, id, contacts=None, get_profiles=False): def get_thread(self, id, contacts=None, get_profiles=False):
@ -176,15 +177,15 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
contacts = {} contacts = {}
if not thread.title: if not thread.title:
thread.title = u'Discussion with %s' % mails['member']['pseudo'] thread.title = u'Discussion with %s' % mails['who']['pseudo']
self.storage.set('sluts', int(thread.id), 'status', mails['status']) self.storage.set('sluts', int(thread.id), 'status', mails['status'])
self.storage.save() self.storage.save()
for mail in mails['messages']: for mail in mails['results']:
flags = 0 flags = 0
if self.antispam and not self.antispam.check_mail(mail): if self.antispam and not self.antispam.check_mail(mail):
self.logger.info('Skipped a spam-mail from %s' % mails['member']['pseudo']) self.logger.info('Skipped a spam-mail from %s' % mails['who']['pseudo'])
self.report_spam(thread.id) self.report_spam(thread.id)
break break
@ -192,31 +193,31 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
flags |= Message.IS_UNREAD flags |= Message.IS_UNREAD
if get_profiles: if get_profiles:
if not mail['id_from'] in contacts: if not mail['from'] in contacts:
with self.browser: with self.browser:
contacts[mail['id_from']] = self.get_contact(mail['id_from']) contacts[mail['from']] = self.get_contact(mail['from'])
if self.antispam and not self.antispam.check_contact(contacts[mail['id_from']]): if self.antispam and not self.antispam.check_contact(contacts[mail['from']]):
self.logger.info('Skipped a spam-mail-profile from %s' % mails['member']['pseudo']) self.logger.info('Skipped a spam-mail-profile from %s' % mails['who']['pseudo'])
self.report_spam(thread.id) self.report_spam(thread.id)
break break
if int(mail['id_from']) == self.browser.my_id: if int(mail['from']) == self.browser.my_id:
if int(mails['remoteStatus']) == 0 and msg is None: if mails['remote_status'] == 'new' and msg is None:
flags |= Message.IS_NOT_RECEIVED flags |= Message.IS_NOT_RECEIVED
else: else:
flags |= Message.IS_RECEIVED flags |= Message.IS_RECEIVED
signature = u'' signature = u''
if mail.get('src', None): #if mail.get('src', None):
signature += u'Sent from my %s\n\n' % mail['src'] # signature += u'Sent from my %s\n\n' % mail['src']
if mail['id_from'] in contacts: if mail['from'] in contacts:
signature += contacts[mail['id_from']].get_text() signature += contacts[mail['from']].get_text()
msg = Message(thread=thread, msg = Message(thread=thread,
id=int(time.strftime('%Y%m%d%H%M%S', parse_dt(mail['date']).timetuple())), id=int(time.strftime('%Y%m%d%H%M%S', parse_dt(mail['date']).timetuple())),
title=thread.title, title=thread.title,
sender=to_unicode(my_name if int(mail['id_from']) == self.browser.my_id else mails['member']['pseudo']), sender=to_unicode(my_name if int(mail['from']) == self.browser.my_id else mails['who']['pseudo']),
receivers=[to_unicode(my_name if int(mail['id_from']) != self.browser.my_id else mails['member']['pseudo'])], receivers=[to_unicode(my_name if int(mail['from']) != self.browser.my_id else mails['who']['pseudo'])],
date=parse_dt(mail['date']), date=parse_dt(mail['date']),
content=to_unicode(unescape(mail['message'] or '').strip()), content=to_unicode(unescape(mail['message'] or '').strip()),
signature=signature, signature=signature,
@ -246,17 +247,17 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
with self.browser: with self.browser:
threads = self.browser.get_threads_list() threads = self.browser.get_threads_list()
for thread in threads: for thread in threads:
if thread['member'].get('isBan', thread['member'].get('dead', False)): #if thread['member'].get('isBan', thread['member'].get('dead', False)):
with self.browser: # with self.browser:
self.browser.delete_thread(int(thread['member']['id'])) # self.browser.delete_thread(int(thread['member']['id']))
continue # continue
if self.antispam and not self.antispam.check_thread(thread): if self.antispam and not self.antispam.check_thread(thread):
self.logger.info('Skipped a spam-unread-thread from %s' % thread['member']['pseudo']) self.logger.info('Skipped a spam-unread-thread from %s' % thread['who']['pseudo'])
self.report_spam(thread['member']['id']) self.report_spam(thread['member']['id'])
continue continue
slut = self._get_slut(thread['member']['id']) slut = self._get_slut(thread['who']['id'])
if parse_dt(thread['date']) > slut['lastmsg'] or int(thread['status']) != int(slut['status']): if parse_dt(thread['date']) > slut['lastmsg'] or thread['status'] != slut['status']:
t = self.get_thread(thread['member']['id'], contacts, get_profiles=True) t = self.get_thread(thread['who']['id'], contacts, get_profiles=True)
for m in t.iter_all_messages(): for m in t.iter_all_messages():
if m.flags & m.IS_UNREAD: if m.flags & m.IS_UNREAD:
yield m yield m
@ -275,7 +276,7 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
baskets = self.browser.get_baskets() baskets = self.browser.get_baskets()
my_name = self.browser.get_my_name() my_name = self.browser.get_my_name()
for basket in baskets: for basket in baskets:
if basket['isBan'] or parse_dt(basket['date']) <= slut['lastmsg']: if parse_dt(basket['date']) <= slut['lastmsg']:
continue continue
contact = self.get_contact(basket['id']) contact = self.get_contact(basket['id'])
if self.antispam and not self.antispam.check_contact(contact): if self.antispam and not self.antispam.check_contact(contact):
@ -321,12 +322,12 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
sluts = self.storage.get('sluts') sluts = self.storage.get('sluts')
if not sluts or not id in sluts: if not sluts or not id in sluts:
slut = {'lastmsg': datetime.datetime(1970,1,1), slut = {'lastmsg': datetime.datetime(1970,1,1),
'status': 0} 'status': None}
else: else:
slut = self.storage.get('sluts', id) slut = self.storage.get('sluts', id)
slut['lastmsg'] = slut.get('lastmsg', datetime.datetime(1970,1,1)).replace(tzinfo=tz.tzutc()) slut['lastmsg'] = slut.get('lastmsg', datetime.datetime(1970,1,1)).replace(tzinfo=tz.tzutc())
slut['status'] = int(slut.get('status', 0)) slut['status'] = slut.get('status', None)
return slut return slut
# ---- ICapMessagesPost methods --------------------- # ---- ICapMessagesPost methods ---------------------
@ -383,31 +384,24 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
return contact return contact
def _get_partial_contact(self, contact): def _get_partial_contact(self, contact):
if contact.get('isBan', contact.get('dead', False)):
with self.browser:
self.browser.delete_thread(int(contact['id']))
return None
s = 0 s = 0
if contact.get('isOnline', False): if contact.get('online', False):
s = Contact.STATUS_ONLINE s = Contact.STATUS_ONLINE
else: else:
s = Contact.STATUS_OFFLINE s = Contact.STATUS_OFFLINE
c = Contact(contact['id'], to_unicode(contact['pseudo']), s) c = Contact(contact['id'], to_unicode(contact['pseudo']), s)
c.url = self.browser.id2url(contact['id']) c.url = self.browser.id2url(contact['id'])
if 'birthday' in contact: if 'age' in contact:
birthday = _parse_dt(contact['birthday']) c.status_msg = u'%s old, %s' % (contact['age'], contact['city'])
age = int((datetime.datetime.now() - birthday).days / 365.25) if contact['cover'] is not None:
c.status_msg = u'%s old, %s' % (age, contact['city']) url = contact['cover'] + '/%(type)s'
if contact['cover'].isdigit() and int(contact['cover']) > 0:
url = u'http://s%s.adopteunmec.com/%s%%(type)s%s.jpg' % (contact['shard'], contact['path'], contact['cover'])
else: else:
url = u'http://s.adopteunmec.com/www/img/thumb0.gif' url = u'http://s.adopteunmec.com/www/img/thumb0.jpg'
c.set_photo(u'image%s' % contact['cover'], c.set_photo(u'image%s' % contact['cover'],
url=url % {'type': 'image'}, url=url % {'type': 'full'},
thumbnail_url=url % {'type': 'thumb0_'}) thumbnail_url=url % {'type': 'small'})
return c return c
def iter_contacts(self, status=Contact.STATUS_ALL, ids=None): def iter_contacts(self, status=Contact.STATUS_ALL, ids=None):
@ -415,7 +409,7 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
threads = self.browser.get_threads_list(count=100) threads = self.browser.get_threads_list(count=100)
for thread in threads: for thread in threads:
c = self._get_partial_contact(thread['member']) c = self._get_partial_contact(thread['who'])
if c and (c.status & status) and (not ids or c.id in ids): if c and (c.status & status) and (not ids or c.id in ids):
yield c yield c
@ -547,7 +541,6 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
StatusField('score', 'Score', self.browser.score()), StatusField('score', 'Score', self.browser.score()),
StatusField('avcharms', 'Available charms', self.browser.nb_available_charms()), StatusField('avcharms', 'Available charms', self.browser.nb_available_charms()),
StatusField('newvisits', 'New visits', self.browser.nb_new_visites()), StatusField('newvisits', 'New visits', self.browser.nb_new_visites()),
StatusField('godchilds', 'Number of godchilds', self.browser.nb_godchilds()),
) )
OBJECTS = {Thread: fill_thread, OBJECTS = {Thread: fill_thread,

View file

@ -20,15 +20,12 @@
import math import math
import re import re
import datetime
import random
import urllib import urllib
from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword, BrowserUnavailable from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword, BrowserHTTPNotFound
from weboob.tools.json import json from weboob.tools.json import json
from weboob.capabilities.base import UserError from weboob.capabilities.base import UserError
from weboob.capabilities.chat import ChatException, ChatMessage
from weboob.capabilities.messages import CantSendMessage from weboob.capabilities.messages import CantSendMessage
@ -63,16 +60,24 @@ class AuMException(UserError):
self.code = code self.code = code
class AuMBrowser(BaseBrowser): class AuMBrowser(BaseBrowser):
DOMAIN = 'api.adopteunmec.com' DOMAIN = 'www.adopteunmec.com'
APIKEY = 'fb0123456789abcd' APIKEY = 'fb0123456789abcd'
consts = None consts = None
search_query = None
my_sex = 0 my_sex = 0
my_id = 0 my_id = 0
my_name = u'' my_name = u''
my_coords = (0,0) my_coords = (0,0)
def __init__(self, username, password, search_query, *args, **kwargs):
kwargs['get_home'] = False
BaseBrowser.__init__(self, username, password, *args, **kwargs)
self.add_password('http://www.adopteunmec.com/api/', self.username, self.password)
self.home()
self.search_query = search_query
def id2url(self, id): def id2url(self, id):
return u'http://www.adopteunmec.com/index.php/profile/%s' % id return u'http://www.adopteunmec.com/index.php/profile/%s' % id
@ -88,7 +93,7 @@ class AuMBrowser(BaseBrowser):
return func(self, id, *args, **kwargs) return func(self, id, *args, **kwargs)
return inner return inner
def api_request(self, command, action, parameter='', data=None, nologin=False): def api0_request(self, command, action, parameter='', data=None, nologin=False):
if data is None: if data is None:
# Always do POST requests. # Always do POST requests.
data = '' data = ''
@ -97,11 +102,13 @@ class AuMBrowser(BaseBrowser):
elif isinstance(data, unicode): elif isinstance(data, unicode):
data = data.encode('utf-8') data = data.encode('utf-8')
url = self.buildurl(self.absurl('/api.php'), S=self.APIKEY, url = self.buildurl('http://api.adopteunmec.com/api.php',
S=self.APIKEY,
C=command, C=command,
A=action, A=action,
P=parameter, P=parameter,
O='json') O='json')
buf = self.openurl(url, data).read() buf = self.openurl(url, data).read()
try: try:
@ -109,232 +116,162 @@ class AuMBrowser(BaseBrowser):
except ValueError: except ValueError:
raise ValueError(buf) raise ValueError(buf)
#pprint(r)
if 'errors' in r and r['errors'] != '0' and len(r['errors']) > 0: if 'errors' in r and r['errors'] != '0' and len(r['errors']) > 0:
code = r['errors'][0] code = r['errors'][0]
if code in (u'0.0.2', u'1.1.1', u'1.1.2'): if code in (u'0.0.2', u'1.1.1', u'1.1.2'):
if not nologin: if not nologin:
self.login() self.login()
return self.api_request(command, action, parameter, data, nologin=True) return self.api0_request(command, action, parameter, data, nologin=True)
else: else:
raise BrowserIncorrectPassword(AuMException.ERRORS[code]) raise BrowserIncorrectPassword(AuMException.ERRORS[code])
else: else:
raise AuMException(code) raise AuMException(code)
return r
def logout(self): return r
self._ua_handlers["_cookies"].cookiejar.clear()
def login(self): def login(self):
r = self.api_request('me', 'login', data={'login': self.username, r = self.api0_request('me', 'login', data={'login': self.username,
'pass': self.password, 'pass': self.password,
}, nologin=True) }, nologin=True)
self.my_sex = r['result']['me']['sex']
self.my_id = int(r['result']['me']['id'])
self.my_name = r['result']['me']['pseudo']
self.my_coords = (float(r['result']['me']['lat']), float(r['result']['me']['lng'])) self.my_coords = (float(r['result']['me']['lat']), float(r['result']['me']['lng']))
if not self.search_query:
self.search_query = 'region=%s' % r['result']['me']['region']
def api_request(self, command, **kwargs):
if 'data' in kwargs:
data = kwargs.pop('data').encode('utf-8', 'replace')
else:
data = None
url = self.buildurl(self.absurl('/api/%s' % command), **kwargs)
buf = self.openurl(url, data).read()
try:
r = json.loads(buf)
except ValueError:
raise ValueError(buf)
return r return r
#def register(self, password, sex, birthday_d, birthday_m, birthday_y, zipcode, country, godfather=None): def home(self):
# if not self.is_on_page(RegisterPage): r = self.api_request('home/')
# self.location('http://www.adopteunmec.com/register2.php') self.my_sex = r['user']['sex']
# self.page.register(password, sex, birthday_d, birthday_m, birthday_y, zipcode, country) self.my_id = int(r['user']['id'])
# if godfather: self.my_name = r['user']['pseudo']
# if not self.is_on_page(AccountPage):
# self.location('http://www.adopteunmec.com/account.php')
# self.page.set_godfather(godfather)
#@pageaccess return r
#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)
def check_login(func):
def inner(self, *args, **kwargs):
if self.my_id == 0:
self.login()
return func(self, *args, **kwargs)
return inner
def get_consts(self): def get_consts(self):
if self.consts is not None: if self.consts is not None:
return self.consts return self.consts
self.consts = [] self.consts = [{}, {}]
for i in xrange(2): for key, sexes in self.api_request('values').iteritems():
r = self.api_request('me', 'all_values', data={'sex': i}) for sex, values in sexes.iteritems():
self.consts.append(r['result']['values']) if sex in ('boy', 'both'):
self.consts[0][key] = values
if sex in ('girl', 'both'):
self.consts[1][key] = values
return self.consts return self.consts
@check_login
def score(self): def score(self):
r = self.api_request('member', 'view', data={'id': self.my_id}) r = self.home()
return int(r['result']['member']['popu']['popu']) return int(r['user']['points'])
@check_login
def get_my_name(self): def get_my_name(self):
return self.my_name return self.my_name
@check_login
def get_my_id(self): def get_my_id(self):
return self.my_id return self.my_id
@check_login
def nb_new_mails(self): def nb_new_mails(self):
r = self.api_request('me', '[default]') r = self.home()
return r['result']['news']['newMails'] return r['counters']['new_mails']
@check_login
def nb_new_baskets(self): def nb_new_baskets(self):
r = self.api_request('me', '[default]') r = self.home()
return r['result']['news']['newBaskets'] return r['counters']['new_baskets']
@check_login
def nb_new_visites(self): def nb_new_visites(self):
r = self.api_request('me', '[default]') r = self.home()
return r['result']['news']['newVisits'] return r['counters']['new_visits']
@check_login
def nb_available_charms(self): def nb_available_charms(self):
r = self.login() r = self.home()
return r['result']['flashs'] return r['subscription']['flashes_stock']
@check_login
def nb_godchilds(self):
r = self.api_request('member', 'view', data={'id': self.my_id})
return int(r['result']['member']['popu']['invits'])
@check_login
def get_baskets(self): def get_baskets(self):
r = self.api_request('me', 'basket') r = self.api_request('basket', count=30, offset=0)
return r['result']['basket'] return r['results']
@check_login
def get_flashs(self): def get_flashs(self):
r = self.api_request('me', 'flashs') r = self.api_request('charms/', count=30, offset=0)
return r['result']['all'] return r['results']
@check_login
def get_visits(self): def get_visits(self):
# display three pages r = self.api_request('visits', count=30, offset=0)
for i in xrange(3): return r['results']
r = self.api_request('me', 'visits', data={'page': i})
for p in (r['result']['news'] + r['result']['olds']):
yield p
@check_login
def get_threads_list(self, count=30): def get_threads_list(self, count=30):
r = self.api_request('message', '[default]', '%d,0' % count) r = self.api_request('threads', count=count, offset=0)
return r['result']['threads'] return r['results']
@check_login
@url2id @url2id
def get_thread_mails(self, id, count=30): def get_thread_mails(self, id, count=30):
r = self.api_request('message', 'thread', data={'memberId': id, 'count': count}) r = self.api_request('threads/%s' % id, count=count, offset=0)
return r['result']['thread'] return r
@check_login
@url2id @url2id
def post_mail(self, id, content): def post_mail(self, id, content):
# It seems it is not needed anymore. content = content.replace('\n', '\r\n')
#new_content = u''
#for c in content:
# try:
# new_content += '&%s;' % codepoint2name[ord(c)]
# except KeyError:
# new_content += c
content = content.replace('\n', '\r\n').encode('utf-8', 'replace')
try: try:
self.api_request('message', 'new', data={'memberId': id, 'message': content}) self.api_request('threads/%s' % id, data=content)
except AuMException, e: except BrowserHTTPNotFound:
raise CantSendMessage(unicode(e)) raise CantSendMessage('Unable to send message.')
@check_login
@url2id @url2id
def delete_thread(self, id): def delete_thread(self, id):
r = self.api_request('message', 'delete', data={'id_user': id}) r = self.api_request('message', 'delete', data={'id_user': id})
self.logger.debug('Thread deleted: %r' % r) self.logger.debug('Thread deleted: %r' % r)
@check_login
@url2id @url2id
def send_charm(self, id): def send_charm(self, id):
try: try:
self.api_request('member', 'addBasket', data={'id': id}) self.api_request('users/%s/charms' % id, data='')
except AuMException: except BrowserHTTPNotFound:
return False return False
else: else:
return True return True
@check_login
@url2id @url2id
def add_basket(self, id): def add_basket(self, id):
try: try:
self.api_request('member', 'addBasket', data={'id': id}) self.api_request('basket/%s' % id, data='')
except AuMException: except BrowserHTTPNotFound:
return False return False
else: else:
return True return True
@url2id
def deblock(self, id):
self.readurl('http://www.adopteunmec.com/fajax_postMessage.php?action=deblock&to=%s' % id)
return True
@url2id
def report_fake(self, id):
return self.readurl('http://www.adopteunmec.com/fake.php', 'id=%s' % id)
@url2id
def rate(self, id, what, rating):
result = self.openurl('http://www.adopteunmec.com/fajax_vote.php', 'member=%s&what=%s&rating=%s' % (id, what, rating)).read()
return float(result)
def search_profiles(self, **kwargs): def search_profiles(self, **kwargs):
if self.search_query is None: if not self.search_query:
r = self.api_request('searchs', '[default]') # retrieve query
self.search_query = r['result']['search'] self.login()
params = {} r = self.api_request('users?count=60&offset=0&%s' % self.search_query)
for key, value in json.loads(self.search_query['query']).iteritems(): ids = [s['id'] for s in r['results']]
if isinstance(value, dict):
for k, v in value.iteritems():
params['%s%s' % (key, k.capitalize())] = v
else:
params[key] = value or ''
r = self.api_request('searchs', 'advanced', '60,0', params)
ids = [s['id'] for s in r['result']['search']]
return set(ids) return set(ids)
@url2id @url2id
def get_profile(self, id, with_pics=True): def get_profile(self, id, with_pics=True):
r = self.api_request('member', 'view', data={'id': id}) r = self.api0_request('member', 'view', data={'id': id})
if not 'result' in r: if not 'result' in r:
print r print r
profile = r['result']['member'] profile = r['result']['member']
profile.update(self.api_request('users/%s' % id))
# Calculate distance in km. # Calculate distance in km.
profile['dist'] = 0.0 profile['dist'] = 0.0
@ -352,56 +289,4 @@ class AuMBrowser(BaseBrowser):
c= 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) c= 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
profile['dist'] = R * c profile['dist'] = R * c
if with_pics:
r = self.api_request('member', 'pictures', data={'id': id})
profile['pictures'] = []
for pic in r['result']['pictures']:
d = {'hidden': False}
d.update(pic)
profile['pictures'].append(d)
return profile return profile
def _get_chat_infos(self):
try:
data = json.load(self.openurl('http://www.adopteunmec.com/1.1_cht_get.php?anticache=%f' % random.random()))
except ValueError:
raise BrowserUnavailable()
if data['error']:
raise ChatException(u'Error while getting chat infos. json:\n%s' % data)
return data
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'])
data = self._get_chat_infos()
return iter_dedupe(data['contacts'])
def iter_chat_messages(self, _id=None):
data = self._get_chat_infos()
if data['messages'] is not None:
for message in data['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

View file

@ -95,9 +95,9 @@ class FieldOld(FieldBase):
return int((datetime.now() - birthday).days / 365.25) return int((datetime.now() - birthday).days / 365.25)
class FieldSplit(FieldBase): class FieldList(FieldBase):
def get_value(self, profile, consts): def get_value(self, profile, consts):
return [html2text(s).strip() for s in profile[self.key].split(self.key2) if len(s.strip()) > 0] return profile[self.key]
class FieldBMI(FieldBase): class FieldBMI(FieldBase):
@ -126,24 +126,19 @@ class FieldBMI(FieldBase):
return 'obese' return 'obese'
class FieldFlags(FieldBase): class FieldConst(FieldBase):
def get_value(self, profile, consts): def get_value(self, profile, consts):
i = int(profile[self.key]) v = profile[self.key]
labels = [] if isinstance(v, (basestring,int)):
for d in consts[self.key]: try:
if i & (1 << int(d['value'])): return consts[self.key][str(v)]
labels.append(html2text(d['label']).strip()) except KeyError:
return labels
class FieldList(FieldBase):
def get_value(self, profile, consts):
i = int(profile[self.key])
for d in consts[self.key]:
if i == int(d['value']):
return html2text(d['label']).strip()
return '' return ''
elif isinstance(v, (tuple,list)):
labels = []
for i in v:
labels.append(consts[self.key][i])
return labels
class Contact(_Contact): class Contact(_Contact):
TABLE = OrderedDict(( TABLE = OrderedDict((
@ -165,7 +160,7 @@ class Contact(_Contact):
('bonus', FieldPopu('bonus')), ('bonus', FieldPopu('bonus')),
('score', FieldPopu('popu')), ('score', FieldPopu('popu')),
('ratio', FieldPopuRatio('mails', 'flashs')), ('ratio', FieldPopuRatio('mails', 'flashs')),
('mailable', FieldBool('mailable')), ('mailable', FieldBool('can_mail')),
))), ))),
('details', OrderedDict(( ('details', OrderedDict((
('old', FieldOld('birthday')), ('old', FieldOld('birthday')),
@ -175,69 +170,64 @@ class Contact(_Contact):
('distance', FieldDist('dist')), ('distance', FieldDist('dist')),
('country', FieldStr('country')), ('country', FieldStr('country')),
('phone', FieldStr('phone')), ('phone', FieldStr('phone')),
('eyes', FieldList('eyes')), ('eyes', FieldConst('eyes_color')),
('hair_color', FieldList('hair_color')), ('hair_color', FieldConst('hair_color')),
('hair_size', FieldList('hair_size')), ('hair_size', FieldConst('hair_size')),
('height', FieldList('size')), ('height', FieldConst('size')),
('weight', FieldList('weight')), ('weight', FieldConst('weight')),
('BMI', FieldBMI('size', 'weight')), ('BMI', FieldBMI('size', 'weight')),
('fat', FieldBMI('size', 'weight', fat=True)), ('fat', FieldBMI('size', 'weight', fat=True)),
('shape', FieldList('shape')), ('shape', FieldConst('shape')),
('origins', FieldList('origins')), ('origins', FieldConst('origins')),
('signs', FieldFlags('checks1')), ('signs', FieldConst('features')),
('job', FieldStr('job')), ('job', FieldStr('job')),
('style', FieldList('style')), ('style', FieldConst('style')),
('food', FieldList('food')), ('food', FieldConst('diet')),
('drink', FieldList('drink')), ('drink', FieldConst('alcohol')),
('smoke', FieldList('smoke')), ('smoke', FieldConst('tobacco')),
))), ))),
('tastes', OrderedDict(( ('tastes', OrderedDict((
('hobbies', FieldStr('hobbies')), ('hobbies', FieldStr('hobbies')),
('music', FieldSplit('music', '<br>')), ('music', FieldList('music')),
('cinema', FieldSplit('cinema', '<br>')), ('cinema', FieldList('cinema')),
('books', FieldSplit('books', '<br>')), ('books', FieldList('books')),
('tv', FieldSplit('tvs', '<br>')), ('tv', FieldList('tvs')),
))), ))),
('sex', OrderedDict(( ('+sex', OrderedDict((
('underwear', FieldFlags('checks7')), ('underwear', FieldConst('underwear')),
('practices', FieldFlags('checks5')), ('practices', FieldConst('sexgames')),
('favorite', FieldFlags('checks3')), ('favorite', FieldConst('arousing')),
('toys', FieldFlags('checks6')), ('toys', FieldConst('sextoys')),
))), ))),
('personality', OrderedDict(( ('+personality', OrderedDict((
('snap', FieldStr('texts1')), ('snap', FieldStr('fall_for')),
('exciting', FieldStr('texts2')), ('exciting', FieldStr('turned_on_by')),
('hate', FieldStr('texts3')), ('hate', FieldStr('cant_stand')),
('vices', FieldStr('texts4')), ('vices', FieldStr('vices')),
('assets', FieldStr('texts6')), ('assets', FieldStr('assets')),
('fantasies', FieldStr('texts5')), ('fantasies', FieldStr('fantasies')),
('is', FieldFlags('checks2')), ('is', FieldConst('character')),
))) )))
)) ))
def parse_profile(self, profile, consts): def parse_profile(self, profile, consts):
cat = int(profile.get('cat', 3)) if profile['online']:
if cat == 1:
self.status = Contact.STATUS_ONLINE self.status = Contact.STATUS_ONLINE
self.status_msg = u'online' self.status_msg = u'online'
self.status_msg = u'since %s' % profile['last_cnx'] self.status_msg = u'since %s' % profile['last_cnx']
elif cat == 2: else:
self.status = Contact.STATUS_AWAY
self.status_msg = u'away'
self.status_msg = u'connection at %s' % profile['last_cnx']
elif cat == 3:
self.status = Contact.STATUS_OFFLINE self.status = Contact.STATUS_OFFLINE
self.status_msg = u'last connection %s' % profile['last_cnx'] self.status_msg = u'last connection %s' % profile['last_cnx']
self.summary = html2text(profile.get('about1', '')).strip().replace('\n\n', '\n') self.summary = html2text(profile.get('announce', '')).strip().replace('\n\n', '\n')
if len(profile.get('about2', '')) > 0: if len(profile.get('shopping_list', '')) > 0:
self.summary += u'\n\nLooking for:\n%s' % html2text(profile['about2']).strip().replace('\n\n', '\n') self.summary += u'\n\nLooking for:\n%s' % html2text(profile['shopping_list']).strip().replace('\n\n', '\n')
for photo in profile['pictures']: for photo in profile['pics']:
self.set_photo(photo['url'].split('/')[-1], self.set_photo(photo.split('/')[-1],
url=photo['url'], url=photo + '/full',
thumbnail_url=photo['url'].replace('image', 'thumb1_'), thumbnail_url=photo + '/small',
hidden=photo['hidden']) hidden=False)
self.profile = OrderedDict() self.profile = OrderedDict()
if 'sex' in profile: if 'sex' in profile:
@ -245,7 +235,12 @@ class Contact(_Contact):
flags = ProfileNode.SECTION flags = ProfileNode.SECTION
if section.startswith('_'): if section.startswith('_'):
flags |= ProfileNode.HEAD flags |= ProfileNode.HEAD
section = section.lstrip('_') if (section.startswith('+') and int(profile['sex']) != 1) or \
(section.startswith('-') and int(profile['sex']) != 0):
continue
section = section.lstrip('_+-')
s = ProfileNode(section, section.capitalize(), OrderedDict(), flags=flags) s = ProfileNode(section, section.capitalize(), OrderedDict(), flags=flags)
for key, builder in d.iteritems(): for key, builder in d.iteritems():

View file

@ -46,7 +46,6 @@ class Visibility(Optimization):
def reconnect(self): def reconnect(self):
try: try:
with self.browser: with self.browser:
self.browser.logout()
self.browser.login() self.browser.login()
except BrowserUnavailable, e: except BrowserUnavailable, e:
print str(e) print str(e)