diff options
Diffstat (limited to 'brevisurl/backends')
| -rw-r--r-- | brevisurl/backends/__init__.py | 0 | ||||
| -rw-r--r-- | brevisurl/backends/base.py | 41 | ||||
| -rw-r--r-- | brevisurl/backends/local.py | 53 | 
3 files changed, 94 insertions, 0 deletions
| diff --git a/brevisurl/backends/__init__.py b/brevisurl/backends/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/brevisurl/backends/__init__.py diff --git a/brevisurl/backends/base.py b/brevisurl/backends/base.py new file mode 100644 index 0000000..3fc053a --- /dev/null +++ b/brevisurl/backends/base.py @@ -0,0 +1,41 @@ +from abc import ABCMeta + + +class BaseBrevisUrlBackend(object): +    """Base class for brevisurl backend implementations. Subclasses must at least overwrite shorten_url().""" + +    __metaclass__ = ABCMeta + + +    def __init__(self, fail_silently=False, **kwargs): +        self.fail_silently = fail_silently +        self.class_path = '{0}.{1}'.format(self.__module__, self.__class__.__name__) + +    def open(self): +        """Open a network connection. + +        This method can be overwritten by backend implementations to +        open a network connection. + +        It's up to the backend implementation to track the status of +        a network connection if it's needed by the backend. + +        The default implementation does nothing. + +        """ +        pass + +    def close(self): +        """Close a network connection.""" +        pass + +    def shorten_url(self, original_url): +        """Shortens url into more compact form. + +        :param original_url: url that will be shortened +        :type original_url: string +        :returns: shortened url from original url +        :rtype: brevisurl.models.ShortUrl + +        """ +        raise NotImplementedError
\ No newline at end of file diff --git a/brevisurl/backends/local.py b/brevisurl/backends/local.py new file mode 100644 index 0000000..42d0263 --- /dev/null +++ b/brevisurl/backends/local.py @@ -0,0 +1,53 @@ +import string +import random +import logging + +from django.contrib.sites.models import Site + +from brevisurl.backends.base import BaseBrevisUrlBackend +from brevisurl.models import ShortUrl + + +log = logging.getLogger(__name__) + + +class BrevisUrlBackend(BaseBrevisUrlBackend): + +    PROTOCOL = 'http' + +    def shorten_url(self, original_url): +        """ +        :raises: ImproperlyConfigured, django.core.exceptions.ValidationError +        """ +        try: +            short_url = ShortUrl.objects.get(backend=self.class_path, original_url=original_url) +            log.info('Url "%s" already shortened to "%s"', original_url, short_url.shortened_url) +            return short_url +        except ShortUrl.DoesNotExist: +            pass + +        try: +            current_site = Site.objects.get_current() +            short_url = ShortUrl() +            short_url.original_url = original_url +            short_url.shortened_url = '{0}://{1}/{2}'.format(self.PROTOCOL, current_site.domain, +                                                             self.__generate_token()) +            short_url.backend = self.class_path +            short_url.save() +            log.info('Url "%s" shortened to "%s"', original_url, short_url.shortened_url) +            return short_url +        except Exception: +            if self.fail_silently: +                return None +            else: +                log.exception('Unknown exception raised while shortening url "%s"', original_url) +                raise + +    def __generate_token(self, size=5): +        chars = list(string.ascii_letters + string.digits) +        random.shuffle(chars) +        while True: +            token = ''.join([random.choice(chars) for x in range(size)]) +            if not ShortUrl.objects.filter(backend=self.class_path, shortened_url__endswith=token).count(): +                break +        return token
\ No newline at end of file | 
