[Tkabber-dev] r317 - trunk/plugins/avatarcache

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Mon Mar 15 11:32:36 MSK 2010


Author: Hermitifier
Date: 2010-03-15 11:32:36 +0300 (Mon, 15 Mar 2010)
New Revision: 317

Modified:
   trunk/plugins/avatarcache/README
   trunk/plugins/avatarcache/avatarcache.tcl
Log:
automatic requesting avatars is optional now (for low bandwidth connections)
optimise excessive hook running
code cleanup

Modified: trunk/plugins/avatarcache/README
===================================================================
--- trunk/plugins/avatarcache/README	2010-03-11 21:02:41 UTC (rev 316)
+++ trunk/plugins/avatarcache/README	2010-03-15 08:32:36 UTC (rev 317)
@@ -13,7 +13,8 @@
 
 $jid is a bare form, with stripped resource name
 $filename is name of actual file in the avatar cache. It's not warranted 
-that it contains any usable graphic data.
+that it contains any usable graphic data. $filename equal to empty
+string means no avatar.
 
 Offline cache is restored on finload_hook. If it's needed at a later
 time, it can be invoked again by calling proc avatarcache::restore_cache

Modified: trunk/plugins/avatarcache/avatarcache.tcl
===================================================================
--- trunk/plugins/avatarcache/avatarcache.tcl	2010-03-11 21:02:41 UTC (rev 316)
+++ trunk/plugins/avatarcache/avatarcache.tcl	2010-03-15 08:32:36 UTC (rev 317)
@@ -9,6 +9,7 @@
     variable vcard_photo_hashes
     variable pep_avatar_hashes
     variable assigned_hashes
+    variable pending_avatars
     
     disco::register_feature "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"
     disco::register_feature "urn:xmpp:avatar:metadata+notify"
@@ -25,6 +26,16 @@
     custom::defvar avatarcache_custom {} "Mapping of JIDs to custom assigned avatar hashes." \
 	    -group Hidden
 
+    custom::defgroup AvatarCache \
+	[::msgcat::mc "Options for Avatar cache module,\
+		       which automatically downloads announced avatars\
+		       and notifies other modules on a hook."] \
+	-group Plugins -tag "Avatar Cache"
+	 
+    custom::defvar auto_retrieve_avatars 1 \
+	[::msgcat::mc "Automatically request PEP avatar nodes and vCard photos."] \
+	-group AvatarCache -type boolean -command [namespace current]::toggle_auto_retrieve
+    
     hook::add userinfo_hook [namespace current]::after_vCard_photo
     
     hook::add client_presence_hook [namespace current]::process_presence
@@ -34,9 +45,25 @@
     hook::add roster_jid_popup_menu_hook [namespace current]::add_assign_menu_item 73
 }
 
