# -*- coding: utf-8 -*- # Copyright(C) 2008-2011 Romain Bignon # # This file is part of weboob. # # weboob is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # weboob 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . import socket from datetime import datetime from dateutil.parser import parse as parse_dt from weboob.tools.ordereddict import OrderedDict from weboob.capabilities.contact import Contact as _Contact, ProfileNode from weboob.tools.misc import html2text class FieldBase(object): def __init__(self, key, key2=None): self.key = key self.key2 = key2 def get_value(self, value, consts): raise NotImplementedError() class FieldStr(FieldBase): def get_value(self, profile, consts): return html2text(unicode(profile[self.key])).strip() class FieldBool(FieldBase): def get_value(self, profile, consts): return bool(int(profile[self.key])) class FieldDist(FieldBase): def get_value(self, profile, consts): return '%.2f km' % float(profile[self.key]) class FieldIP(FieldBase): def get_hostname(self, s): try: return socket.gethostbyaddr(s)[0] except (socket.gaierror, socket.herror): return s def get_value(self, profile, consts): s = self.get_hostname(profile[self.key]) if profile[self.key] != profile[self.key2]: s += ' (first %s)' % self.get_hostname(profile[self.key2]) return s class FieldProfileURL(FieldBase): def get_value(self, profile, consts): id = int(profile[self.key]) if id > 0: return 'http://www.adopteunmec.com/index.php/profile/%d' % id else: return '' class FieldPopu(FieldBase): def get_value(self, profile, consts): return unicode(profile['popu'][self.key]) class FieldPopuRatio(FieldBase): def get_value(self, profile, consts): v1 = float(profile['popu'][self.key]) v2 = float(profile['popu'][self.key2]) if v2 == 0.0: return 'NaN' else: return '%.2f' % (v1 / v2) class FieldOld(FieldBase): def get_value(self, profile, consts): birthday = parse_dt(profile[self.key]) return int((datetime.now() - birthday).days / 365.25) class FieldList(FieldBase): def get_value(self, profile, consts): return profile[self.key] class FieldBMI(FieldBase): def __init__(self, key, key2, fat=False): FieldBase.__init__(self, key, key2) self.fat = fat def get_value(self, profile, consts): height = int(profile[self.key]) weight = int(profile[self.key2]) if height == 0 or weight == 0: return '' bmi = (weight / float(pow(height / 100.0, 2))) if not self.fat: return bmi elif bmi < 15.5: return 'severely underweight' elif bmi < 18.4: return 'underweight' elif bmi < 24.9: return 'normal' elif bmi < 30: return 'overweight' else: return 'obese' class FieldConst(FieldBase): def get_value(self, profile, consts): v = profile[self.key] if isinstance(v, (basestring,int)): try: return consts[self.key][str(v)] except KeyError: return '' elif isinstance(v, (tuple,list)): labels = [] for i in v: labels.append(consts[self.key][i]) return labels class Contact(_Contact): TABLE = OrderedDict(( ('_info', OrderedDict(( ('title', FieldStr('title')), # ipaddr is not available anymore. #('IPaddr', FieldIP('last_ip', 'first_ip')), ('admin', FieldBool('admin')), ('ban', FieldBool('isBan')), ('first', FieldStr('first_cnx')), ('godfather', FieldProfileURL('godfather')), ))), ('_stats', OrderedDict(( ('mails', FieldPopu('mails')), ('charms', FieldPopu('charmes')), ('visites', FieldPopu('visites')), ('baskets', FieldPopu('panier')), ('invits', FieldPopu('invits')), ('bonus', FieldPopu('bonus')), ('score', FieldStr('points')), ('ratio', FieldPopuRatio('mails', 'charmes')), ('mailable', FieldBool('can_mail')), ))), ('details', OrderedDict(( ('old', FieldStr('age')), #('old', FieldOld('birthday')), ('birthday', FieldStr('birthday')), ('zipcode', FieldStr('zip')), ('location', FieldStr('city')), ('distance', FieldDist('dist')), ('country', FieldStr('country')), ('phone', FieldStr('phone')), ('eyes', FieldConst('eyes_color')), ('hair_color', FieldConst('hair_color')), ('hair_size', FieldConst('hair_size')), ('height', FieldConst('size')), ('weight', FieldConst('weight')), ('BMI', FieldBMI('size', 'weight')), ('fat', FieldBMI('size', 'weight', fat=True)), ('shape', FieldConst('shape')), ('origins', FieldConst('origins')), ('signs', FieldConst('features')), ('job', FieldStr('job')), ('style', FieldConst('style')), ('food', FieldConst('diet')), ('favorite_food', FieldConst('favourite_food')), ('drink', FieldConst('alcohol')), ('smoke', FieldConst('tobacco')), ))), ('tastes', OrderedDict(( ('hobbies', FieldStr('hobbies')), ('music', FieldList('music')), ('cinema', FieldList('cinema')), ('books', FieldList('books')), ('tv', FieldList('tvs')), ))), ('+sex', OrderedDict(( ('underwear', FieldConst('underwear')), ('practices', FieldConst('sexgames')), ('favorite', FieldConst('arousing')), ('toys', FieldConst('sextoys')), ))), ('+personality', OrderedDict(( ('snap', FieldStr('fall_for')), ('exciting', FieldStr('turned_on_by')), ('hate', FieldStr('cant_stand')), ('vices', FieldStr('vices')), ('assets', FieldStr('assets')), ('fantasies', FieldStr('fantasies')), ('is', FieldConst('character')), ))) )) def parse_profile(self, profile, consts): if profile['online']: self.status = Contact.STATUS_ONLINE self.status_msg = u'online' self.status_msg = u'since %s' % profile['last_cnx'] else: self.status = Contact.STATUS_OFFLINE self.status_msg = u'last connection %s' % profile['last_cnx'] self.summary = profile.get('announce', '').strip() if len(profile.get('shopping_list', '')) > 0: self.summary += u'\n\nLooking for:\n%s' % profile['shopping_list'].strip() for photo in profile['pics']: self.set_photo(photo.split('/')[-1], url=photo + '/full', thumbnail_url=photo + '/small', hidden=False) self.profile = OrderedDict() if 'sex' in profile: for section, d in self.TABLE.iteritems(): flags = ProfileNode.SECTION if section.startswith('_'): flags |= ProfileNode.HEAD 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) for key, builder in d.iteritems(): try: value = builder.get_value(profile, consts[int(profile['sex'])]) except KeyError: pass else: s.value[key] = ProfileNode(key, key.capitalize().replace('_', ' '), value) self.profile[section] = s self._aum_profile = profile def get_text(self): def print_node(node, level=1): result = u'' if node.flags & node.SECTION: result += u'\t' * level + node.label + '\n' for sub in node.value.itervalues(): result += print_node(sub, level + 1) else: if isinstance(node.value, (tuple, list)): value = ', '.join(unicode(v) for v in node.value) elif isinstance(node.value, float): value = '%.2f' % node.value else: value = node.value result += u'\t' * level + u'%-20s %s\n' % (node.label + ':', value) return result result = u'Nickname: %s\n' % self.name if self.status & Contact.STATUS_ONLINE: s = 'online' elif self.status & Contact.STATUS_OFFLINE: s = 'offline' elif self.status & Contact.STATUS_AWAY: s = 'away' else: s = 'unknown' result += u'Status: %s (%s)\n' % (s, self.status_msg) result += u'URL: %s\n' % self.url result += u'Photos:\n' for name, photo in self.photos.iteritems(): result += u'\t%s%s\n' % (photo, ' (hidden)' if photo.hidden else '') result += u'\nProfile:\n' for head in self.profile.itervalues(): result += print_node(head) result += u'Description:\n' for s in self.summary.split('\n'): result += u'\t%s\n' % s return result