2008/01/31


以下個人的な勝手な見解。そんなに熱く語ってる訳ではありませんので...
昨今色々なSNSが出回り、個々のSNSでそれぞれの色を出してアピールしています。
その中でもmixiがアクティブユーザ数はダントツで誇っており、これから数年も変わらないであろうと思われます。
mixiを代表とするSNSを色づけるSNS特有の機能として「足跡」があります。足跡とはそのSNSユーザ(もしくはゲスト)が対象のユーザページにアクセスした際、アクセスされた側に残されるログを指します。
otsuneさんも言うとおり、自前のブログを運営されている方であればHTTPアクセスログは一度は目を通した事があるでしょうし、知らない人が閲覧しているのは当たり前だと認識していると思います。
よく「足跡機能の付いてるSNSは嫌いだ」という人が稀にいますが、私が思うに
「足跡機能が必要ない」ではなく「足跡機能が嫌いだ」という人は、"自分が踏まれる事"よりも"自分が踏んでしまう事"で、踏まれた側から"勝手な先入観を持たれる"のが嫌いなのであって、単に見なければいいはずの足跡を"嫌い"という理由を明示しない。
という事。

私は、何個かSNSを掛け持ちしています。足跡機能があるSNSにも参加しています。時には足跡も見ますし、このサイトのアクセスログも見ています。
時にはtrackerfeedを使って、リファラにアクセスしたりもしますし、ハンドルネームで検索したりする事もあります。

ネットでコミュニケーションしたいなら普通の行動だと思っていますし、私のようにソフトウェアを開発している人間にとっては、作ったアプリケーションやプラグイン、パッチがまわりでどんな風に使われているのか知りたいと思うことは当然の事だと信じています。
まさか自分の為だけに作ったソフトウェアを自分だけで動かしてウヒヒヒヒ...なんてつもりはないですし、もちろんこの考え方も個々の勝手でいいとも思っています。

閲覧者は、客観的に人を判断している訳ですから、どう判断されたって致し方ないし、そもそも足跡をつけてしまっただけで勝手な先入観を持たれるコミュニケーションなんて成立しないんじゃ...と。

別に
貴方に関する記事書いたのにリアクション無いし、足跡見たら踏んでるのにスルーですか?
なんて可愛い事を言うなと言ってる訳でもないですし、平然とクールに足跡は閲覧すべきだ!と「SNSのルール」を語ってる訳でもないです。

ただただ足跡の有無でSNSの良し悪しを公言したり、足跡なんか気にするのは××だと公言するのはどうかと...

その「足跡拒否反応のおしつけ」こそが逆に
熱いはずの熱湯風呂に"熱い"と絶叫しながら入れない人間はおかしい
と言ってるように私には見えてしまうのです。

まぁ、その個々の考え方の不一致がSNSを面白くしているんでしょうけどね。

以上、独り言でした。
Posted at by




擬似GM_xmlhttpRequestを使ってたので、はてなリソースしか動いてなかった。
擬似GM_xmlhttpRequestでは、はてなスターの場合だけJSONで動かすようにしたので、きっと行けると思う。
JSONデータから文字列に戻す部分はこれを使わせて頂いた。
前とそれほど変わらないけど、unsafeWindowの宣言場所を上にもってったので前回のような簡単なパッチの当て方は出来なくなった。

--- HatenaStarEverywhere.user.js.orig   Mon Oct 01 10:37:41 2007
+++ HatenaStarEverywhere.user.js    Fri Oct 05 23:08:10 2007
@@ -92,6 +92,9 @@
     ensure(window.Hatena, 'Star');
 }
 
+if (typeof unsafeWindow == "undefined") {
+    var unsafeWindow = window;
+}
 if (typeof unsafeWindow.Hatena == 'undefined'
         || typeof unsafeWindow.Hatena.Star == 'undefined'
         || !unsafeWindow.Hatena.Star.loaded) {
@@ -138,4 +141,137 @@
             GM_setValue('configExpire', '');
         }
     });
