MediaWiki:Gadget-Notification.js

H萌娘,万物皆可H的百科全书!
Mediawiki>夕舞八弦2019年8月6日 (二) 10:06的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

注意:这类代码页面在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

$(function(){
    if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
        return false
    }
    var lock=setInterval(function(){
        if(mw.Api){
            clearInterval(lock);
            function nct(nct, url, life) {
                var life = life || 8000
                if (url) { nct.onclick = function () { open(url, '_blank') } }
                nct.addEventListener('click', function () {
                    setTimeout(function () {
                        nct.close()
                    })
                }, 500)
                setTimeout(function () {
                    nct.close()
                }, life)
            }

            function setCookie(cname, cvalue, GMTStr) {
                var expires = "expires=" + GMTStr;
                document.cookie = cname + "=" + cvalue + "; " + expires;
            }

            function getCookie(cname) {
                var name = cname + "=";
                var ca = document.cookie.split(';');
                for (var i = 0; i < ca.length; i++) {
                    var c = ca[i].trim();
                    if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
                }
                return "";
            }

            function serviceToken(flag) {
                var flag = flag || false
                var d = new Date()
                if (flag) {
                    d.setTime(d.getTime() + (2 * 60 * 1000))
                    setCookie('widget-notification-serviceOn', 'true', d.toGMTString())
                } else {
                    d.setTime(d.getTime() - 1)
                    setCookie('widget-notification-serviceOn', '', d.toGMTString())
                }
            }

            function isObjectValueEqual(a, b) {
                var aProps = Object.getOwnPropertyNames(a);
                var bProps = Object.getOwnPropertyNames(b);

                if (aProps.length != bProps.length) {
                    return false;
                }

                for (var i = 0; i < aProps.length; i++) {
                    var propName = aProps[i];
                    if (a[propName] !== b[propName]) {
                        return false;
                    }
                }
                return true;
            }

            if (typeof Notification == 'undefined') {
                mw.notify('你的浏览器版本过低或不支持某些功能,无法使用Web Notification插件!', { type: 'warn' })
                setTimeout(function () {
                    mw.notify('请从你的用户页移除该插件,以消除这些警告!', { type: 'warn' });
                }, 2000)
                return false
            }

            if (Notification.permission == 'default') {
                alert('点击确定关闭这条消息后,将弹出授予通知权限的窗口,届时请点击“允许”,以保证插件的正常运行。')
            }

            Notification.requestPermission(function () {
                var status = Notification.permission
                if (status == 'granted') {
                    if (!localStorage.getItem('widget-notification-messageMark')) {
                        localStorage.setItem('widget-notification-messageMark', 'true')
                        nct(new Notification('欢迎', {
                            body: '您已经成功开启通知功能,欢迎使用!',
                            icon: 'https://fgo.wiki/resources/assets/wiki.png'
                        }))
                    }
                }
                if (status == 'denied') {
                    alert('您未能正确授予通知权限,若要继续使用,请在url栏左侧点击小锁标志开启权限,若无法设置,请从你的用户页删去此插件。')
                }
            })

            var api = new mw.Api()

            var userName = ''
            api.get({
                "action": "query",
                "format": "json",
                "meta": "userinfo",
                "utf8": 1
            }).done(function (data) {
                userName = data.query.userinfo.name
            })

            var pages = []
            var pagesStr = ''
            var apiContinue = null
            function getWatch() {
                var request = {
                    "action": "query",
                    "format": "json",
                    "list": "watchlistraw",
                    "utf8": 1,
                    "wrlimit": "max"
                }
                if (apiContinue) {
                    request.wrcontinue = apiContinue.wrcontinue
                    request['continue'] = apiContinue['continue']
                } else {
                    delete request.wrcontinue
                    delete request['continue']
                }
                api.get(request).done(function (data) {
                    apiContinue = data['continue']
                    var watch = data.watchlistraw
                    $.each(watch, function () {
                        if (this.title != 'User talk:' + userName) {
                            pages.push(this.title)
                        }
                    })
                    pagesStr = pages.join('|')
                    localStorage.setItem('widget-notification-watchList', pagesStr)
                    apiContinue && getWatch()
                })
            }

            if (location.href == encodeURIComponent('https://fgo.wiki/w/Special:编辑监视列表')) {
                if (/已从您的监视列表移除%d{1,2}个标题/.test($('#mw-content-text').text())) {
                    pages = []
                    getWatch()
                }
            }

            function setWatch(act) {
                var act = act || 'push'
                var watch = localStorage.getItem('widget-notification-watchList').split('|')
                var thisTitle = location.href.replace(/https\:\/\/fgo\.wiki\/w\/(.+)$/, '$1')
                if (/(index\.php|action=edit)/.test(thisTitle)) {
                    thisTitle = thisTitle.replace(/.*title=(.+?)(&.+|$)/, '$1')
                }
                thisTitle = decodeURIComponent(thisTitle)
                var talkTitle = 'Talk:' + thisTitle
                var npRE = /(Template|Mooncell|模块|User|Help):(.+)/
                if (npRE.test(thisTitle)) {
                    var prefix = thisTitle.replace(npRE, '$1')
                    var name = thisTitle.replace(npRE, '$2')
                }
                if (/(Template|Mooncell|User|Help)/.test(prefix)) {
                    talkTitle = prefix + ' talk:' + name
                }
                if (prefix == '模块') {
                    talkTitle = '模块讨论:' + name
                }
                if (act == 'push') {
                    var flag = true
                    $.each(watch, function () {
                        if (this == thisTitle || this == talkTitle) { flag = false }
                    })
                    flag && watch.push(thisTitle, talkTitle)
                }
                (act == 'remove') && $.each(watch, function (i) {
                    if (this == thisTitle || this == talkTitle) {
                        watch[i] = ''
                    }
                })

                var watchStr = watch.join('|')
                localStorage.setItem('widget-notification-watchList', watchStr)
            }

            $('#ca-watch, #ca-unwatch').mousedown(function () {
                (this.id.toLowerCase() == 'ca-watch') && setWatch()
                    ; (this.id.toLowerCase() == 'ca-unwatch') && setWatch('remove')
            })
            $('#mw-editpage-watch').mouseup(function () {
                $('#wpWatchthis').is(':checked') ? setWatch('remove') : setWatch()   // 此处获得了false为选中,true为未选中
            })

            getCookie('widget-notification-serviceOn') != 'true' && main()
            var watchdogKey = setInterval(function () {
                if (getCookie('widget-notification-serviceOn') != 'true') {
                    main()
                    clearInterval(watchdogKey)
                }
            }, 5000 + Math.random())


            function main() {
                console.log('notification.js已开启服务,开始进行消息与监视列表的通知推送。')
                serviceToken(true)
                    ; (function serviceStart() {
                        setTimeout(function () {
                            serviceToken(true)
                            serviceStart()
                        }, 60 * 1000)
                    })()

                $(window).on('unload', function () {
                    serviceToken()
                })

                if (!getCookie('widget-notification-removeTime')) {
                    var d = new Date()
                    d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
                    setCookie('widget-notification-removeTime', d.toGMTString(), d.toGMTString())
                }

                ; (function () {
                    function getTimeISO8061() {
                        var fun = function (num) {
                            return num < 10 ? '0' + num : num
                        }
                        var time = new Date()
                        var y = time.getUTCFullYear(),
                            m = fun(time.getUTCMonth() + 1),
                            d = fun(time.getUTCDate()),
                            h = fun(time.getUTCHours()),
                            i = fun(time.getUTCMinutes()),
                            s = fun(time.getUTCSeconds())
                        var timeStr = y + '-' + m + '-' + d + 'T' + h + ':' + i + ':' + s + 'Z'
                        return timeStr
                    }

                    setTimeout(function () {
                        getWatch()
                        console.log('notification.js:已获取监视列表')
                    }, 30000)

                    var lastSearchTime = getTimeISO8061()
                    setInterval(function () {
                        var usedStr = getCookie('widget-notification-usedIds')
                        if (usedStr) {
                            var used = usedStr.split('|')
                        } else {
                            var used = []
                        }

                        var rcidsStr = getCookie('widget-notification-rcids')
                        if (rcidsStr) {
                            var rcids = rcidsStr.split('|')
                        } else {
                            var rcids = []
                        }

                        var memoryTime = getCookie('widget-notification-lastSearchTime')
                        if (memoryTime) {
                            lastSearchTime = memoryTime
                        }
                        api.get({
                            action: 'query',
                            format: 'json',
                            prop: '',
                            list: 'recentchanges',
                            rcend: lastSearchTime,
                            rclimit: 'max',
                            utf8: 1,
                            formatversion: 1,
                            rctoponly: 1,
                            rcexcludeuser: userName,
                            rcprop: 'title|user|comment|ids'
                        }).done(function (data) {
                            var d = new Date()
                            d.setTime(d.getTime() + (30 * 60 * 1000))
                            setCookie('widget-notification-lastSearchTime', getTimeISO8061(), d.toGMTString())
                            var query = data.query.recentchanges
                            var filter = []
                            var pages = localStorage.getItem('widget-notification-watchList').split('|')
                            $.each(query, function () {
                                for (var i = 0; i < pages.length; i++) {
                                    if (this.title == pages[i]) {
                                        var flag = true
                                        for (var j = 0; j < filter.length; j++) {
                                            if (isObjectValueEqual(this, filter[j])) {
                                                flag = false
                                            }
                                        }
                                        flag && filter.push(this)
                                    }
                                }
                            })

                            $.each(filter, function () {
                                var mark = true
                                for (var i = 0; i < rcids.length; i++) {
                                    if (this.rcids == rcids[i]) {
                                        mark = false
                                    }
                                }

                                if (mark) {
                                    var commentStr = '在【' + this.title + '】作出了编辑。'
                                    if (this.comment) {
                                        this.comment = this.comment.replace('// Edit via Wikiplus', '')
                                        var chapterRE = /\/\* (.+?) \*\/([^\/]*)/
                                        if (chapterRE.test(this.comment)) {
                                            var chapter = this.comment.replace(chapterRE, '$1')
                                            var comment = this.comment.replace(chapterRE, '$2').replace(/[\s]*(.+)[\s]*/, '$1')
                                            if (chapter && (chapter != this.comment)) {
                                                commentStr += '\n章节 → ' + chapter
                                            }
                                            if (comment && (comment != this.comment)) {
                                                commentStr += '\n摘要:' + comment
                                            }
                                        } else {
                                            commentStr += '\n摘要:' + this.comment.replace(/[\s]*(.+)[\s]*/, '$1')
                                        }

                                    }
                                    nct(new Notification(this.user, {
                                        body: commentStr,
                                        icon: '//fgo.wiki/extensions/Avatar/avatar.php?user=' + this.user
                                    }), 'https://fgo.wiki/index.php?title=' + this.title + '&curid=' + this.pageid + '&diff=' + this.revid + '&oldid=' + this.old_revid)
                                    console.log('编辑者:' + this.user + '\n' + commentStr)
                                    rcids.push(this.rcid)
                                }
                                var rcidsStr = rcids.join('|')
                                setCookie('widget-notification-rcids', rcidsStr, getCookie('widget-notification-removeTime'))
                            })
                        })

                        api.get({
                            action: "query",
                            format: "json",
                            prop: "",
                            meta: "notifications",
                            utf8: 1,
                            notfilter: "!read",
                            notlimit: "max"
                        }).done(function (data) {
                            var query = data.query.notifications.list
                            $.each(query, function () {
                                var msgNct = function (text, $this) {
                                    nct(new Notification($this.agent.name + ':', {
                                        body: text,
                                        icon: '//fgo.wiki/extensions/Avatar/avatar.php?user=' + $this.agent.name,
                                        sticky: true
                                    }), 'https://fgo.wiki/w/' + $this.title.full, 9999999999)
                                    console.log($this.agent.name + ':' + text)
                                }

                                var mark = true
                                for (var i = 0; i < used.length; i++) {
                                    if (this.id == used[i]) {
                                        mark = false
                                    }
                                }

                                if (mark) {
                                    switch (this.type) {
                                        case 'edit-thank': {
                                            msgNct('对您在【' + this.title.full + '】的编辑表示了感谢!', this)
                                            break
                                        }
                                        case 'edit-user-talk': {
                                            msgNct('在您的讨论页留言了。', this)
                                            break
                                        }
                                        case 'flowthread_reply': {
                                            msgNct('回复了您在【' + this.title.full + '】的评论。', this)
                                            break
                                        }
                                        case 'flowthread_userpage': {
                                            msgNct('在您的用户页留下了评论。', this)
                                            break
                                        }
                                        case 'flowthread_delete': {
                                            nct(new Notification('通知', {
                                                body: '您在【' + this.title.full + '】下的评论被删除了。',
                                                icon: 'https://fgo.wiki/resources/assets/wiki.png',
                                                sticky: true
                                            }), 'https://fgo.wiki/w/' + this.title.full, 9999999999)
                                            console.log('评论被删除:在页面【' + this.title.full + '】上')
                                            break
                                        }
                                        case 'mention': {
                                            msgNct('在【' + this.title.full + '】中提到了您。', this)
                                            break
                                        }
                                    }
                                    used.push(this.id)
                                }
                            })
                            var usedStr = used.join('|')
                            setCookie('widget-notification-usedIds', usedStr, getCookie('widget-notification-removeTime'))
                        })

                    }, 60000)

                })()

            }
        }
    },1)
})