aboutsummaryrefslogtreecommitdiffstats
path: root/gmail_biff.js
blob: 5086eabae0e794ee5b92963ff921ef1b3ef8c4c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Vimperator plugin: gmail-biff
// Maintainer: mattn <mattn.jp@gmail.com> - http://mattn.kaoriya.net
(function(){
    const ICON1 = 'data:image/png;base64,'+
        'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAIAAADAAbR1AAAACXBIWXMAAABIAAAASABGyWs+AAAA'+
        'CXZwQWcAAAAQAAAAEABcxq3DAAAEXklEQVQ4y7WUXUxTdxyG33/bU6gIY5VSa8WkXSUu6hyDKMkM'+
        'S1TAuSUQl10sMtAsGnQKs64Vq5KAGWNxas1E/GJ1YHQJjMT4FdEZIqgJBkRnZA7mV0uFCuLgcNpz'+
        '2vP/7UKz7GLJrnwu3svn5k0eRkREhNeGDiFswzYMUiVVIpmtYqtgww7sANCABgAxxP7XUoxiPMU5'+
        'nMNT8pAHZraVbYUVdajD+OKzj84+Cma7FrsWD3+8q3dXr/zjXcNdA5EUlsJEk/ZJO5EYESNEoiIq'+
        'RKIsykSTwqRAJMmSHCt/Yntie/bcO9M7M5jmvOO889TQpDapkhSZEpmikz99kPAgQWxt97f70Udl'+
        'VCa3DNQM1KR8Uq6UKwY1oyKjAm/iEA4BaEQjgIVYCECBokgPpYfSyOa6kbqRydYOZ4cTnbEDsQMT'+
        'C+ROuZMXLr239J6GbdHe1N5Ei/a09rTwTVp5Wnl0dLBosGjYVS1Xy+JvV+ZdmQcPP8qPAuhGN0Jg'+
        'YOFbt/pv9Q9bqpZULQlf6antqY0T0y+kX2AufbO+WW1CGcq4jVu4RQOOcYyjlfIob8rPWY4sh+mU'+
        '64TrBH7iZ/iZ0PHaYG3wxWcty1qWUYK0V9o7IbTVtNUML68qqiqK1g5Zh6ym0k0FmwoSVy83Ljfy'+
        'jZRO6dSOgzgIO5vFZule3TRBbdSGY7q1urWJ/tyruVd126cFpvmfzffO8FpGN9Qfrj8s2a55r3kj'+
        'G/vQB21icl5ynrnDOcc5J0HOCeeEXxxpvt58nc+nVErlH1AlVWIAbrg1pAIAogAACY/xGBbmYz7D'+
        'zsy3Mh3TS9we9w/xMftD+4PJ32/subFHaJxunm42n3Sfd59P8OXk5+TjLzjgoFJ+jB+LvsO7ebfq'+
        'IpVUGKGFVof9YGCUDwaGD2GHHRrexbtgfJ7zPFe/Oik1yZQaqFhfsV5Uu/xdgYS6rJ6sHv1dw5hh'+
        'DL+EskPZEExTTVPVNdRIjfI4ZVBGtJpyKRdvQICgQy9kKBhjK9gKOidnypkkBD4PFMMsfCdUQzMj'+
        'd8ZSHQlFwpZkcXbD7AaMwAormWO9sV5kj64cXYn2gBSQ1AGpTCpTWvgavkZ10n26j07EIU5HfdiN'+
        'L/hMWknFfFDeKX/L25JKk0phStyY+CXAClgBhlRFjWEME5gAwz7sg8yy2SK0pmSkvEenpFFpNJoS'+
        'bgo3Rf/k6/g6/jaVUAmmIh/5uuju2OVYn+yJxkWNkQXCImGu5GZO9jUziZfEywBKUAKG27gNBgaG'+
        'l1nRwI8A3cR93Ma7zMYskSf6An2hauMn+UmaSyqpCGIIQzql2njReP3ZR2l/pPWPlIxL42OBLW3u'+
        'i+XYDgfLBv5R4lUy7gEA+gEwvA8NJOrB99imbAh6gnVhv3WzdbP2K6PH6NHEs3pWz6T9ok/0DXmD'+
        'jqBDzlGuKh2YYD7mA6AB+4/uRP+1HACDAD3ikEe/0iVYUIjCuOPxarxq6bGGrCH2umuqeX3ql/wN'+
        'QBozxfxKbAIAAAAASUVORK5CYII=';

    const ICON2 = 'data:image/png;base64,'+
        'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAAAAABqCHz+AAAACXBIWXMAAABIAAAASABGyWs+AAAA'+
        'CXZwQWcAAAAQAAAAEABcxq3DAAABvUlEQVQoz2P4TwAw/J/13/x/9f87/6f/n4IErwHFTf73ARUc'+
        't5zOskjjvtvPVT+Sfrj8cAVC359rXv5bPWGq9w7O79sZ1uam1aXeaFt26/n/zf83/s//P/X//+cc'+
        'U5PSJ6Yc6yh4lsqwviXTo0axqKS65eyrv7eBlvbfOtMWlv+hRTTjUQfHk0aG9VXpvxZPPLWp8nQx'+
        'x77qH+KnflVZlzgcWrVrVvrF9rgnC0AKji5T/G9xM6Blad7zSSHFDnUfL5z9/2zfzbSKttInixjW'+
        'V6YfXsbxf/3//3f/d3Km7WyVv9H+//3/33vTUgxaNj5ZxbA+Ir136cu/rz8ueXnsCe+u/EcrX616'+
        'v+lfyR7WhPNNdU+2MKx3TV+54Oersre7fn/4v+l/5v8Vf6a9F311bPOa2BMNa57sY1g3LW3K7Luf'+
        'nf9s/PPyz+Q/LUC48k/V14DVz6KZ6k89Ocyw6lei65yMjz4f7T6afDT7aA6Elh95P85Y+z2iq+78'+
        'k9UMW8vzxTtMN0ZvrATDio05GxM3hm/cMvFrhlvno2dxDF9Nbh+9Gn/19NUzUHj66kkgPH91y1WH'+
        'O1e/yzEQjk0CAAARc29gwOvTnwAAAABJRU5ErkJggg==';

    var gmailBiffIntervals = parseInt(globalVariables.gmbf_check_intervals || 30) * 1000;

    var gmailBiffIcon = document.createElement('statusbarpanel');
    gmailBiffIcon.setAttribute('id','gmail-biff-icon');
    gmailBiffIcon.setAttribute('class','statusbarpanel-iconic');
    gmailBiffIcon.setAttribute('src', ICON2);
    gmailBiffIcon.setAttribute('tooltip', 'gmail-biff-tip');
    gmailBiffIcon.addEventListener("click",function(e){
        liberator.open("https://mail.google.com/", liberator.NEW_TAB);
    },false);

    var gmailBiffTip = document.createElement('tooltip');
    gmailBiffTip.setAttribute('id','gmail-biff-tip');
    var gmailBiffText = document.createElement('description');
    gmailBiffText.setAttribute('id','gmail-biff-text');
    gmailBiffTip.appendChild(gmailBiffText);

    document.getElementById('status-bar')
            .insertBefore(gmailBiffIcon,document.getElementById('security-button').nextSibling);
    document.getElementById('status-bar').appendChild(gmailBiffTip);

    setTimeout(function() {
        try {
            var form = ['https://www.google.com', 'https://www.google.com', null];
            var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
            var logins = passwordManager.findLogins({}, form[0], form[1], form[2]);
            if(logins.length)
                var [gmailUser, gmailPassword] = [logins[0].username, logins[0].password];
            else {
                liberator.echoerr("Gmail Biff: account not found");
                var promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Ci.nsIPromptService);
                var user = { value : null };
                var pass = { value : null };
                var ret = promptSvc.promptUsernameAndPassword(
                    window, form[0], "GMail Biff Login", user, pass, null, {});
                if(ret){
                    var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
                            Ci.nsILoginInfo,
                            "init");
                    [gmailUser, gmailPassword] = [user.value, pass.value];
                    var formLoginInfo = new nsLoginInfo(
                        form[0], form[1], form[2],
                        gmailUser, gmailPassword, '', '');
                    passwordManager.addLogin(formLoginInfo);
                }
                return;
            }

            const feed_url = 'https://mail.google.com/mail/feed/atom';
            var xhr = new XMLHttpRequest();
            xhr.mozBackgroundRequest = true;
            xhr.open("GET", feed_url, false, gmailUser, gmailPassword);
            xhr.send(null);

            var count = parseInt(xhr.responseXML.getElementsByTagName('fullcount')[0].childNodes[0].nodeValue);
            gmailBiffIcon.setAttribute('src', count > 0 ? ICON1 : ICON2);
            gmailBiffText.setAttribute('value', count > 0 ? 'You have new mail (' + count + ')' : 'No new mail');
            setTimeout(arguments.callee, gmailBiffIntervals);
        } catch(e) {
            liberator.log(e);
            liberator.echoerr("Gmail Biff: " + e);
        }
    }, 1000);
})();
// vim:sw=4 ts=4 et:
xhr.send(null); } function unfavHaiku(username, password, user){ var xhr = new XMLHttpRequest(); xhr.open("POST", "http://h.hatena.ne.jp/api/statuses/user_timeline/" + user + ".json?count=1", false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); xhr.open("POST", "http://h.hatena.ne.jp/api/favorites/destroy/" + evalFunc(xhr.responseText)[0].id + '.json', false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); } function isValidStatusID(id){ if (!statuses) return false; return statuses.some(function(status) status.id == id); } function getStatusIDFromUserID(userid){ if (!statuses) return null; return statuses.filter(function(status) status.in_reply_to_user_id == userid)[0].id; } function getTimelineURLFromTarget(target){ if (target == "/"){ return "http://h.hatena.ne.jp/api/statuses/public_timeline.json"; } else if (target == "album"){ return "http://h.hatena.ne.jp/api/statuses/album.json"; } else if (/^#(.+)/.test(target)){ return "http://h.hatena.ne.jp/api/statuses/keyword_timeline/" + encodeURIComponent(RegExp.$1) + ".json"; } else if (/^@?(.+)/.test(target)){ return "http://h.hatena.ne.jp/api/statuses/user_timeline/" + RegExp.$1 + ".json"; } return "http://h.hatena.ne.jp/api/statuses/friends_timeline.json"; } function statusToXML(statuses){ var html = <style type="text/css"><![CDATA[ span.haiku.entry-title { text-decoration: underline; } .haiku.entry-content { white-space: normal; } .haiku.entry-content a { text-decoration: none; } dl.haiku { margin-left: 1em; } img.haiku.photo { border; 0px; width: 16px; height: 16px; vertical-align: baseline; } ]]></style>; statuses.forEach(function(status) { var text = status.text; var keyword = status.keyword; var star = status.favorited > 0 ? <><img src="http://s.hatena.ne.jp/images/star.gif"/><span style="color:orange;">{'x' + status.favorited}</span></> : <></>; var replies = <></>; if (text.indexOf(keyword+"=") == 0) text = status.text.substr(keyword.length + 1); text = convert(text); keyword = convert(keyword); if (status.replies.length > 0){ replies = <dl class="haiku"></dl>; status.replies.forEach(function(rep){ replies.* += <> <dt> <img src={rep.user.profile_image_url} alt={rep.user.screen_name} class="haiku photo"/> <strong>{rep.user_name}</strong> </dt> <dd class="haiku entry-content">{rep.text.substr(keyword.length+1)}</dd> </>; }); } html += <> <div> <img src={status.user.profile_image_url} alt={status.user.screen_name} title={status.user.screen_name} class="haiku photo"/> <strong>{status.user.name}&#x202C;</strong> {star} <span>:</span> <span class="haiku entry-title">{keyword}</span><br/> <span class="haiku entry-content">{text}</span> </div> {replies} <hr/> </>; }); return html; } function showFollowersStatus(username, password, target){ var xhr = new XMLHttpRequest(); var endPoint = getTimelineURLFromTarget(target); xhr.open("POST", endPoint, false, username, password); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(null); statuses = evalFunc(xhr.responseText); var html = statusToXML(statuses); liberator.log(html.toXMLString(), 0); liberator.echo(html, true); } function convert(str){ function createHTML(all){ var str = all; if (all.indexOf("id:") == 0){ str = '<a href="http://h.hatena.ne.jp/' + all.replace(":", "/") + '">' + all + '</a>'; } else if (/\.(?:jpe?g|gif|png|bmp)$/.test(all)){ str = '<img src="' + all + '"/>'; } else if (/^http:\/\/(?:[^.]+\.)?youtube\.com\/(?:watch\?(?:[^&]+&)*v=|v\/)([^&=#?;\/]+)/.test(all)){ var url = "http://www.youtube.com/v/" + RegExp.$1 + "&amp;fs=1"; str = '<a href="#" class="hl-URL">' + url + '</a>' + '<div><object width="300" height="250" data="' + url + '" type="application/x-shockwave-flash">'+ '<param name="wmode" value="transparent"/><param name="allowFullScreen" value="true"/>'+ '</object></div>'; } else if (/^http:\/\/www\.nicovideo\.jp\/watch\/([-\w]+)$/.test(all)){ str = '<iframe width="312" height="176" src="http://ext.nicovideo.jp/thumb/'+RegExp.$1 + '" scrolling="no">'+ '<a href="' + all + '">' +all+'</a></iframe>'; } else if (all.charAt(0) == "["){ var keyword = all.substring(2, all.length -2); str = '<a href="http://h.hatena.ne.jp/keyword/' + keyword + '" class="hl-URL">' + keyword + '</a>'; } return str; } var str = str.replace(/&/g,"&amp;") .replace(/</g,"&lt;") .replace(/>/g,"&gt;") .replace(/\n/g,"<br/>") .replace(/\[\[[^\]]+\]\]|https?:\/\/[-\w!#$%&'()*+,.\/:;=?@~]+|id:[a-zA-Z][-\w]{1,30}[a-zA-Z\d]/g, createHTML); return new XMLList(str); } commands.addUserCommand(["haiku"], "Change Haiku status", function(arg, special){ var password; var username; try { var logins = passwordManager.findLogins({}, 'http://h.hatena.ne.jp', null, 'http://h.hatena.ne.jp (API)'); if (logins.length) [username, password] = [logins[0].username, logins[0].password]; else { var ps = Cc['@mozilla.org/embedcomp/prompt-service;1'].getService(Ci.nsIPromptService); var [user,pass] = [{ value : '' }, { value : '' }]; var ret = ps.promptUsernameAndPassword( window, 'http://h.hatea.ne.jp (API)', 'Enter username and password.\nyou can get "password" from\n\thttp://h.hatena.ne.jp/api#auth', user, pass, null, {}); if(ret){ username = user.value; password = pass.value.replace(/@.*$/, ''); var nsLoginInfo = new Components.Constructor( '@mozilla.org/login-manager/loginInfo;1', Ci.nsILoginInfo, 'init'); loginInfo = new nsLoginInfo('http://h.hatena.ne.jp', null, 'http://h.hatena.ne.jp (API)', username, password, '', ''); passwordManager.addLogin(loginInfo); } else throw 'Haiku: account not found'; } } catch (ex){ liberator.echoerr(ex); } arg = arg.string.replace(/%URL%/g, buffer.URL) .replace(/%TITLE%/g, buffer.title); if (special && arg.match(/^\+\s*(.*)/)) favHaiku(username, password, RegExp.$1) else if (special && arg.match(/^-\s*(.*)/)) unfavHaiku(username, password, RegExp.$1) else if (special || arg.length == 0) showFollowersStatus(username, password, arg) else sayHaiku(username, password, arg); }, { bang: true, hereDoc: true, completer: function(filter, special){ if (!filter || !statuses) return [0,[]]; var matches= filter.match(/^([@#]|[-+]\s*)([^\s]*)$/); if (!matches) return [0,[]]; var list = []; var [prefix, target] = [matches[1],matches[2]]; switch (prefix.charAt(0)){ case "+": case "-": if (!special) return; case "@": if (special) list = statuses.map(function(entry) [entry.user.id, entry.text]); else list = statuses.map(function(entry) [entry.user.id + "#" + entry.id, entry.text]); break; case "#": list = statuses.map(function(entry) [entry.keyword, entry.text]); break; } if (target){ list = list.filter(function($_) $_[0].indexOf(target) >= 0); } return [prefix.length, list]; } } ); })(); // vim:sw=4 ts=4 et: