def send_request(url, data):
    """send a http request.
    """
    req = urllib2.Request(url, data)
    try:
        return urllib2.urlopen(req).read()
    except urllib2.HTTPError as e:
        raise FlickrError(e.read().split('&')[0])
Exemplo n.º 2
0
def _check_tickets():
    try:
        tickets = yield Photo.checkUploadTickets(_futures.keys())
    except Exception as e:
        print e
        raise e
    for t in tickets:
        f = _futures[t.id]
        del _futures[t.id]
        if not _futures:
            _periodic_checks.stop()

        if t.get("complete", 0) == 1:
            # completed successfully
            f.set_result()
        elif t.get("complete", 0) == 2:
            # ticket failed, problem converting photo?
            f.set_exception(FlickrError("Ticket %s failed" % t.id))
        elif t.get("invalid", 0) == 1:
            # ticket not found
            f.set_exception(FlickrError("Ticket %s not found" % t.id))
Exemplo n.º 3
0
def bindings_to(flickr_method):
    """
        Returns the list of bindings to the given Flickr API method
        in the object API.
        
        ex:
        >>> bindings_to("flickr.people.getPhotos")
        ['Person.getPhotos']
        this tells that the method from Flickr API 'flickr.people.getPhotos'
        is bound to the 'Person.getPhotos' method of the object API.
    """
    try:
        return __bindings__[flickr_method]
    except KeyError:
        if flickr_method in __methods__: return []
        else:
            raise FlickrError("Unknown Flickr API method: %s" % flickr_method)
Exemplo n.º 4
0
def post(url, auth_handler, args, photo_file):
    args = format_dict(args)
    args["api_key"] = method_call.API_KEY

    params = auth_handler.complete_parameters(url, args).parameters

    fields = params.items()

    files = [("photo", os.path.basename(photo_file), open(photo_file).read())]

    r = multipart.posturl(url, fields, files)
    if r.status != 200:
        raise FlickrError("HTTP Error %i: %s" % (r.status, r.read()))
    r = ET.fromstring(r.read())
    if r.get("stat") != 'ok':
        err = r[0]
        raise FlickrAPIError(int(err.get("code")), err.get("msg"))
    return r
Exemplo n.º 5
0
def upload(**args):
    """
    Authentication:

        This method requires authentication with 'write' permission.
        
    Arguments:
        photo_file
            The file to upload.
        title (optional)
            The title of the photo.
        description (optional)
            A description of the photo. May contain some limited HTML.
        tags (optional)
            A space-seperated list of tags to apply to the photo.
        is_public, is_friend, is_family (optional)
            Set to 0 for no, 1 for yes. Specifies who can view the photo.
        safety_level (optional)
            Set to 1 for Safe, 2 for Moderate, or 3 for Restricted.
        content_type (optional)
            Set to 1 for Photo, 2 for Screenshot, or 3 for Other.
        hidden (optional)
            Set to 1 to keep the photo in global search results, 2 to hide 
            from public searches.
        async
            set to 1 for async mode, 0 for sync mode 
    
    """
    if "async" not in args: args["async"] = False

    photo_file = args.pop("photo_file")
    r = post(UPLOAD_URL, auth.AUTH_HANDLER, args, photo_file)

    t = r[0]
    if t.tag == 'photoid':
        return Photo(id=t.text,
                     editurl='http://www.flickr.com/photos/upload/edit/?ids=' +
                     t.text)
    elif t.tag == 'ticketid':
        return UploadTicket(id=t.text)
    else:
        raise FlickrError("Unexpected tag: %s" % t.tag)
Exemplo n.º 6
0
def replace(**args):
    """
     Authentication:

        This method requires authentication with 'write' permission.

        For details of how to obtain authentication tokens and how to sign 
        calls, see the authentication api spec. Note that the 'photo' parameter 
        should not be included in the signature. All other POST parameters 
        should be included when generating the signature.
    
    Arguments:

        photo_file
            The file to upload.
        photo_id
            The ID of the photo to replace.
        async (optional)
            Photos may be replaced in async mode, for applications that 
            don't want to wait around for an upload to complete, leaving 
            a socket connection open the whole time. Processing photos 
            asynchronously is recommended. Please consult the documentation 
            for details. 
            
    """
    if "async" not in args: args["async"] = True
    if "photo" in args: args["photo_id"] = args.pop("photo").id

    photo_file = args.pop("photo_file")

    r = post(REPLACE_URL, AUTH_HANDLER, args, photo_file)

    t = r[0]
    if t.tag == 'photoid':
        return Photo(id=t.text)
    elif t.tag == 'ticketid':
        return UploadTicket(id=t.text, secret=t.secret)
    else:
        raise FlickrError("Unexpected tag: %s" % t.tag)
