zhongrj
2025-11-24 276323dce9613867abb3f58a4cc2abbfb2fd0dea
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import math
 
from rest_framework import status
from rest_framework.response import Response
from app.plugins.views import TaskView
from app.plugins import get_current_plugin, signals as plugin_signals
from django.dispatch import receiver
from app.plugins import GlobalDataStore
from django.http import Http404
from django.shortcuts import redirect
 
import logging
 
logger = logging.getLogger('app.logger')
 
ds = GlobalDataStore('shortlinks')
 
def gen_short_string(num):
    num = int(abs(num))
 
    def nbase(num, numerals="abcdefghijklmnopqrstuvwxyz0123456789"):
        return ((num == 0) and numerals[0]) or (nbase(num // len(numerals), numerals).lstrip(numerals[0]) + numerals[num % len(numerals)])
 
    return nbase(num)
 
 
class GetShortLink(TaskView):
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        key = str(task.id)
 
        if ds.has_key(key):
            # Return existing short link
            return Response({'shortId': ds.get_string(key)}, status=status.HTTP_200_OK)
        else:
            # Compute short link, store it
            
            # Not atomic, but this shouldn't be a big problem
            counter = ds.get_int("counter", 0)
            ds.set_int("counter", counter + 1)
 
            short_id = gen_short_string(counter)
 
            # TaskId --> short id
            ds.set_string(key, short_id)
 
            # short id --> taskId
            ds.set_string(short_id, str(task.id))
 
            return Response({'shortId': short_id}, status=status.HTTP_200_OK)
 
 
def HandleShortLink(request, view_type, short_id):
    if ds.has_key(short_id):
        task_id = ds.get_string(short_id)
        if view_type == 'm':
            v = 'map'
        elif view_type == '3':
            v = '3d'
        
        return redirect('/public/task/{}/{}/'.format(task_id, v))
    else:
        raise Http404()
 
@receiver(plugin_signals.task_removed, dispatch_uid="shortlinks_on_task_removed")
def shortlinks_cleanup(sender, task_id, **kwargs):
    short_id = ds.get_string(task_id)
    if short_id:
        logger.info("Cleaning up shortlinks datastore for task {}".format(str(task_id)))
        ds.del_key(task_id)
        ds.del_key(short_id)