Ejemplo n.º 1
0
    def _pack_image(filename, contentname, max_size=1024, **params):
        """Pack image from file into multipart-formdata post body"""
        # image must be less than 700kb in size
        try:
            if os.path.getsize(filename) > (max_size * 1024):
                raise QWeiboError('File is too big, must be less than 700kb.')
        except os.error:
            raise QWeiboError('Unable to access file')

        # image must be gif, jpeg, or png
        file_type = mimetypes.guess_type(filename)
        if file_type is None:
            raise QWeiboError('Could not determine file type')
        file_type = file_type[0]
        if file_type.split('/')[0] != 'image':
            raise QWeiboError('Invalid file type for image: %s' % file_type)

        # build the mulitpart-formdata body
        BOUNDARY = 'QqWeIbObYaNdElF----'  # qqweibo by andelf
        body = []
        for key, val in params.items():
            if val is not None:
                body.append('--' + BOUNDARY)
                body.append('Content-Disposition: form-data; name="%s"' % key)
                body.append('Content-Type: text/plain; charset=UTF-8')
                body.append('Content-Transfer-Encoding: 8bit')
                body.append('')
                val = convert_to_utf8_bytes(val)
                body.append(val)
        fp = open(filename, 'rb')
        body.append('--' + BOUNDARY)
        body.append(
            'Content-Disposition: form-data; name="%s"; filename="%s"' %
            (contentname, filename.encode('utf-8')))
        body.append('Content-Type: %s' % file_type)
        body.append('Content-Transfer-Encoding: binary')
        body.append('')
        body.append(fp.read())
        body.append('--%s--' % BOUNDARY)
        body.append('')
        fp.close()
        body.append('--%s--' % BOUNDARY)
        body.append('')
        # fix py3k
        for i in range(len(body)):
            body[i] = convert_to_utf8_bytes(body[i])
        body = b'\r\n'.join(body)
        # build headers
        headers = {
            'Content-Type': 'multipart/form-data; boundary=%s' % BOUNDARY,
            'Content-Length': len(body)
        }

        return headers, body
Ejemplo n.º 2
0
    def get_access_token(self, verifier=None):
        """
        After user has authorized the request token, get access token
        with user supplied verifier.
        """
        try:
            url = self._get_oauth_url('access_token')

            # build request
            request = oauth.OAuthRequest.from_consumer_and_token(
                self._consumer,
                token=self.request_token,
                http_url=url,
                verifier=str(verifier))
            request.sign_request(self._sigmethod, self._consumer,
                                 self.request_token)

            # send request
            resp = urlopen(Request(request.to_url()))  # must
            self.access_token = oauth.OAuthToken.from_string(
                resp.read().decode('ascii'))

            #print ('Access token key: ' + str(self.access_token.key))
            #print ('Access token secret: ' + str(self.access_token.secret))

            return self.access_token
        except Exception as e:
            raise QWeiboError(e)
Ejemplo n.º 3
0
    def parse(self, method, payload):
        try:
            if method.payload_type is None:
                return
            model = getattr(self.model_factory, method.payload_type)
        except AttributeError:
            raise QWeiboError('No model for this payload type: %s' %
                              method.payload_type)

        json = JSONParser.parse(self, method, payload)
        data = json['data']

        # TODO: add pager
        if 'pagetime' in method.allowed_param:
            pass

        if method.payload_list:
            # sometimes data will be a None
            if data:
                if 'hasnext' in data:
                    # need pager here
                    hasnext = data['hasnext'] in [0, 2]
                    # hasNext:2表示不能往上翻 1 表示不能往下翻,
                    # 0表示两边都可以翻 3表示两边都不能翻了
                else:
                    hasnext = False
                if 'info' in data:
                    data = data['info']
            else:
                hasnext = False
            result = model.parse_list(method.api, data)
            result.hasnext = hasnext
        else:
            result = model.parse(method.api, data)
        return result
Ejemplo n.º 4
0
        def __init__(self, api, args, kargs):
            # If authentication is required and no credentials
            # are provided, throw an error.
            if self.require_auth and not api.auth:
                raise QWeiboError('Authentication required!')

            self.api = api
            self.payload_format = api.parser.payload_format
            self.post_data = kargs.pop('post_data', None)
            self.retry_count = kargs.pop('retry_count', api.retry_count)
            self.retry_delay = kargs.pop('retry_delay', api.retry_delay)
            self.retry_errors = kargs.pop('retry_errors', api.retry_errors)
            self.headers = kargs.pop('headers', {})
            self.build_parameters(args, kargs)
            self.api_root = api.api_root

            # Perform any path variable substitution
            self.build_path()

            self.scheme = 'http://'

            self.host = api.host

            # Manually set Host header to fix an issue in python 2.5
            # or older where Host is set including the 443 port.
            # This causes Twitter to issue 301 redirect.
            # See Issue http://github.com/joshthecoder/tweepy/issues/#issue/12
            self.headers['Host'] = self.host
