root/lang/javascript/vimperator-plugins/branches/2.1/hatebuWatchDog.js

Revision 33835, 10.3 kB (checked in by snaka, 15 months ago)

Change Icon transparency

Line 
1//
2//  hatebuWatchDog.js     - hatena bookmark watch dog -
3//
4// LICENSE: {{{
5//
6// This software distributable under the terms of an MIT-style license.
7//
8// Copyright (c) 2009 snaka<snaka.gml@gmail.com>
9//
10// Permission is hereby granted, free of charge, to any person obtaining a copy
11// of this software and associated documentation files (the "Software"), to deal
12// in the Software without restriction, including without limitation the rights
13// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14// copies of the Software, and to permit persons to whom the Software is
15// furnished to do so, subject to the following conditions:
16//
17// The above copyright notice and this permission notice shall be included in
18// all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26// THE SOFTWARE.
27//
28// OSI page : http://opensource.org/licenses/mit-license.php
29// Japanese : http://sourceforge.jp/projects/opensource/wiki/licenses%2FMIT_license
30//
31// }}}
32// PLUGIN INFO: {{{
33let PLUGIN_INFO =
34<VimperatorPlugin>
35  <name>{NAME}</name>
36  <description>Make notify hatebu-count when specified site's hatebu-count changed.</description>
37  <description lang="ja">指定されたサイトのはてブ数を監視、変動があったらお知らせします。</description>
38  <minVersion>2.0pre</minVersion>
39  <maxVersion>2.2pre</maxVersion>
40  <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/hatebuWatchDog.js</updateURL>
41  <author mail="snaka.gml@gmail.com" homepage="http://vimperator.g.hatena.ne.jp/snaka72/">snaka</author>
42  <license>MIT style license</license>
43  <version>1.2.0</version>
44  <detail><![CDATA[
45    == Subject ==
46      Make notify hatebu-count when specified site's hatebu-count changed.
47      Usage is just put this script into vimperator's plugin directory.
48
49    == Global variables ==
50      g:hatebuWatchDogInterval:
51        Number. Watching interval. Default:600 Min:60
52      g:hatebuWtachDogTargets:
53        String. Sites where it wants you to watch.
54        If you want watch only one site, you should specify like following.
55        >||
56          :let g:hatebuWatchDogTargets = "http://d.hatena.ne.jp/snaka72/"
57        ||<
58        If you want watch more than one site, you should specify like following.
59        >||
60          :let g:hatebuWatchDogTargets = "['http://d.hatena.ne.jp/snaka72/', 'http://vimperator.g.hatena.ne.jp/snaka72/']"
61        ||<
62      g:hatebuWatchDogAlways:
63        Boole. Make notify every time. (for debug) Default:false
64
65  ]]></detail>
66  <detail lang="ja"><![CDATA[
67    == 概要 ==
68      指定されたサイトの被はてブ数を監視して、その数値に変動があったらお知らせします。
69      使い方は、このスクリプトをVimperatorのpluginディレクトリに格納するだけです。
70
71    == グローバル変数 ==
72      g:hatebuWatchDogInterval:
73        Number. 監視の間隔(秒). デフォルト600 設定可能な最小値:60
74      g:hatebuWtachDogTargets:
75        String. Sites where it wants you to watch
76        監視対象のサイトが一つだけの場合は以下のように設定します。
77        >||
78          :let g:hatebuWatchDogTargets = "http://d.hatena.ne.jp/snaka72/"
79        ||<
80        監視対象のサイトがが複数の場合は以下のように設定します。
81        >||
82          :let g:hatebuWatchDogTargets = "['http://d.hatena.ne.jp/snaka72/', 'http://vimperator.g.hatena.ne.jp/snaka72/']"
83        ||<
84      g:hatebuWatchDogAlways:
85        Boole. 毎回報告を挙げるかどうか。デフォルト:false (主にでバッグ用)
86
87    == ToDo ==
88      - 新着ブックマークのユーザidとコメントの表示
89
90    ]]></detail>
91  </VimperatorPlugin>;
92// }}}
93
94// Clear all watchers if started watcher exists.
95if (plugins.hatebuWatchDog && plugins.hatebuWatchDog.stopWatching)
96  plugins.hatebuWatchDog.stopWatching();
97
98let publics = plugins.hatebuWatchDog = (function() {
99  // PRIVATE //////////////////////////////////////////////////////////////{{{
100  const libly = plugins.libly;
101  let previousValue = 0;
102  let tasks = [];
103
104  function getCurrentValue(target, onSuccess, onFailure) {
105    // build hatebu xml-rpc request
106    let req = new libly.Request(
107      'http://b.hatena.ne.jp/xmlrpc',
108      {
109        'Content-Type' : 'text/xml'
110      },{
111        postBody : <methodCall>
112                     <methodName>bookmark.getTotalCount</methodName>
113                     <params>
114                       <param><value><string>{target}</string></value></param>
115                     </params>
116                   </methodCall>.toXMLString()
117      }
118    );
119
120    let currentValue;
121    req.addEventListener("onSuccess", function(data) {
122      liberator.log("XML-RPC request was succeeded.");
123      let resXml = new XML(data.responseText.replace(/^<\?xml version[^>]+?>/, ''));
124      currentValue = window.eval(resXml..int.toString());
125      onSuccess(currentValue);
126    });
127    req.addEventListener("onFailure", function(data) {
128      onFailure();
129    });
130    liberator.log("reauest...");
131    req.post();
132    liberator.log("done...");
133  }
134
135  function notifyAlways()
136    window.eval(liberator.globalVariables.hatebuWatchDogAlways) || false;
137
138  function showHatebuNotification(targetSite, currentValue, delta) {
139    let title = delta >= 0
140              ? "hatebuWatchDog\u304B\u3089\u306E\u304A\u77E5\u3089\u305B"  // ordinary notification
141              : "\u6B8B\u5FF5\u306A\u304A\u77E5\u3089\u305B"                // bad notification
142    let suffix = delta != 0 ? "\u306B\u306A\u308A\u307E\u3057\u305F\u3002"
143                            : "\u3067\u3059\u3002";
144    let message = "'" + targetSite + "' \u306E\u88AB\u306F\u3066\u30D6\u6570\u306F '" +
145                  currentValue + "' " + suffix + " (" + getSignedNum(delta) + ")";
146
147    //showAlertNotification(null, title, message);
148    //publics.notify(title, message);
149    (getNotifier())(title, message);
150  }
151
152  function getSignedNum(num) {
153    if (num > 0) return "+" + num;
154    if (num < 0) return "-" + Math.abs(num);
155    return "0";
156  }
157
158  let _notifier = null;
159  const GROWL_EXTENSION_ID = "growlgntp@brian.dunnington";
160
161  function getNotifier() {
162    if (_notifier) return _notifier;
163
164    if (Application.extensions.has(GROWL_EXTENSION_ID) &&
165        Application.extensions.get(GROWL_EXTENSION_ID).enabled) {
166      _notifier = publics.notify;
167    }
168    else {
169      _notifier = showAlertNotification;
170    }
171    return _notifier;
172  }
173
174  function showAlertNotification(title, message) {
175    Cc['@mozilla.org/alerts-service;1']
176    .getService(Ci.nsIAlertsService)
177    .showAlertNotification(
178      null, //'chrome://mozapps/skin/downloads/downloadIcon.png',
179      title,
180      message
181    );
182  }
183
184  function growl() Components.classes['@growlforwindows.com/growlgntp;1']
185                   .getService().wrappedJSObject;
186  const growlIcon = "http://img.f.hatena.ne.jp/images/fotolife/s/snaka72/20090608/20090608082837.png";  // temporary
187
188  function growlRegister() {
189    growl().register(
190      PLUGIN_INFO.name,
191      growlIcon,
192      [
193        {name: 'announce', displayName: 'Announce from hatebuWatchDog'},
194        {name: 'sadlynews',displayName: 'Sadly announce from hatebuWatchdog'},
195        {name: 'failed',   displayName: 'Erroer report from hatebuWatchdog'}
196      ]
197    );
198  }
199
200  function getInterval()
201    window.eval(liberator.globalVariables.hatebuWatchDogInterval) || 600; // default : 10 min.
202
203  // for debug
204  let log  = liberator.log;
205  let dump = liberator.dump;
206
207  // }}}
208  // PUBLIC ///////////////////////////////////////////////////////////////{{{
209  let self = {
210    startWatching: function() {
211      let targets;
212      try {
213        targets = window.eval(liberator.globalVariables.hatebuWatchDogTargets);
214      } catch(e) {
215        targets = liberator.globalVariables.hatebuWatchDogTargets;
216      }
217      if (targets) {
218        if (!(targets instanceof Array))
219          targets = [targets];
220        let i = 1, delay = 5000;
221        log("before setTimeout()");
222        targets.forEach(function(targetSite) {
223            setTimeout(function() {
224              publics.addTask({site : targetSite});
225            }, delay * i++);
226        });
227        log("after setTimeout()");
228      }
229      else {
230        liberator.echoerr("Please set g:hatebeWatchDogTargets before watching().");
231      }
232    },
233
234    addTask: function(target) {
235      dump(target.site);
236      const MINUTE = 60; // sec.
237      interval = getInterval() || (10 * MINUTE);       // default 10 min.
238      interval = Math.max(interval, MINUTE);      // lower limt is 1 min.
239
240      // initialize previous value
241      target.previousValue = 0;
242      target.initialize = true;
243      publics.watching(target);
244
245      // set watching interval
246      tasks.push(setInterval(publics.watching, 1000 * interval, target));
247      dump({target: target, interval: interval});
248    },
249
250    clearAllTasks: function() {
251      tasks.forEach(function(task) {
252          clearInterval(task);
253      });
254      tasks = [];
255      dump("watch dog is sleeping...");
256    },
257
258    watching: function(target) {
259      dump("watching...");
260      dump(target);
261
262      getCurrentValue(
263        target.site,
264        function(currentValue) {
265          if (target.initialize) {
266            target.initialize = false;
267            target.previousValue = currentValue;
268            return;
269          }
270          let delta =  currentValue - target.previousValue;
271          if (delta || notifyAlways()) {
272            showHatebuNotification(target.site, currentValue, delta);
273          }
274          target.previousValue = currentValue;
275        },
276        function() {
277          liberator.echoerr("Cannot get current value.");
278        }
279      );
280    },
281   
282    notify: function(title, message) {
283      growlRegister();
284      growl().notify(
285        PLUGIN_INFO.name,
286        'announce',
287        title,
288        message
289      );
290    }
291  };
292  // }}}
293  return self;
294})();
295
296// Awaking the watch dog.
297publics.startWatching();
298liberator.dump("Watch dog is awaking ...");
299// vim: sw=2 ts=2 et fdm=marker
Note: See TracBrowser for help on using the browser.