Add a basic link embiggener
[bigly] / src / bigly / views.py
index 46bccd6..f88753a 100644 (file)
@@ -1,3 +1,6 @@
+from urllib.parse import urlparse, urlunparse, parse_qs
+
+from django.shortcuts import render
 from django.views.generic.base import TemplateView
 
 from rest_framework import status, viewsets
@@ -6,11 +9,81 @@ import requests
 
 from . import serializers
 
+def _remove_utm(link):
+    parsed_link = urlparse(link)
+    parsed_link = parsed_link._replace(
+        query='&'.join(
+            [
+                p
+                for p in parsed_link.query.split('&')
+                if not p.startswith('utm_')
+            ]
+        )
+    )
+
+    return ''.join((
+        parsed_link.scheme + '://' if parsed_link.scheme else '',
+        parsed_link.netloc,
+        parsed_link.path,
+        ';' + parsed_link.params if parsed_link.params else '',
+        '?' + parsed_link.query if parsed_link.query else '',
+        '#' + parsed_link.fragment if parsed_link.fragment else '',
+    ))
+
+def _follow_redirects(link, remove_utm):
+    while True:
+        if remove_utm:
+            link = _remove_utm(link)
+
+        response = requests.head(link)
+
+        # TODO Handle timeouts
+
+        if 301 <= response.status_code and response.status_code <= 308:
+            # TODO Handle the different kinds of redirects correctly
+
+            link = response.headers.get('Location')
+
+            if not link:
+                # TODO Handle this
+                raise Exception()
+
+        # TODO Handle error responses
+        else:
+            return {
+                'link': link,
+                'status': response.status_code,
+            }
+
 class IndexView(TemplateView):
     template_name = 'bigly/index.html'
 
 index = IndexView.as_view()
 
+def embiggen(request):
+    serializer = serializers.FollowRedirectsSerializer(data=request.GET)
+
+    if not serializer.is_valid():
+        return render(
+            request,
+            'bigly/index.html',
+            {
+                'errors': serializer.errors,
+            },
+            status=400,
+        )
+
+    result = _follow_redirects(
+        link = serializer.data['link'],
+        remove_utm = serializer.data['remove_utm'],
+    )
+
+    return render(
+        request,
+        'bigly/link_info.html',
+        result,
+    )
+
 class FollowRedirectsViewSet(viewsets.ViewSet):
     serializer_class = serializers.FollowRedirectsSerializer
 
@@ -23,32 +96,15 @@ class FollowRedirectsViewSet(viewsets.ViewSet):
                 status=status.HTTP_400_BAD_REQUEST,
             )
 
-        link = serializer.data['link']
-
-        while True:
-            response = requests.head(link)
-
-            # TODO Handle timeouts
-
-            if 301 <= response.status_code and response.status_code <= 308:
-                # TODO Handle the different kinds of redirects correctly
-
-                link = response.headers.get('Location')
-
-                if not link:
-                    # TODO Handle this
-                    raise Exception()
-
-            # TODO Handle error responses
-            else:
-                return Response(
-                    {
-                        'link': link,
-                        'status': response.status_code,
-                    },
-                    status=status.HTTP_200_OK,
-                )
+        result = _follow_redirects(
+            link = serializer.data['link'],
+            remove_utm = serializer.data['remove_utm'],
+        )
 
+        return Response(
+            result,
+            status=status.HTTP_200_OK,
+        )
 
 api_follow_redirects = FollowRedirectsViewSet.as_view({
     'get': 'follow_redirects',