Ejemplo n.º 5
0
    def parse(self, method, payload):
        try:
            json = self.json_lib.loads(payload, encoding='utf-8')
        except Exception as e:
            print("Failed to parse JSON payload:" + repr(payload))
            raise QWeiboError('Failed to parse JSON payload: %s' % e)

        return json
Ejemplo n.º 6
0
 def _get_request_token(self):
     try:
         url = self._get_oauth_url('request_token')
         request = oauth.OAuthRequest.from_consumer_and_token(
             self._consumer, http_url=url, callback=self.callback)
         request.sign_request(self._sigmethod, self._consumer, None)
         resp = urlopen(Request(request.to_url()))  # must
         return oauth.OAuthToken.from_string(resp.read().decode('ascii'))
     except RuntimeError as e:
         raise QWeiboError(e)
Ejemplo n.º 7
0
 def get_username(self):
     if self.username is None:
         api = API(self)
         user = api.user.info()
         if user:
             self.username = user.name
         else:
             raise QWeiboError(
                 "Unable to get username, invalid oauth token!")
     return self.username
Ejemplo n.º 8
0
        def build_parameters(self, args, kargs):
            # bind here, as default
            self.parameters = {'format': self.payload_format}
            for idx, arg in enumerate(args):
                try:
                    self.parameters[self.allowed_param[idx]] = quote(
                        convert_to_utf8_str(arg))
                except IndexError:
                    raise QWeiboError('Too many parameters supplied!')

            for k, arg in kargs.items():
                if bool(arg) == False:
                    continue
                if k in self.parameters:
                    raise QWeiboError(
                        'Multiple values for parameter `%s` supplied!' % k)
                #if k not in self.allowed_param:
                #    raise QWeiboError('`%s` is not allowd in this API function.' % k)
                self.parameters[k] = quote(convert_to_utf8_str(arg))
Ejemplo n.º 9
0
        def build_path(self):
            for variable in re_path_template.findall(self.path):
                name = variable.strip('{}')

                if name == 'user' and self.api.auth:
                    value = self.api.auth.get_username()
                else:
                    try:
                        value = quote(self.parameters[name])
                    except KeyError:
                        raise QWeiboError(
                            'No parameter value found for path variable: %s' %
                            name)
                    del self.parameters[name]

                self.path = self.path.replace(variable, value)
Ejemplo n.º 10
0
    def get_authorization_url(self, signin_with_weibo=False):
        """Get the authorization URL to redirect the user"""
        try:
            # get the request token
            self.request_token = self._get_request_token()

            # build auth request and return as url
            if signin_with_weibo:
                url = self._get_oauth_url('authenticate')
            else:
                url = self._get_oauth_url('authorize')
            request = oauth.OAuthRequest.from_token_and_callback(
                token=self.request_token, http_url=url, callback=self.callback)

            return request.to_url()
        except RuntimeError as e:
            raise QWeiboError(e)
Ejemplo n.º 11
0
        def __init__(self, api, args, kargs):
            # If authentication is required and no credentials
            # are provided, throw an error.
            if self.require_auth and not api.auth:
                raise QWeiboError('Authentication required!')

            self.api = api
            self.payload_format = api.parser.payload_format
            self.post_data = kargs.pop('post_data', None)
            self.retry_count = kargs.pop('retry_count', api.retry_count)
            self.retry_delay = kargs.pop('retry_delay', api.retry_delay)
            self.retry_errors = kargs.pop('retry_errors', api.retry_errors)
            self.headers = kargs.pop('headers', {})
            self.build_parameters(args, kargs)
            self.api_root = api.api_root

            self.scheme = 'https://' if api.auth.AUTH_TYPE == "OAuth2.0" else 'http://'

            self.host = api.host
Ejemplo n.º 12
0
 def delete(self):
     if self.self:
         return self._api.t.delete(self.id)
     else:
         raise QWeiboError("You can't delete others' tweet")
Ejemplo n.º 13
0
        def execute(self):
            # Build the request URL
            url = self.scheme + self.host + self.api_root + self.path

            full_url, parameters = self.api.auth.authorize_request(
                url, self.method, self.headers, self.parameters)
            self.headers.setdefault("User-Agent", "pyqqweibo")
            if self.method == 'POST':
                if self.post_data is None:
                    self.headers.setdefault(
                        "Content-Type", "application/x-www-form-urlencoded")
                    # asure in bytes format
                    self.post_data = '&'.join(
                        ("%s=%s" % kv) for kv in parameters)
                req = Request(full_url,
                              data=self.post_data,
                              headers=self.headers)
            elif self.method == 'GET':
                req = Request(full_url)
            try:
                resp = urlopen(req)
            except Exception as e:
                raise QWeiboError("Failed to request %s headers=%s %s" % \
                                  (url, self.headers, e))
            body = resp.read()
            self.api.last_response = resp
            # log handling
            if self.api.log is not None:
                requestUrl = "URL:http://" + self.host + url
                eTime = '%.0f' % ((time.time() - sTime) * 1000)
                postData = ""
                if self.post_data is not None:
                    postData = ",post:" + self.post_data[:500]
                self.api.log.debug("%s, time: %s, %s result: %s" %
                                   (requestUrl, eTime, postData, body))

            retcode = 0
            errcode = 0
            # for py3k, ^_^
            if not hasattr(body, 'encode'):
                body = str(body, 'utf-8')
            # if self.api.parser.payload_format == 'json':
            #     try:
            #         # BUG: API BUG, refer api.doc.rst
            #         if body.endswith('out of memery'):
            #             body = body[:body.rfind('}')+1]
            #         json = self.api.parser.parse_error(self, body)
            #         retcode = json.get('ret', 0)
            #         msg = json.get('msg', '')
            #         # only in some post request
            #         errcode = json.get('errcode', 0)
            #     except ValueError as e:
            #         retcode = -1
            #         msg = "Bad json format (%s)" % e
            #     finally:
            #         if retcode + errcode != 0:
            #             raise QWeiboError("Response error: %s. (ret=%s, errcode=%s)" % \
            #                               (msg, retcode, errcode))

            # Parse the response payload
            result = self.api.parser.parse(self, body)

            # Store result into cache if one is available.
            if self.api.cache and self.method == 'GET' and result:
                self.api.cache.store(url, result)
            return result
