Source code for lnk.bitly.key
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Handles the oauth2 authorization procedure for the bit.ly API."""
import click
import ecstasy
import simplejson
import lnk.beauty
import lnk.config
import lnk.errors
from lnk.bitly.command import Command
CLIENT_ID = '049118cdcf01c6b267f77582990d48da9127259a'
CLIENT_SECRET = 'b5257382fd1c7118688cae7942d5128b4d995c9e'
[docs]def echo(*args):
"""
Executes a key command and echoes its output.
Arguments:
args (variadic): The arguments to pass to a
Key instance's fetch() method.
"""
click.echo(Key().fetch(*args), nl=False)
[docs]class Key(Command):
"""
Handles oauth2 authorization for the bit.ly API.
The bulk of the work is done by the user in the command-line interface.
When 'lnk bitly --key' is run (or 'lnk --key' if bitly is the default),
the user is prompted for his or her login and password. This information
is passed to this class, which then fetches an oauth2 access-token using
the appropriate exchange procedure.
Attributes:
raw (bool): Whether or not to return the raw output for internal use
or the prettified output for outside representation.
"""
def __init__(self, raw=False):
super(Key, self).__init__('key')
self.raw = raw
self.parameters['client_id'] = CLIENT_ID
self.parameters['client_service'] = CLIENT_SECRET
[docs] def fetch(self, _, login, password, show, who):
"""
Fetches an oauth2 access-token for a given login and password.
Arguments:
_: This is the --generate flag, just a dummy parameter because it
must be passed from the command-line to initiate the procedure
but has no actual use here.
login (str): The user's login (username).
password (str): The user's password.
show (bool): Whether or not to return the access-token for output
once retrieved.
Returns:
If the show flag is set, the raw key as a string if self.raw
is True, else the key in a pretty box. If the show flag is unset,
an empty string is returned (such that nothing appears in the
command-line output).
"""
if who:
who = lnk.config.get('bitly', 'login')
return '{0}\n'.format(who) if who else 'Nobody.\n'
if not login:
login = click.prompt('Login')
if not password:
password = click.prompt('Password', hide_input=True)
key = self.request(login, password)
with lnk.config.Manager('bitly', write=True) as manager:
manager['key'] = key
manager['login'] = login
success = ecstasy.beautify('<Success!>', ecstasy.Color.Magenta)
click.echo(success)
if show:
if self.raw:
return key
return lnk.beauty.boxify([[key]]) + '\n'
return ''
[docs] def request(self, login, password):
"""
Requests an oauth2 token from the bit.ly API.
Arguments:
login (str): The user's login (username).
password (str): The user's password.
Returns:
The oauth2 token/key, if the request was successful.
Raises:
Any errors thrown by the verify() method.
"""
response = self.post(self.endpoints['oauth'],
authorization=(login, password))
key = self.verify(response, 'generate an API key')
return key
@staticmethod
[docs] def verify(response, what):
"""
Verifies the HTTP response following the request for an oauth2 token.
Arguments:
response (requests.Response): The HTTP-response from the request
for an oauth2 token.
what (str): A string-representation of what the request was for,
such that if an error is found and raised, its message
is 'Could not <what>' (e.g. 'generate an API key').
Returns:
The plain, string oauth2 access-token.
Raises:
errors.HTTPError: If an HTTP-related fault was found in the response.
"""
# If the request succeeded, the response is in
# text format, so the json decoding would fail,
# if there was an error we have to retrieve it in json
try:
response = response.json()
if not str(response['status_code']).startswith('2'):
raise lnk.errors.HTTPError('Could not {0}.'.format(what),
response['status_code'],
response['status_txt'])
except simplejson.scanner.JSONDecodeError:
pass
return str(response.text)