tuenpy.py

Upload: same

Post on 01-Jun-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 tuenpy.py

    1/7

    # -*- coding: utf-8 -*-import libxml2domimport mechanizeimport urllib

    TUENTI_HOST = "http://m.tuenti.com"PROFILE_URL = "/?m=profile&user_id="URLS = {  'login': TUENTI_HOST + "/?m=login&func=process_login",  'friends': TUENTI_HOST + "/?m=friends&page=%s",  'profile': TUENTI_HOST + "/?m=profile&user_id=%s",  'comments': TUENTI_HOST + "/?m=profile&func=view_wall&user_id=%s&fpi=%s",  'my_profile': TUENTI_HOST + "/?m=profile&func=my_profile",  'set_status': TUENTI_HOST + "/?m=profile&func=process_set_status&from=home&csfr=%s",  'create_blog_entry': TUENTI_HOST + "/?t=profile_send_blog&ot=blog_entry&m=blog_entry&uid=%s",}MESSAGES = {  'login_error': "Dirección de correo o contraseña inválidos.",  'more_friends': ">Ver más amigos",  'more_comments': ">Ver más comentarios del tablón",  'wall': u"Tablón de",

      'my_wall': u"Mi tablón",  'restricted_area': "Acceso Restringido",  'status': "Estado",  'status_verb': u"está",}HTTP_RESPONSE_CODES = {  'OK': 200,  'CREATED': 201,  'ACCEPTED': 202,  'BAD_REQUEST': 400,  'UNAUTHORIZED': 401,  'NOT_FOUND': 404,  'CONFLICT': 409,

      'PRECONDITION_FAILED': 412}

    class StatusException(Exception):  """Response Error class"""  def __init__(self, value, result=None):  self.value = value  self.responses = {  100: ('Continue', 'Request received, please continue'),  101: ('Switching Protocols',  'Switching to new protocol; obey Upgrade header'),  200: ('OK', 'Request fulfilled, document follows'),

      201: ('Created', 'Document created, URL follows'),  202: ('Accepted',  'Request accepted, processing continues off-line'),  203: ('Non-Authoritative Information', 'Request fulfilled from cache'),  204: ('No Content', 'Request fulfilled, nothing follows'),  205: ('Reset Content', 'Clear input form for further input.'),  206: ('Partial Content', 'Partial content follows.'),  300: ('Multiple Choices',  'Object has several resources -- see URI list'),  301: ('Moved Permanently', 'Object moved permanently -- see URI list'),

  • 8/9/2019 tuenpy.py

    2/7

      302: ('Found', 'Object moved temporarily -- see URI list'),  303: ('See Other', 'Object moved -- see Method and URL list'),  304: ('Not Modified',  'Document has not changed since given time'),  305: ('Use Proxy',  'You must use proxy specified in Location to access this '  'resource.'),  307: ('Temporary Redirect',  'Object moved temporarily -- see URI list'),  400: ('Bad Request',  'Bad request syntax or unsupported method'),  401: ('Unauthorized',  'No permission -- see authorization schemes'),  402: ('Payment Required',  'No payment -- see charging schemes'),  403: ('Forbidden',  'Request forbidden -- authorization will not help'),  404: ('Not Found', 'Nothing matches the given URI'),  405: ('Method Not Allowed',  'Specified method is invalid for this server.'),  406: ('Not Acceptable', 'URI not available in preferred format.'),  407: ('Proxy Authentication Required', 'You must authenticate with '  'this proxy before proceeding.'),  408: ('Request Timeout', 'Request timed out; try again later.'),

      409: ('Conflict', 'Request conflict.'),  410: ('Gone',  'URI no longer exists and has been permanently removed.'),  411: ('Length Required', 'Client must specify Content-Length.'),  412: ('Precondition Failed', 'Precondition in headers is false.'),  413: ('Request Entity Too Large', 'Entity is too large.'),  414: ('Request-URI Too Long', 'URI is too long.'),  415: ('Unsupported Media Type', 'Entity body in unsupported format.'),  416: ('Requested Range Not Satisfiable',  'Cannot satisfy request range.'),  417: ('Expectation Failed',  'Expect condition could not be satisfied.'),  500: ('Internal Server Error', 'Server got itself in trouble'),

      501: ('Not Implemented',  'Server does not support this operation'),  502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),  503: ('Service Unavailable',  'The server cannot process the request due to a high load'),  504: ('Gateway Timeout',  'The gateway server did not receive a timely response'),  505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),  }  if result:  self.result = "\n%s" % result

      def __str__(self):

      return "Error [%s]: %s. %s.%s" % (self.value,  self.responses[self.value][0], self.responses[self.value][1],  self.result)

    class API(object):  """Main class"""  def __init__(self, email, password, *args, **kwargs):  self._br = mechanize.Browser()  data = {'email': email, 'password': password}

  • 8/9/2019 tuenpy.py

    3/7

      self.encoded_data = urllib.urlencode(data)  response = self._br.open(URLS['login'], self.encoded_data)  status = response.code  body = response.read()  if (status == HTTP_RESPONSE_CODES['OK'] and  MESSAGES['login_error'] not in body):  self.Profile = Profile(self._br)  self.Friends = Friends(self._br)  self.Comments = Comments(self._br, self.Profile.id)  else:  raise StatusException(401, "Email or password are invalid.")

    class User(object):  """User base class"""  def __init__(self, br, user_id, *args, **kwargs):  self._br = br  self.id = user_id

      def _get_first_name(self):  pass  first_name = property(_get_first_name)

      def _get_last_name(self):

      pass  last_name = property(_get_last_name)

      def _get_name(self):  pass  name = property(_get_name)

      def _get_birthdate(self):  pass  birthdate = property(_get_birthdate)

      def _get_marital_status(self):  pass

      marital_status = property(_get_marital_status)

      def _get_province(self):  pass  province = property(_get_province)

      def _get_locality(self):  pass  locality = property(_get_locality)

      def _get_hobbies(self):  pass  hobbies = property(_get_hobbies)

      def _get_films(self):  pass  films = property(_get_films)

      def _get_quotes(self):  pass  quotes = property(_get_quotes)

      def _get_music(self):

  • 8/9/2019 tuenpy.py

    4/7

      pass  music = property(_get_music)

      def _get_books(self):  pass  books = property(_get_books)

    class Profile(User):  """Profile class"""  def __init__(self, br, *args, **kwargs):  self._br = br  user_id = self._get_user_id()  if not user_id:  raise StatusException(404, "User not found in tuenti.")  else:  super(Profile, self).__init__(br, user_id, *args, **kwargs)  self._csfr = self._get_csfr()  if not self._csfr:  raise StatusException(404, "csfr key not found in profile.")

      def _get_user_id(self):  response = self._br.open(URLS['my_profile'])  status = response.code

      body = response.read()  if status == HTTP_RESPONSE_CODES['OK']:  doc = libxml2dom.parseString(body, html=1)  fieldsets = doc.getElementsByTagName('fieldset')  for fieldset in fieldsets:  if fieldset.getAttribute('title') == MESSAGES['my_wall']:  anchor = fieldset.getElementsByTagName('a').pop()  user_id = anchor.getAttribute('href').split('user_id=')[1].split('&')[0]  return user_id

      def _get_csfr(self):  response = self._br.open(TUENTI_HOST)

      status = response.code  body = response.read()  if status == HTTP_RESPONSE_CODES['OK']:  doc = libxml2dom.parseString(body, html=1)  forms = doc.getElementsByTagName('go')  if forms:  return forms[0].getAttribute('href').split('csfr=')[1].split('&')[0]

      def _set_status(self, value):  if value:  data = {'status': value}  else:

      data = {'status': ""}  self.encoded_data = urllib.urlencode(data)  response = self._br.open(URLS['set_status'] % self._csfr, self.encoded_data)  status = response.code  body = response.read()  if (status != HTTP_RESPONSE_CODES['OK'] or  MESSAGES['restricted_area'] in body):  raise StatusException(304, "Status not modified.")  def _get_status(self):

  • 8/9/2019 tuenpy.py

    5/7

      response = self._br.open(URLS['my_profile'])  status = response.code  body = response.read()  if status == HTTP_RESPONSE_CODES['OK']:  doc = libxml2dom.parseString(body, html=1)  fieldsets = doc.getElementsByTagName("fieldset")  for fieldset in fieldsets:  if (len(fieldset.childNodes) > 2 and  fieldset.childNodes[0].toString() == MESSAGES['status']):  status_node_value = fieldset.childNodes[2].value  if status_node_value:  status_message = status_node_value.split(MESSAGES['status_verb'])[1].strip()  return status_message  return None  status = property(_get_status, _set_status)

      def _get_first_name(self):  pass  first_name = property(_get_first_name)

      def _get_last_name(self):  pass  last_name = property(_get_last_name)

      def _get_name(self):  pass  name = property(_get_name)

    class Friends(object):  """Friend collection class"""  def __init__(self, br, *args, **kwargs):  self._br = br  cont = 0  response = self._br.open(URLS['friends'] % str(cont))  status = response.code

      body = response.read()  self._friends = []  while (status == HTTP_RESPONSE_CODES['OK'] and  MESSAGES['more_friends'] in body):  doc = libxml2dom.parseString(body, html=1)  anchors = doc.getElementsByTagName('a')  for anchor in anchors:  if anchor and anchor.getAttribute('href').startswith(PROFILE_URL):  friend_dic = {}  friend_dic['user_id'] = anchor.getAttribute('href').split(PROFILE_URL)[1].split('&')[0]  friend_dic['nick'] = anchor.textContent

      self._friends.append(friend_dic)  cont = cont + 1  response = self._br.open(URLS['friends'] % str(cont))  status = response.code  body = response.read()  doc = libxml2dom.parseString(body, html=1)  anchors = doc.getElementsByTagName('a')  for anchor in anchors:  if anchor and anchor.getAttribute('href').startswith(PROFILE_URL):  friend_dic = {}

  • 8/9/2019 tuenpy.py

    6/7

      friend_dic['user_id'] = anchor.getAttribute('href').split(PROFILE_URL)[1].split('&')[0]  friend_dic['nick'] = anchor.textContent  self._friends.append(friend_dic)

      def get(self, index):  f = self._friends[index]  return Friend(self._br, f.get('user_id', None), f.get('nick', None))

      def all(self):  friend_list = []  for f in self._friends:  friend_list.append(Friend(self._br, f.get('user_id', None), f.get('nick', None)))  return friend_list

    class Friend(User):  """Friend base class"""  def __init__(self, br, user_id, nick, *args, **kwargs):  super(Friend, self).__init__(br, user_id, *args, **kwargs)  self.nick = nick  self.Comments = Comments(self._br, user_id)

    class Comments(object):  """Comment collection class"""  def __init__(self, br, user_id, *args, **kwargs):  self._br = br  self.user_id = user_id  cont = 0  response = self._br.open(URLS['comments'] % (self.user_id, cont))  status = response.code  body = response.read()  self._comments = []  while(status == HTTP_RESPONSE_CODES['OK'] and  MESSAGES['more_comments'] in body):

      doc = libxml2dom.parseString(body, html=1)  fieldsets = doc.getElementsByTagName('fieldset')  for fieldset in fieldsets:  if (fieldset.getAttribute('title') and  (fieldset.getAttribute('title') == MESSAGES['my_wall'] or  fieldset.getAttribute('title').startswith(MESSAGES['wall']))):  smalls = fieldset.getElementsByTagName('small')  for small in smalls[1:]:  comment_dic = {}  anchor = small.getElementsByTagName('a')[0]  if anchor and '?m=profile&user_id' in anchor.getAttribute('href'):

      comment_dic.update({'friend_id': anchor.getAttribute('href').split('user_id=')[1]})  comment_dic.update({'friend_name': anchor.textContent})  text = anchor.nextSibling.textContent  splitted_text = text.split('(')  time = splitted_text.pop()  time_parsed = time.split(')')[0]  text_parsed = text[2:len(text)-len(time)-3]  comment_dic.update({'text': text_parsed})

  • 8/9/2019 tuenpy.py

    7/7

      comment_dic.update({'time': time_parsed})  self._comments.append(comment_dic)  cont = cont + 3  response = self._br.open(URLS['comments'] % (self.user_id, cont))  status = response.code  body = response.read()  doc = libxml2dom.parseString(body, html=1)  fieldsets = doc.getElementsByTagName('fieldset')  for fieldset in fieldsets:  if (fieldset.getAttribute('title') and  (fieldset.getAttribute('title') == MESSAGES['my_wall'] or  fieldset.getAttribute('title').startswith(MESSAGES['wall']))):  smalls = fieldset.getElementsByTagName('small')  for small in smalls[1:]:  comment_dic = {}  anchor = small.getElementsByTagName('a')[0]  if anchor and '?m=profile&user_id' in anchor.getAttribute('href'):  comment_dic.update({'friend_id': anchor.getAttribute('href').split('user_id=')[1]})  comment_dic.update({'friend_name': anchor.textContent})  text = anchor.nextSibling.textContent  splitted_text = text.split('(')  time = splitted_text.pop()

      time_parsed = time.split(')')[0]  text_parsed = text[2:len(text)-len(time)-3]  comment_dic.update({'text': text_parsed})  comment_dic.update({'time': time_parsed})  self._comments.append(comment_dic)

      def get(self, index):  # TODO: Create an Friend instance  return self._comments[index]

      def all(self):  # TODO: Retrieve a Friend collection

      return self._comments

      def latest(self, entries=5):  # TODO: Retrieve a Friend collection  return self._comments[:entries]

    class Comment(object):  """Comment base class"""  def __init__(self, br, user_id, *args, **kwargs):  self._br = br  self.user_id  # TODO: Get Comment

     __all__ = ['API']