Ejemplo n.º 14
0
        def execute(self):
            # Build the request URL
            url = self.api_root + self.path
            #if self.api.source is not None:
            #    self.parameters.setdefault('source',self.api.source)

            if len(self.parameters):
                if self.method == 'GET':
                    url = '%s?%s' % (url, urlencode(self.parameters))
                else:
                    self.headers.setdefault("User-Agent", "pyqqweibo")
                    if self.post_data is None:
                        self.headers.setdefault("Accept", "text/html")
                        self.headers.setdefault(
                            "Content-Type",
                            "application/x-www-form-urlencoded")
                        # asure in bytes format
                        self.post_data = urlencode(
                            self.parameters).encode('ascii')
            # Query the cache if one is available
            # and this request uses a GET method.
            if self.api.cache and self.method == 'GET':
                cache_result = self.api.cache.get(url)
                # if cache result found and not expired, return it
                if cache_result:
                    # must restore api reference
                    if isinstance(cache_result, list):
                        for result in cache_result:
                            result._api = self.api
                    else:
                        cache_result._api = self.api
                    return cache_result
                #urllib.urlencode(self.parameters)
            # Continue attempting request until successful
            # or maximum number of retries is reached.
            sTime = time.time()
            retries_performed = 0
            while retries_performed < self.retry_count + 1:
                # Open connection
                # FIXME: add timeout
                # Apply authentication
                if self.require_auth and self.api.auth:
                    url_full = self.api.auth.get_authed_url(
                        self.scheme + self.host + url, self.method,
                        self.headers, self.parameters)
                else:  # this brunch is never accoured
                    url_full = self.api.auth.get_signed_url(
                        self.scheme + self.host + url, self.method,
                        self.headers, self.parameters)
                try:
                    if self.method == 'POST':
                        req = Request(url_full,
                                      data=self.post_data,
                                      headers=self.headers)
                    else:
                        req = Request(url_full)
                    resp = urlopen(req, timeout=20)
                except Exception as e:
                    raise QWeiboError("Failed to request %s headers=%s %s" % \
                                      (url, self.headers, e))

                # Exit request loop if non-retry error code
                if self.retry_errors:
                    if resp.code not in self.retry_errors:
                        break
                else:
                    if resp.code == 200:
                        break

                # Sleep before retrying request again
                time.sleep(self.retry_delay)
                retries_performed += 1

            # If an error was returned, throw an exception
            body = resp.read()
            self.api.last_response = resp
            if self.api.log is not None:
                requestUrl = "URL:http://" + self.host + url
                eTime = '%.0f' % ((time.time() - sTime) * 1000)
                postData = ""
                if self.post_data is not None:
                    postData = ",post:" + self.post_data[:500]
                self.api.log.debug("%s, time: %s, %s result: %s" %
                                   (requestUrl, eTime, postData, body))

            retcode = 0
            errcode = 0
            # for py3k, ^_^
            if not hasattr(body, 'encode'):
                body = str(body, 'utf-8')
            if self.api.parser.payload_format == 'json':
                try:
                    # BUG: API BUG, refer api.doc.rst
                    if body.endswith('out of memery'):
                        body = body[:body.rfind('}') + 1]
                    json = self.api.parser.parse_error(self, body)
                    retcode = json.get('ret', 0)
                    msg = json.get('msg', '')
                    # only in some post request
                    errcode = json.get('errcode', 0)
                except ValueError as e:
                    retcode = -1
                    msg = "Bad json format (%s)" % e
                finally:
                    if retcode + errcode != 0:
                        raise QWeiboError("Response error: %s. (ret=%s, errcode=%s)" % \
                                          (msg, retcode, errcode))

            # Parse the response payload
            result = self.api.parser.parse(self, body)

            # Store result into cache if one is available.
            if self.api.cache and self.method == 'GET' and result:
                self.api.cache.store(url, result)
            return result