+proc avatarcache::toggle_auto_retrieve {args} {
+    variable auto_retrieve_avatars
+    variable pending_avatars
+    
+    if {!$auto_retrieve_avatars} {
+	return
+    }
+    
+    foreach {id cmds} [array get pending_avatars] {
+	foreach cmd $cmds {
+	    eval $cmd
+	}
+    }
+}
+
 proc avatarcache::process_presence {xlib from type x args} {
     variable vcard_photo_hashes
-    variable assigned_hashes
+    variable auto_retrieve_avatars
+    variable pending_avatars
     set bjid [::xmpp::jid::stripResource $from]
     if {[chat::is_groupchat [chat::chatid $xlib $bjid]]} {
 	return
@@ -52,33 +79,38 @@
 			::xmpp::xml::split $subel stag sxmlns sattrs scdata ssubels
 			if {$stag == "photo"} {
 			    debugmsg avatarcache "photo $from: '$scdata'"
-			    if {![info exists vcard_photo_hashes($bjid)] \
-				    || $vcard_photo_hashes($bjid) != $scdata} {
-				debugmsg avatarcache "saving unknown photo hash $from $scdata"
-				if {$scdata != ""} {
+			    if {[info exists vcard_photo_hashes($bjid)] \
+				    && $vcard_photo_hashes($bjid) == $scdata} {
+				#we downloaded vcard before, and announced hash matches
+				return
+			    }
+			    debugmsg avatarcache "saving unknown photo hash $from $scdata"
+			    if {$scdata != ""} {
+				set filename [file join $::configdir avatars $scdata]
+				if {[file exists $filename]} {
+				    #we have file matching the announced hash. work is done.
 				    set vcard_photo_hashes($bjid) $scdata
-				    store_cache
-				    set filename [file join $::configdir avatars $scdata]
-				    if {![file exists $filename]} {
-				        if {[roster::is_trusted $xlib $bjid]} {
-					    after_vCard_photo "" $xlib $from 0
-					    ::xmpp::sendIQ $xlib get \
+				    store_and_notify $bjid
+				} {
+				    if {[roster::is_trusted $xlib $bjid]} {
+					set aftercmd [list after_vCard_photo "" $xlib $from 0]
+					set dloadcmd [list ::xmpp::sendIQ $xlib get \
 						-query [::xmpp::xml::create vCard -xmlns vcard-temp] \
 						-to $bjid \
-						-command [list userinfo::parse_vcard $from]
+						-command [list userinfo::parse_vcard $from] \
+					    ]
+					if {$auto_retrieve_avatars && ![info exists pending_avatars($scdata)]} {
+					    set pending_avatars($scdata) [list $aftercmd $dloadcmd]    
+					    eval $aftercmd
+					    eval $dloadcmd
+					} {
+					    set pending_avatars($scdata) [list $aftercmd $dloadcmd]    
 					}
-				    } {
-					if {![info exists assigned_hashes($bjid)]} {
-					    hook::run user_avatar_notification_hook $bjid $filename
-					}
 				    }
-				} {
-				    catch {unset vcard_photo_hashes($bjid)}
-				    store_cache
-				    if {![info exists assigned_hashes($bjid)]} {
-					hook::run user_avatar_notification_hook $bjid ""
-				    }
 				}
+			    } {
+				set vcard_photo_hashes($bjid) ""
+				store_and_notify $bjid
 			    }
 			}
 		    }
@@ -90,7 +122,8 @@
 
 proc avatarcache::process_avatar_metadata_notification {node xlib jid items} {
     variable pep_avatar_hashes
-    variable assigned_hashes
+    variable auto_retrieve_avatars
+    variable pending_avatars
     set stop true
 
     foreach item $items {
@@ -109,6 +142,7 @@
 		    info {
 			set stop false
 			#TODO: check if has all needed data
+			#TODO: multiple avatars
 			
 			set id [::xmpp::xml::getAttr $ssattrs id]
 			
@@ -129,21 +163,24 @@
 
     if {$stop} {
 	catch {unset pep_avatar_hashes($jid)}
-	store_cache
-	if {![info exists assigned_hashes($jid)]} {
-	    hook::run user_avatar_notification_hook $jid ""
-	}
+	store_and_notify $jid
     } {
 	set filename [file join $::configdir avatars $id]
 	if {[file exists $filename]} {
 	    set pep_avatar_hashes($jid) $id
-	    store_cache
-	    if {![info exists assigned_hashes($jid)]} {
-		hook::run user_avatar_notification_hook $jid $filename
+	    store_and_notify $jid
+	} {
+	    set cmd [list ::xmpp::pubsub::retrieveItems $xlib $jid $node \
+			-items $id \
+			-command [list [namespace current]::process_avatar_data\
+					$jid $node $filename] \
+		    ]
+	    if {$auto_retrieve_avatars && ![info exists pending_avatars($id)]} {
+		set pending_avatars($id) [list $cmd]
+		eval $cmd
+	    } {
+		set pending_avatars($id) [list $cmd]
 	    }
-	} {
-	    ::xmpp::pubsub::retrieveItems $xlib $jid $node -items $id \
-		    -command [list [namespace current]::process_avatar_data $jid $node $filename]
 	}
     }
 }
@@ -152,8 +189,8 @@
     if {$status != "ok"} return
     
     variable pep_avatar_hashes
-    variable assigned_hashes
-    
+    variable pending_avatars
+
     foreach item $xml {
 	::xmpp::xml::split $item tag xmlns attrs cdata subels
 	foreach idata $subels {
@@ -164,19 +201,19 @@
 
 	    set avatarb64 $scdata
 	    set hash [file tail $filename]
+	    
+	    catch {unset pending_avatars($hash)}
 
 	    #TODO: calculate real hash and check if matches ...
-	    if {!([file exists $filename] && [file attributes $filename -readonly])} {
+	    if {!([file exists $filename] && \
+		  [file attributes $filename -readonly])} {
 		set fileid [open $filename w]
 		fconfigure $fileid -translation binary
 		puts -nonewline $fileid [base64::decode $avatarb64]
 		close $fileid
 	    }
 	    set pep_avatar_hashes($jid) $hash
-	    store_cache
-	    if {![info exists assigned_hashes($jid)]} {
-		hook::run user_avatar_notification_hook $jid $filename
-	    }
+	    store_and_notify $jid
 	    return
 	}
     }
@@ -186,26 +223,22 @@
     debugmsg avatarcache [info level 0]
     if {[roster::is_trusted $xlib $jid] && !$editable} {
 	set bjid [::xmpp::jid::stripResource $jid]
-	trace vdelete ::userinfo::userinfo(photo_binval,$jid) w [list [namespace current]::save_vCard_photo $jid $bjid]
-	trace variable ::userinfo::userinfo(photo_binval,$jid) w [list [namespace current]::save_vCard_photo $jid $bjid]
+	trace vdelete ::userinfo::userinfo(photo_binval,$jid) w \
+		[list [namespace current]::save_vCard_photo $jid $bjid]
+	trace variable ::userinfo::userinfo(photo_binval,$jid) w \
+		[list [namespace current]::save_vCard_photo $jid $bjid]
     }
 }
 
 proc avatarcache::save_vCard_photo {jid bjid a b c} {
-    variable assigned_hashes
     debugmsg avatarcache [info level 0]
-    trace vdelete "userinfo::$a\($b\)" $c [list [namespace current]::save_vCard_photo $jid $bjid]
+    trace vdelete "userinfo::$a\($b\)" $c \
+	    [list [namespace current]::save_vCard_photo $jid $bjid]
     variable vcard_photo_hashes
+    variable pending_avatars
     set hash [sha1::sha1 $::userinfo::userinfo(photo_binval,$jid)]
-    if {[info exists vcard_photo_hashes($bjid)] && $vcard_photo_hashes($bjid) != ""} {
-	#TODO: check if hashes match ... misbehaving clients might be announcing wrong hash.
-	# what should happen then ?
-	#set filename [file join $::configdir avatars $vcard_photo_hashes($xjid)]
-    } {
-	#we didn't see avatar announce yet, but we deduce it anyway
-	set vcard_photo_hashes($bjid) $hash
-	store_cache
-    }
+
+    catch {unset pending_avatars($hash)}
     set filename [file join $::configdir avatars $hash]
 	
     if {!([file exists $filename] && [file attributes $filename -readonly])} {
@@ -214,20 +247,36 @@
 	puts -nonewline $fileid $::userinfo::userinfo(photo_binval,$jid)
 	close $fileid
     }
-    if {![info exists assigned_hashes($bjid)]} {
-	hook::run user_avatar_notification_hook $bjid $filename
-    }
+    set vcard_photo_hashes($bjid) $hash
+    store_and_notify $bjid
     return
 }
 
-proc avatarcache::store_cache {} {
+proc avatarcache::store_and_notify {jid} {
     variable pep_avatar_hashes
     variable vcard_photo_hashes
     variable avatarcache
+    variable assigned_hashes
+
     array set tmp $avatarcache
+    set oldhash [lindex [array get tmp $jid] 1]
     array set tmp [array get vcard_photo_hashes]
     array set tmp [array get pep_avatar_hashes]
     set avatarcache [array get tmp]
+
+    if {[info exists assigned_hashes($jid)]} return
+	
+    set hash [lindex [array get tmp $jid] 1]
+    if {$hash != $oldhash} {
+	if {$hash != ""} {
+	    set filename [file join $::configdir avatars $hash]
+	    if {[file exists $filename]} {
+		hook::run user_avatar_notification_hook $jid $filename
+	    }
+	} {
+	    hook::run user_avatar_notification_hook $jid ""
+	}
+    }
 }
 
 proc avatarcache::restore_cache {} {
@@ -235,18 +284,14 @@
     variable avatarcache_custom
     variable assigned_hashes
     
-#    foreach filename [glob -nocomplain [file join $::configdir avatars *@*.*]] {
-#	set jid_lookalike [file tail $filename]
-#	if {[info exists avatarcache($jid_lookalike)]} continue
-#
-#	hook::run user_avatar_notification_hook $jid_lookalike $filename
-#    }
-    
     array set assigned_hashes $avatarcache_custom
     foreach {jid hash} $avatarcache {
+	if {[info exists assigned_hashes($jid)]} {
+	    continue
+	}
 	if {$hash != ""} {
 	    set filename [file join $::configdir avatars $hash]
-	    if {[file exists $filename] && ![info exists assigned_hashes($jid)]} {
+	    if {[file exists $filename]} {
 		debugmsg avatarcache "restoring '$jid' -> '$hash'"
 		hook::run user_avatar_notification_hook $jid $filename
 	    }



More information about the Tkabber-dev mailing list