Exemplo n.º 7
0
def post(url, auth_handler, photo_file, **kwargs):
    kwargs = format_dict(kwargs)
    kwargs["api_key"] = auth_handler.key

    params = auth_handler.complete_parameters(url, kwargs).parameters

    fields = params.items()

    files = [("photo", os.path.basename(photo_file), open(photo_file).read())]

    try:
        response = yield multipart.posturl(url, fields, files)
    except Exception as e:
        raise e

    if response.code != 200:
        raise FlickrError("HTTP Error %i: %s" % (response.code, response.body))

    r = ElementTree.fromstring(response.body)
    if r.get("stat") != 'ok':
        err = r[0]
        raise FlickrAPIError(int(err.get("code")), err.get("msg"))
    raise Return(r)
Exemplo n.º 8
0
def call_api(api_key=None,
             api_secret=None,
             auth_handler=None,
             needssigning=False,
             request_url=REST_URL,
             raw=False,
             **args):
    """
        Performs the calls to the Flickr REST interface.
        
        Arguments :
            api_key : The API_KEY to use, if none is given, the key from flickr_keys is used.
            api_secret : The API_SECRET to use, if none is given, the key from flickr_keys is used.
            auth_handler : The authentication handler object to use to perform authentication
            request_url : The url to the rest interface to use by default the url in REST_URL is used.
            raw : if True the default xml response from the server is returned. if False (default)
                  a dictionnary built from the JSON answer is returned.
            args : the arguments to pass to the method.
    """

    if not api_key:
        api_key = API_KEY
    if not api_secret:
        api_secret = API_SECRET

    if not api_key or not api_secret:
        raise FlickrError("The Flickr API keys have not been set")

    clean_args(args)
    args["api_key"] = api_key
    if not raw:
        args["format"] = 'json'
        args["nojsoncallback"] = 1
    if auth_handler is None:
        if needssigning:
            query_elements = [e.split("=") for e in query.split("&")]
            query_elements.sort()
            sig = API_SECRET + ["".join(["".join(e) for e in query_elements])]
            m = hashlib.md5()
            m.update(sig)
            api_sig = m.digest()
            args["api_sig"] = api_sig
        data = urllib.urlencode(args)

    else:
        data = auth_handler.complete_parameters(url=request_url,
                                                params=args).to_postdata()

    if CACHE is None:
        resp = send_request(request_url, data)
    else:
        resp = CACHE.get(data) or send_request(request_url, data)
        if data not in CACHE: CACHE.set(data, resp)

    if raw:
        return resp

    try:
        resp = json.loads(resp)
    except ValueError, e:
        print resp
        raise e
Exemplo n.º 9
0
def upload(**kwargs):
    """
    Authentication:

        This method requires authentication with 'write' permission.

    Arguments:
        photo_file
            The file to upload.
        title (optional)
            The title of the photo.
        description (optional)
            A description of the photo. May contain some limited HTML.
        tags (optional)
            A space-separated list of tags to apply to the photo.
        is_public, is_friend, is_family (optional)
            Set to 0 for no, 1 for yes. Specifies who can view the photo.
        safety_level (optional)
            Set to 1 for Safe, 2 for Moderate, or 3 for Restricted.
        content_type (optional)
            Set to 1 for Photo, 2 for Screenshot, or 3 for Other.
        hidden (optional)
            Set to 1 to keep the photo in global search results, 2 to hide
            from public searches.
        async
            set to 1 for async mode, 0 for sync mode

    """
    if "async" not in kwargs:
        kwargs["async"] = False

    if auth.AUTH_HANDLER is None:
        raise FlickrError("Not authenticated")

    photo_file = kwargs.pop("photo_file")
    try:
        resp_body = yield post(UPLOAD_URL, auth.AUTH_HANDLER, photo_file,
                               **kwargs)
    except Exception as e:
        log.error("Failed to upload %s" % photo_file)
        raise e

    t = resp_body[0]
    if t.tag == 'photoid':
        # sync mode, got a photo
        raise Return(
            Photo(id=t.text,
                  editurl='https://www.flickr.com/photos/upload/edit/?ids=' +
                  t.text))
    elif t.tag == 'ticketid':
        # async mode, got a ticket
        if not _futures:
            _periodic_checks.start()

        _futures[t.text] = Future()
        try:
            yield _futures[t.text]
        except Exception as e:
            raise e

        raise Return(
            Photo(id=t.text,
                  editurl='https://www.flickr.com/photos/upload/edit/?ids=' +
                  t.text))
    else:
        raise FlickrError("Unexpected tag: %s" % t.tag)
