Source code for yourls.client

# client.py
#  - Python client for yourls
#
# Copyright 2011, Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Author:
#       Tim Flink <tflink@redhat.com>

"""
.. module:: yourls.client
   :synopsis: A simple client for the YOURLS URL shortener

.. moduleauthor:: Tim Flink <tflink@redhat.com>
"""

import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import json
from yourls import YourlsError, YourlsOperationError

[docs]class YourlsClient(): def __init__(self, apiurl, username=None, password=None, token=None): """The use of a username/password combo or a signature token is required :param apiurl: The location of the api php file :param username: The username to login with (not needed with signature token) :param password: The password to login with (not needed with signature token) :param token: The signature token to use (not needed with username/password combo) :throws: YourlsError for incorrent parameters """ self.data_format = 'json' if not apiurl: raise YourlsError("An api url is required") self.apiurl = apiurl if not username or not password: if not token: raise YourlsError("username and password or signature token are required") else: self.std_args = {'signature' : token, 'format' : self.data_format} else: self.username = username self.password = password self.std_args = {'username':self.username, 'password':self.password, 'format':self.data_format} def _send_request(self, args): """Encapsulates the actual sending of a request to a YOURLS instance :param args: The arguments to send to YOURLS """ urlargs = urllib.parse.urlencode(self._make_args(args)) req = urllib.request.Request(self.apiurl) req.add_data(urlargs) r = urllib.request.urlopen(req) data = r.read() return data def _make_args(self, new_args): """Convenience method for putting args into the proper format :param new_args: Dictionary containing the args to pass on """ return dict(list(self.std_args.items()) + list(new_args.items())) def _base_request(self, args, url): """Encapsulates common code and error handling for the access methods :param args: The arguments to send to YOURLS :param url: The url (short or long) arg being used in the request :raises: YourlsOperationError """ try: data = json.loads(self._send_request(args)) except urllib.error.URLError as error: raise YourlsOperationError(url, str(error)) if 'errorCode' in data: raise YourlsOperationError(url, data['message']) return data
[docs] def shorten(self, url, custom = None, title = None): """Request a shortened URL from YOURLS with an optional keyword request :param url: The URL to shorten :type url: str :param custom: The custom keyword to request :type custom: str :param title: Use the given title instead of download it from the URL, this will increase performances :type title: str :returns: str -- The short URL :raises: YourlsOperationError """ args = {'action':'shorturl','url':url} if custom: args['keyword'] = custom if title: args['title'] = title # shorten raw_data = self._base_request(args, url) # parse result if raw_data['status'] == 'fail' and raw_data['code'] == 'error:keyword': raise YourlsOperationError(url, raw_data['message']) if not 'shorturl' in raw_data: raise YourlsOperationError(url, 'Unknown error: %s' % raw_data['message']) return raw_data['shorturl']
[docs] def expand(self, shorturl): """Expand a shortened URL to its original form :param shorturl: The URL to expand :returns: str -- The expanded URL :raises: YourlsOperationError """ args = {'action' : 'expand', 'shorturl' : shorturl, 'format' : 'json'} raw_data = self._base_request(args, shorturl) if not 'longurl' in raw_data: raise YourlsOperationError(shorturl, raw_data['message']) return raw_data['longurl']
[docs] def get_url_stats(self, shorturl): """Get statistics about a shortened URL :param shorturl: The URL to expand :returns: a list of stuff - FIXME, this isn't complete :raises: YourlsOperationError """ args = {'action' : 'url-stats', 'shorturl' : shorturl, 'format' : 'json'} raw_data = self._base_request(args, shorturl) if raw_data['statusCode'] != 200: raise YourlsOperationError(shorturl, raw_data['message']) return raw_data['link']