281 lines
12 KiB
Python
281 lines
12 KiB
Python
# -*- 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
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:
|
|
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 FieldSplit(FieldBase):
|
|
def get_value(self, profile, consts):
|
|
return [html2text(s).strip() for s in profile[self.key].split(self.key2) if len(s.strip()) > 0]
|
|
|
|
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 FieldFlags(FieldBase):
|
|
def get_value(self, profile, consts):
|
|
i = int(profile[self.key])
|
|
labels = []
|
|
for d in consts[self.key]:
|
|
if i & (1 << int(d['value'])):
|
|
labels.append(html2text(d['label']).strip())
|
|
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 ''
|
|
|
|
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')),
|
|
('baskets', FieldPopu('contacts')),
|
|
('charms', FieldPopu('flashs')),
|
|
('visites', FieldPopu('visites')),
|
|
('invits', FieldPopu('invits')),
|
|
('bonus', FieldPopu('bonus')),
|
|
('score', FieldPopu('popu')),
|
|
('ratio', FieldPopuRatio('mails', 'flashs')),
|
|
))),
|
|
('details', OrderedDict((
|
|
('old', FieldOld('birthday')),
|
|
('birthday', FieldStr('birthday')),
|
|
('zipcode', FieldStr('zip')),
|
|
('location', FieldStr('city')),
|
|
('distance', FieldDist('dist')),
|
|
('country', FieldStr('country')),
|
|
('phone', FieldStr('phone')),
|
|
('eyes', FieldList('eyes')),
|
|
('hair_color', FieldList('hair_color')),
|
|
('hair_size', FieldList('hair_size')),
|
|
('height', FieldList('size')),
|
|
('weight', FieldList('weight')),
|
|
('BMI', FieldBMI('size', 'weight')),
|
|
('fat', FieldBMI('size', 'weight', fat=True)),
|
|
('shape', FieldList('shape')),
|
|
('origins', FieldList('origins')),
|
|
('signs', FieldFlags('checks1')),
|
|
('job', FieldStr('job')),
|
|
('style', FieldList('style')),
|
|
('food', FieldList('food')),
|
|
('drink', FieldList('drink')),
|
|
('smoke', FieldList('smoke')),
|
|
))),
|
|
('tastes', OrderedDict((
|
|
('hobbies', FieldStr('hobbies')),
|
|
('music', FieldSplit('music', '<br>')),
|
|
('cinema', FieldSplit('cinema', '<br>')),
|
|
('books', FieldSplit('books', '<br>')),
|
|
('tv', FieldSplit('tvs', '<br>')),
|
|
))),
|
|
('sex', OrderedDict((
|
|
('underwear', FieldFlags('checks7')),
|
|
('practices', FieldFlags('checks5')),
|
|
('favorite', FieldFlags('checks3')),
|
|
('toys', FieldFlags('checks6')),
|
|
))),
|
|
('personality', OrderedDict((
|
|
('snap', FieldStr('texts1')),
|
|
('exciting', FieldStr('texts2')),
|
|
('hate', FieldStr('texts3')),
|
|
('vices', FieldStr('texts4')),
|
|
('assets', FieldStr('texts6')),
|
|
('fantasies', FieldStr('texts5')),
|
|
('is', FieldFlags('checks2')),
|
|
)))
|
|
))
|
|
|
|
def parse_profile(self, profile, consts):
|
|
cat = int(profile.get('cat', 3))
|
|
if cat == 1:
|
|
self.status = Contact.STATUS_ONLINE
|
|
self.status_msg = u'online'
|
|
self.status_msg = u'since %s' % profile['last_cnx']
|
|
elif cat == 2:
|
|
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_msg = u'last connection %s' % profile['last_cnx']
|
|
|
|
self.summary = html2text(profile.get('about1', '')).strip().replace('\n\n', '\n')
|
|
if len(profile.get('about2', '')) > 0:
|
|
self.summary += u'\n\nLooking for:\n%s' % html2text(profile['about2']).strip().replace('\n\n', '\n')
|
|
|
|
for photo in profile['pictures']:
|
|
self.set_photo(photo['url'].split('/')[-1],
|
|
url=photo['url'],
|
|
thumbnail_url=photo['url'].replace('image', 'thumb1_'),
|
|
hidden=photo['hidden'])
|
|
self.profile = OrderedDict()
|
|
|
|
if 'sex' in profile:
|
|
for section, d in self.TABLE.iteritems():
|
|
flags = ProfileNode.SECTION
|
|
if section.startswith('_'):
|
|
flags |= ProfileNode.HEAD
|
|
section = section.lstrip('_')
|
|
s = ProfileNode(section, section.capitalize(), OrderedDict(), flags=flags)
|
|
|
|
for key, builder in d.iteritems():
|
|
value = builder.get_value(profile, consts[int(profile['sex'])])
|
|
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
|