Exemplo n.º 10
0
def replace(**kwargs):
    """
     Authentication:

        This method requires authentication with 'write' permission.

        For details of how to obtain authentication tokens and how to sign
        calls, see the authentication api spec. Note that the 'photo' parameter
        should not be included in the signature. All other POST parameters
        should be included when generating the signature.

    Arguments:

        photo_file
            The file to upload.
        photo_id
            The ID of the photo to replace.
        async (optional)
            Photos may be replaced in async mode, for applications that
            don't want to wait around for an upload to complete, leaving
            a socket connection open the whole time. Processing photos
            asynchronously is recommended. Please consult the documentation
            for details.

    """
    if "async" not in kwargs:
        kwargs["async"] = False
    if "photo" in kwargs:
        kwargs["photo_id"] = kwargs.pop("photo").id

    photo_file = kwargs.pop("photo_file")

    try:
        resp_body = yield post(REPLACE_URL, auth.AUTH_HANDLER, photo_file,
                               **kwargs)
    except Exception as e:
        raise e

    t = resp_body[0]
    if t.tag == 'photoid':
        # sync mode, got a photo
        raise Return(
            Photo(id=t.text,
                  editurl='https://www.flickr.com/photos/upload/edit/?ids=' +
                  t.text))
    elif t.tag == 'ticketid':
        # async mode, got a ticket
        if not _futures:
            _periodic_checks.start()

        _futures[t.text] = Future()
        try:
            yield _futures[t.text]
        except Exception as e:
            raise e

        raise Return(
            Photo(id=t.text,
                  editurl='https://www.flickr.com/photos/upload/edit/?ids=' +
                  t.text))
    else:
        raise FlickrError("Unexpected tag: %s" % t.tag)
def call_api(api_key=None,
             api_secret=None,
             auth_handler=None,
             needssigning=False,
             request_url=REST_URL,
             raw=False,
             **args):
    """
        Performs the calls to the Flickr REST interface.

    Parameters:
        api_key:
            The API_KEY to use. If none is given and a auth_handler is used
            the key stored in the auth_handler is used, otherwise, the values
            stored in the `flickr_keys` module are used.
        api_secret:
            The API_SECRET to use. If none is given and a auth_handler is used
            the key stored in the auth_handler is used, otherwise, the values
            stored in the `flickr_keys` module are used.
        auth_handler:
            The authentication handler object to use to perform authentication.
        request_url:
            The url to the rest interface to use by default the url in REST_URL
            is used.
        raw:
            if True the default xml response from the server is returned. If
            False (default) a dictionnary built from the JSON answer is
            returned.
        args:
            the arguments to pass to the method.
    """

    if not api_key:
        if auth_handler is not None:
            api_key = auth_handler.key
        else:
            api_key = keys.API_KEY
    if not api_secret:
        if auth_handler is not None:
            api_secret = auth_handler.secret
        else:
            api_secret = keys.API_SECRET

    if not api_key or not api_secret:
        raise FlickrError("The Flickr API keys have not been set")

    clean_args(args)
    args["api_key"] = api_key
    if not raw:
        args["format"] = 'json'
        args["nojsoncallback"] = 1

    if auth_handler is None:
        if needssigning:
            query_elements = args.items()
            query_elements.sort()
            sig = keys.API_SECRET + \
                  ["".join(["".join(e) for e in query_elements])]
            m = hashlib.md5()
            m.update(sig)
            api_sig = m.digest()
            args["api_sig"] = api_sig
        data = urllib3.request.urlencode(args)
    else:
        data = auth_handler.complete_parameters(url=request_url,
                                                params=args).to_postdata()

    if CACHE is None:
        resp = send_request(request_url, data)
    else:
        resp = CACHE.get(data) or send_request(request_url, data)
        if data not in CACHE:
            CACHE.set(data, resp)

    if raw:
        return resp

    try:
        resp = json.loads(resp)
    except ValueError as e:
        print(resp)
        raise e

    if resp["stat"] != "ok":
        raise FlickrAPIError(resp["code"], resp["message"])

    resp = clean_content(resp)

    return resp