summaryrefslogtreecommitdiffstats
path: root/forum/utils/markup.py
blob: 0eef11107f5d39a19c051ff1a1e0e5af17ab2bf9 (plain)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from forum import const
#from forum.models import Comment, Question, Answer
#from forum.models import QuestionRevision, AnswerRevision
from forum.models import Mention, User

def _make_mention(mentioned_whom, context_object = None):
    mentioned_by = context_object.get_last_author()
    if mentioned_whom:
        if mentioned_whom != mentioned_by:
            m = Mention(
                    mentioned_by = mentioned_by,
                    mentioned_whom = mentioned_whom,
                    content_object = context_object
                )
            m.save()
        url = mentioned_whom.get_profile_url()
        username = mentioned_whom.username
        return '<a href="%s">@%s</a>' % (url, username)
    else:
        return '@'

def _extract_matching_mentioned_author(text, authors):

    if len(text) == 0:
        return None, ''

    for a in authors:
        if text.startswith(a.username):
            ulen = len(a.username)
            if len(text) == ulen:
                text = ''
            elif text[ulen] in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
                text = text[ulen:]
            else:
                #near miss, here we could insert a warning that perhaps
                #a termination character is needed
                continue
            return a, text
    return None, text

def mentionize(text, context_object = None):

    if '@' not in text:
        return text

    op = context_object.get_origin_post()
    authors = list(op.get_all_authors())

    extra_name_seed = ''
    for c in text:
        if c in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
            break
        else:
            extra_name_seed += c
        if len(extra_name_seed) > 10:
            break

    if len(extra_name_seed) > 0:
        authors += list(User.objects.filter(username__startswith = extra_name_seed))

    output = ''
    while '@' in text:
        #the purpose of this loop is to convert any occurance of '@mention ' syntax
        #to user account links leading space is required unless @ is the first 
        #character in whole text, also, either a punctuation or a ' ' char is required
        #after the name
        pos = text.index('@')

        #save stuff before @mention to the output
        output += text[:pos]#this works for pos == 0 too

        if len(text) == pos + 1:
            #finish up if the found @ is the last symbol
            output += '@'
            text = ''
            break

        if pos > 0:

            if text[pos-1] in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
                #if there is a termination character before @mention
                #indeed try to find a matching person
                text = text[pos+1:]
                matching_author, text = _extract_matching_mentioned_author(text, authors)
                output += _make_mention(matching_author, context_object = context_object)

            else:
                #if there isn't, i.e. text goes like something@mention, do not look up people
                output += '@'
                text = text[pos+1:]
        else:
            #do this if @ is the first character
            text = text[1:]
            matching_author, text = _extract_matching_mentioned_author(text, authors)
            output += _make_mention(matching_author, context_object = context_object)

    #append the rest of text that did not have @ symbols
    output += text
    return output