+}
+
+if (typeof(GM_setValue) != 'function') {
+  function GM_setValue(key, value) {
+    document.cookie = [
+      name, '=', escape(value),
+      ';expires=', (new Date(new Date() + 365 * 1000 * 60 * 60 * 24)).toGMTString()
+    ].join('');
+  }
+}
+if (typeof(GM_getValue) != 'function') {
+  function GM_getValue(key) {
+    var r = new RegExp('/' + name + '=([^;]*)/'), m;
+    if (m = document.cookie.match(r)) return unescape(m[1]);
+    return null;
+  }
+}
+if (typeof(GM_xmlhttpRequest) != 'function') {
+  var GM_xmlhttpRequest_Data = null;
+  function GM_xmlhttpRequest_Handler(data) {
+     GM_xmlhttpRequest_Data = toJsonString(data);
+  }
+  function GM_xmlhttpRequest(opt) {
+    if (opt.url == 'http://s.hatena.ne.jp/siteconfig.json') {
+       var s = document.createElement('script');
+       s.charset = 'utf-8';
+       s.onload = function(e) {
+          s.responseText = GM_xmlhttpRequest_Data;
+          opt.onload(s);
+         GM_xmlhttpRequest_Data = null;
+       }
+       s.src = opt.url + '?callback=GM_xmlhttpRequest_Handler';
+       document.body.appendChild(s);
+   }
+    var x=new XMLHttpRequest();
+    x.onreadystatechange=function() {
+      switch(x.readyState) {
+        case 4:
+          opt.onload(x);
+          break;
+      }
+    };
+    x.open(opt.method,opt.url,true);
+    x.setRequestHeader('Content-Type',opt.mime);
+    x.send(null);
+  }
+}
+
+/*
+ * include http://code.google.com/p/trimpath/wiki/JsonLibrary
+ * with few modify for opera.
+ */
+
+/*
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+function toJsonString(arg) {
+    return toJsonStringArray(arg).join('');
+}
+
+function toJsonStringArray(arg, out) {
+    out = out || new Array();
+    var u; // undefined
+
+    switch (typeof arg) {
+    case 'object':
+        if (arg) {
+            if (arg.constructor == Array) {
+                out.push('[');
+                for (var i = 0; i < arg.length; ++i) {
+                    if (i > 0)
+                        out.push(',\n');
+                    toJsonStringArray(arg[i], out);
+                }
+                out.push(']');
+                return out;
+            } else if (typeof arg.toString != 'undefined') {
+                out.push('{');
+                var first = true;
+                for (var i in arg) {
+                    var curr = out.length; // Record position to allow undo when arg[i] is undefined.
+                    if (!first)
+                        out.push(',\n');
+                    toJsonStringArray(i, out);
+                    out.push(':');                    
+                    toJsonStringArray(arg[i], out);
+                    if (out[out.length - 1] == u)
+                        out.splice(curr, out.length - curr);
+                    else
+                        first = false;
+                }
+                out.push('}');
+                return out;
+            }
+            return out;
+        }
+        out.push('null');
+        return out;
+    case 'unknown':
+    case 'undefined':
+    case 'function':
+        out.push(u);
+        return out;
+    case 'string':
+        out.push('"')
+        out.push(arg.replace(/(["\\])/g, '\\$1').replace(/\r/g, '').replace(/\n/g, '\\n'));
+        out.push('"');
+        return out;
+    default:
+        out.push(String(arg));
+        return out;
+    }
 }


追記
[はてな][ネット]Twitterとはてなスターは相性がいい」こちらで紹介して頂きました。
一応、私の手元で動いている物をアップします。
はてな事務局さん、問題があればご連絡下さい。
HatenaStarEverywhere.user.js
Posted at by




はてなのお気に入りユーザーの情報を取得できる「お気に入りAPI」(Favorites API)を公開しました」って事でさっそく...


ソースはこんな感じ...
追記:このソースはFirefoxでしか動きません。IEで動くものはこのページのHTMLを直接参照下さい。(Firefox限定時の残骸あり) <script type="text/javascript">
<!--
function hatenaFavorites(data) {
  var container = document.getElementById('hatenaFavorites');
  Array.slice(container.childNodes).forEach(container.removeChild, container);
  data.favorites.forEach(function(i) {
    var div = document.createElement('div');
    var img = document.createElement('img');
    img.src='http://www.hatena.ne.jp/users/'+i.name.substring(0,2)+'/'+i.name+'/profile_s.gif'
    div.appendChild(img);
    div.appendChild(document.createTextNode(' ' + i.name));
    container.appendChild(div);
  });
}
function loadHatenaFavorites() {
  var container = document.getElementById('hatenaFavorites');
  Array.slice(container.childNodes).forEach(container.removeChild, container);

  var img = document.createElement('img');
  img.src='http://mattn.kaoriya.net/images/ajax-loader.gif';
  container.appendChild(img);

  var script = document.createElement('script');
  script.charset = 'utf-8';
  script.src = 'http://www.hatena.ne.jp/mattn/favorites.json?callback=hatenaFavorites';
  document.lastChild.appendChild(script);
}
--></script>

追記
os0xさんからの指摘でIEで動かないのを直しました。
↑のソースは張り替えませんので、直接ソースを閲覧して下さい。(残骸が残ってますが...)
Posted at by