]> git.openstreetmap.org Git - osqa.git/blob - forum/utils/userlinking.py
53a49dc05ecedab60e8153ed10639bc6026ed86d
[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     else:
35         return content
36     
37     # Now we've got the root question. Let's get the list of active users.
38     active_users = question.get_active_users()
39     
40     appeals = APPEAL_PATTERN.finditer(content)
41
42     replacements = []
43
44     for appeal in appeals:
45         # Try to find the profile URL
46         username = appeal.group(0)[1:]
47         
48         matches = []
49         
50         for user in active_users:
51             if user.username.lower().startswith(username.lower()):
52                 matches.append(user)
53                 
54         if len(matches) == 1:
55             replacements.append(
56                                 (find_best_match_in_name(content,  username,  matches[0].username,  appeal.start(0) + 1),  matches[0])
57                                 )                                
58         elif len(matches) == 0:
59             matches = User.objects.filter(username__istartswith=username)
60             
61         if (len(matches) == 0):
62                 continue
63         
64         best_user_match = None
65         final_match = ""
66         
67         for user in matches:
68             user_match = find_best_match_in_name(content,  username,  user.username,  appeal.start(0) + 1)
69             
70             if (len(user_match) < len(final_match)): 
71                 continue
72                 
73             if (len(user_match) == len(final_match)):
74                 if not (user.username.lower() == user_match.lower()):
75                     continue
76                     
77                 if (best_user_match and (best_user_match.username == final_match)):
78                     continue
79                     
80             best_user_match = user
81             final_match = user_match
82         
83         replacements.append((final_match,  best_user_match))            
84     
85     for replacement in replacements:
86         to_replace = "@" + replacement[0]
87         profile_url = replacement[1].get_absolute_url()
88         
89         auto_link = '<a href="%s">%s</a>' % (profile_url, to_replace)
90         content = content.replace(to_replace, auto_link)        
91     
92     return content