]> git.openstreetmap.org Git - osqa.git/blob - forum/utils/userlinking.py
fixes OSQA-562, Mixed-up markdown mangling of simple comment text
[osqa.git] / forum / utils / userlinking.py
1 import re
2
3 from forum.models import User,  Question,  Answer,  Comment
4
5 def find_best_match_in_name(content,  uname,  fullname,  start_index):      
6     end_index = start_index + len(fullname)    
7     
8     while end_index > start_index:
9         if content[start_index : end_index].lower() == fullname.lower():
10             return content[start_index : end_index]
11             
12         while len(fullname) and fullname[-1] != ' ':
13             fullname = fullname[:-1]
14             
15         fullname = fullname.rstrip()
16         end_index = start_index + len(fullname)
17             
18     return uname    
19
20 APPEAL_PATTERN = re.compile(r'(?<!\w)@\w+')
21
22 def auto_user_link(node, content):
23     
24     # We should find the root of the node tree (question) the current node belongs to.
25     if isinstance(node,  Question):
26         question = node
27     elif isinstance(node,  Answer):
28         question = node.question
29     elif isinstance(node,  Comment):
30         if node.question:
31             question = node.question
32         elif node.answer:
33             question = node.answer.question
34     
35     # Now we've got the root question. Let's get the list of active users.
36     active_users = question.get_active_users()
37     
38     appeals = APPEAL_PATTERN.finditer(content)
39
40     replacements = []
41
42     for appeal in appeals:
43         # Try to find the profile URL
44         username = appeal.group(0)[1:]
45         
46         matches = []
47         
48         for user in active_users:
49             if user.username.lower().startswith(username.lower()):
50                 matches.append(user)
51                 
52         if len(matches) == 1:
53             replacements.append(
54                                 (find_best_match_in_name(content,  username,  matches[0].username,  appeal.start(0) + 1),  matches[0])
55                                 )                                
56         elif len(matches) == 0:
57             matches = User.objects.filter(username__istartswith=username)
58             
59         if (len(matches) == 0):
60                 continue
61         
62         best_user_match = None
63         final_match = ""
64         
65         for user in matches:
66             user_match = find_best_match_in_name(content,  username,  user.username,  appeal.start(0) + 1)
67             
68             if (len(user_match) < len(final_match)): 
69                 continue
70                 
71             if (len(user_match) == len(final_match)):
72                 if not (user.username.lower() == user_match.lower()):
73                     continue
74                     
75                 if (best_user_match and (best_user_match.username == final_match)):
76                     continue
77                     
78             best_user_match = user
79             final_match = user_match
80         
81         replacements.append((final_match,  best_user_match))            
82     
83     for replacement in replacements:
84         to_replace = "@" + replacement[0]
85         profile_url = replacement[1].get_absolute_url()
86         
87         auto_link = '<a href="%s">%s</a>' % (profile_url, to_replace)
88         content = content.replace(to_replace, auto_link)        
89     
90     return content