]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Use notice for context when deciding who @nickname refers to
authorEvan Prodromou <evan@status.net>
Sat, 27 Feb 2010 21:06:46 +0000 (16:06 -0500)
committerEvan Prodromou <evan@status.net>
Sat, 27 Feb 2010 21:06:46 +0000 (16:06 -0500)
In a federated system, "@nickname" is insufficient to uniquely
identify a user. However, it's a very convenient idiom. We need to
guess from context who 'nickname' refers to.

Previously, we were using the sender's profile (or what we knew about
them) as the only context. So, we assumed that they'd be mentioning to
someone they followed, or someone who followed them, or someone on
their own server.

Now, we include the notice information for context. We check to see if
the notice is a reply to another notice, and if the author of the
original notice has the nickname 'nickname', then the mention is
probably for them. Alternately, if the original notice mentions someone
with nickname 'nickname', then this notice is probably referring to
_them_.

Doing this kind of context sleuthing means we have to render the
content very late in the notice-saving process.

classes/Notice.php
lib/util.php

index 2d02a9a19f1c747ce02134bdd97e71b0713f936e..6614f3d558a6353de92cc8f8fd61a8dc5123bd77 100644 (file)
@@ -282,12 +282,6 @@ class Notice extends Memcached_DataObject
 
         $notice->content = $final;
 
-        if (!empty($rendered)) {
-            $notice->rendered = $rendered;
-        } else {
-            $notice->rendered = common_render_content($final, $notice);
-        }
-
         $notice->source = $source;
         $notice->uri = $uri;
         $notice->url = $url;
@@ -315,6 +309,12 @@ class Notice extends Memcached_DataObject
             $notice->location_ns = $location_ns;
         }
 
+        if (!empty($rendered)) {
+            $notice->rendered = $rendered;
+        } else {
+            $notice->rendered = common_render_content($final, $notice);
+        }
+
         if (Event::handle('StartNoticeSave', array(&$notice))) {
 
             // XXX: some of these functions write to the DB
index 32061ec04ce037f55a6e4471e9092ecf96c411d8..d12a7920d2d458e421ba841d2e453d72378f7b99 100644 (file)
@@ -426,14 +426,14 @@ function common_render_content($text, $notice)
 {
     $r = common_render_text($text);
     $id = $notice->profile_id;
-    $r = common_linkify_mentions($id, $r);
+    $r = common_linkify_mentions($r, $notice);
     $r = preg_replace('/(^|[\s\.\,\:\;]+)!([A-Za-z0-9]{1,64})/e', "'\\1!'.common_group_link($id, '\\2')", $r);
     return $r;
 }
 
-function common_linkify_mentions($profile_id, $text)
+function common_linkify_mentions($text, $notice)
 {
-    $mentions = common_find_mentions($profile_id, $text);
+    $mentions = common_find_mentions($text, $notice);
 
     // We need to go through in reverse order by position,
     // so our positions stay valid despite our fudging with the
@@ -487,11 +487,11 @@ function common_linkify_mention($mention)
     return $output;
 }
 
-function common_find_mentions($profile_id, $text)
+function common_find_mentions($text, $notice)
 {
     $mentions = array();
 
-    $sender = Profile::staticGet('id', $profile_id);
+    $sender = Profile::staticGet('id', $notice->profile_id);
 
     if (empty($sender)) {
         return $mentions;
@@ -499,6 +499,30 @@ function common_find_mentions($profile_id, $text)
 
     if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) {
 
+        // Get the context of the original notice, if any
+
+        $originalAuthor   = null;
+        $originalNotice   = null;
+        $originalMentions = array();
+
+        // Is it a reply?
+
+        if (!empty($notice) && !empty($notice->reply_to)) {
+            $originalNotice = Notice::staticGet('id', $notice->reply_to);
+            if (!empty($originalNotice)) {
+                $originalAuthor = Profile::staticGet('id', $originalNotice->profile_id);
+
+                $ids = $originalNotice->getReplies();
+
+                foreach ($ids as $id) {
+                    $repliedTo = Profile::staticGet('id', $id);
+                    if (!empty($repliedTo)) {
+                        $originalMentions[$repliedTo->nickname] = $repliedTo;
+                    }
+                }
+            }
+        }
+
         preg_match_all('/^T ([A-Z0-9]{1,64}) /',
                        $text,
                        $tmatches,
@@ -514,7 +538,22 @@ function common_find_mentions($profile_id, $text)
         foreach ($matches as $match) {
 
             $nickname = common_canonical_nickname($match[0]);
-            $mentioned = common_relative_profile($sender, $nickname);
+
+            // Try to get a profile for this nickname.
+            // Start with conversation context, then go to
+            // sender context.
+
+            if (!empty($originalAuthor) && $originalAuthor->nickname == $nickname) {
+
+                $mentioned = $originalAuthor;
+
+            } else if (!empty($originalMentions) &&
+                       array_key_exists($nickname, $originalMentions)) {
+
+                $mention = $originalMentions[$nickname];
+            } else {
+                $mentioned = common_relative_profile($sender, $nickname);
+            }
 
             if (!empty($mentioned)) {