# Web Data Monitor User Guide

## Introduction

Web Data Monitor： [Chrome 商店链接](https://chrome.google.com/webstore/detail/web-data-monitor/jicncdodkpdlndbppohjljcggoemckjp)\
这是一个自定义可编程的网络数据监控框架。\
扩展提供了基于 Javascript 编程语言以及 jQuery 工具库的支持让用户可以编程自定义监控及提醒逻辑，\
通过它用户可以监控任意网页或接口数据变更，实现如股价提醒，商品打折提醒，剧漫更新提醒，RSS更新提醒，直播通知，新邮件提，网站签到等等功能。

## Simple Document​​​

![添加任务界面](https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M4AAOASfUyLQa_RzFtB%2F-M4AAcp0Zi6f5Hd-CiAL%2FaddTask.png?alt=media\&token=f8e101c4-db27-49ef-a48a-85b038887596)

1. ​任务名称：用于任务说明以及唯一标记
2. 相关页面：点击提醒时默认打开页面的url
3. 监测周期：调用网络请求周期
4. 允许弹窗提醒：弹窗提醒控制（优先级高于代码逻辑）
5. 请求参数：基础参数已列出，具体可参考 jQuery ajax请求参数 API 文档（如遇网站复杂请求参数可以通过Chrome浏览器开发者工具拿到curl再通过[工具网站](https://curlconverter.com/javascript-jquery/)转换获取）
6. 数据处理：相关代码说明如下

```javascript
//以下是几个预置变量说明
//queryResult  调用jQuery ajax请求返回的结果，格式根据请求参数可以是JSON或者HTML文本或者XML
//presetPageUrl 配置中的相关页面url
//isRefresh 是否是主动点击刷新标志位
//lastReturn 上一次处理的返回，具体可看最下return返回代码
 
var highlight = lastReturn.highlight;//是否高亮显示
var popup = lastReturn.popup;//是否弹框提醒
var url = presetPageUrl;//点击打开页面url
var content = lastReturn.content;//条目显示文本
var extra = lastReturn.extra;//额外数据
//以上部分为默认设置一般无需修改
 
//此处添加处理代码，根据queryResult和isRefresh确定highlight,popup,url,content,extra
//此处还可以添加额外的操作，如调用其他API实现邮件微信提醒等
 
//返回处理结果一般无需修改
//扩展根据返回结果进行高亮，弹窗，显示说明等操作
return {'highlight':highlight,'popup':popup,'url':url,'content':content,'extra':extra};
```

## Basic Usage​

### 各种更新提醒

```javascript
//queryResult
//presetPageUrl  isRefresh  lastReturn
var highlight = lastReturn.highlight;
var popup = lastReturn.popup;
var url = presetPageUrl;
var content = lastReturn.content;
var extra = lastReturn.extra;
 
//此处可以通过CSS选择器，正则或者读取JSON对象来定位获取更新后不相同的部分
//此示例基本可以实现类似Chrome扩展的所有功能
queryResult = $(queryResult).find('#video_list_li a:last').text();//1 
 
content = '更新到了 ' + queryResult;
if (content != lastReturn.content) {
    highlight = true;
    popup = true;
}
 
 
return {'highlight':highlight,'popup':popup,'url':url,'content':content,'extra':extra};
```

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M5wazljAB1g62283nLS%2F-M4EOcjlVu7aYnSDMVtw%2FRSS%E6%9B%B4%E6%96%B0%E6%8F%90%E9%86%92.json?alt=media&token=1f915bbc-cfa2-4507-969c-43f87fbe5e67>" %}

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M5wazljAB1g62283nLS%2F-M4AQzv_cIbe9mZufmPd%2F%E3%80%8A%E6%B5%B7%E8%B4%BC%E7%8E%8B%E3%80%8B%E6%BC%AB%E7%94%BB%E6%9B%B4%E6%96%B0%E6%8F%90%E9%86%92.json?alt=media&token=3cb08473-1b28-4a3f-ad28-b139ec379246>" %}

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M73qntYRIhyt5DUPr-e%2F-M4AQrMxFw764KhiS4_9%2F%E6%96%97%E9%B1%BC%E5%8D%95%E4%B8%AA%E6%8F%90%E9%86%92%EF%BC%88%E6%97%A0%E9%9C%80%E7%99%BB%E5%BD%95%EF%BC%8C%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE%E5%85%B7%E4%BD%93%E9%A1%B5%E9%9D%A2url%EF%BC%89.json?alt=media&token=2432f56b-7c47-4a69-ac25-07e6470f481d>" %}

### 邮件提醒示例

```javascript
//queryResult
//presetPageUrl  isRefresh  lastReturn
var highlight = lastReturn.highlight;
var popup = lastReturn.popup;
var url = presetPageUrl;
var content = lastReturn.content;
var extra = lastReturn.extra;
 

if (queryResult.indexOf('unreadMessageCount') == -1) {//1 此处为判断登陆的代码，不同邮箱不同
    highlight = true;
    popup = content != '登录失效，请重新登录！';
    content = '登录失效，请重新登录！';
} else {
    //2 此处为用于获取邮件数量的代码
    var count = Number(new RegExp('folderStats.*?\'unreadMessageCount\':(.*?),', 'ig').exec(queryResult)[1]); 
    extra = count;
    var lastCount = lastReturn.extra;
 
    content = count == 0 ? '暂无新邮件' : '收到 ' + count + ' 封新邮件';
    if (count == 0) {
        highlight = false;
        popup = false;
    }
    else if (count > lastCount) {
        highlight = true;
        popup = true;
    } else if (count > 0 && isRefresh) {
        highlight = true;
        popup = false;
    } else if (count < lastCount) {
        popup = false;
    }
}
 
 
return {'highlight':highlight,'popup':popup,'url':url,'content':content,'extra':extra};
```

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M5wazljAB1g62283nLS%2F-M4AQrMv-Z2ghKd8qQvd%2F%E7%BD%91%E6%98%93%E9%82%AE%E7%AE%B1%E6%96%B0%E9%82%AE%E4%BB%B6%E6%8F%90%E9%86%92%EF%BC%88%E9%9C%80%E7%99%BB%E9%99%86%EF%BC%89.json?alt=media&token=8a157151-a42c-4465-afeb-dbcf5d09bf5e>" %}

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M5wazljAB1g62283nLS%2F-M4E_PeTpRP8wQk2VrQB%2FV2EX%E6%96%B0%E6%B6%88%E6%81%AF%E6%8F%90%E9%86%92.json?alt=media&token=83643c21-1fe7-4e9b-9e46-ad4514cb1971>" %}

### 直播提醒示例

```javascript
//queryResult
//presetPageUrl  isRefresh  lastReturn
var highlight = lastReturn.highlight;
var popup = lastReturn.popup;
var url = presetPageUrl;
var content = lastReturn.content;
var extra = lastReturn.extra;


if (queryResult.error == -1) {//1 判断登陆状态
    highlight = true;
    popup = content != '登录失效，请重新登录！';
    content = '登陆失效，请重新登录！';
} else {
    var onLiveInfoList = extra ? JSON.parse(extra) : [];
    var nowOnLiveInfoList = [];
    var newOnline = false;
    var newOffline = false;
    var baseUrl = 'https://www.douyu.com';//2 用于拼接完整直播间网址，一般直播网站都会需要

    queryResult = queryResult.data.list;//3 从JSON数据中获取到直播间列表
    for (let i = 0; i < queryResult.length; i++) {
        if (queryResult[i].show_status == 1) {//4 判断是否在线
            onLiveInfo = {
                'name': queryResult[i].nickname,//5 直播间名
                'subUrl': queryResult[i].url,//6 直播间子网址
            };
            nowOnLiveInfoList.push(onLiveInfo);
        }
    }

    //维护onLiveInfoList
    //移除已下线
    var newOnlineNameMap = {};
    for (let i = 0; i < nowOnLiveInfoList.length; i++) {
        newOnlineNameMap[nowOnLiveInfoList[i].name] = i;
    }
    for (let i = onLiveInfoList.length - 1; i >= 0; i--) {
        if (newOnlineNameMap[onLiveInfoList[i].name] == undefined) {
            newOffline = true;
            onLiveInfoList.splice(i, 1);
        }
    }
    //添加新上线
    var onLiveNameMap = {};
    for (let i = 0; i < onLiveInfoList.length; i++) {
        onLiveNameMap[onLiveInfoList[i].name] = i;
    }
    for (let i = 0; i < nowOnLiveInfoList.length; i++) {
        if (onLiveNameMap[nowOnLiveInfoList[i].name] == undefined) {
            newOnline = true;
            onLiveInfoList.unshift(nowOnLiveInfoList[i]);
        }
    }
    extra = JSON.stringify(onLiveInfoList);

    for (let i = 0; i < onLiveInfoList.length; i++) {
        if (i == 0) {
            content = '当前有' + onLiveInfoList.length + '人正在直播：\n';
            content += onLiveInfoList[i].name + '(最新) ';
            url = baseUrl + onLiveInfoList[i].subUrl;
        } else {
            content += ', ' + onLiveInfoList[i].name;
        }
    }
    if (onLiveInfoList.length == 0) {
        content = '暂无人直播';
        highlight = false;
        popup = false;
    } else if (newOnline) {
        highlight = true;
        popup = true;
    } else if (onLiveInfoList.length > 0 && isRefresh) {
        highlight = true;
        popup = false;
    } else if (onLiveInfoList.length > 0 && newOffline) {
        popup = false;
    }
}


return {'highlight': highlight, 'popup': popup, 'url': url, 'content': content, 'extra': extra};
```

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M5wazljAB1g62283nLS%2F-M4AQrMndpVG5bph1ULc%2F%E6%96%97%E9%B1%BC%E8%81%9A%E5%90%88%E7%9B%B4%E6%92%AD%E6%8F%90%E9%86%92%EF%BC%88%E9%9C%80%E7%99%BB%E9%99%86%EF%BC%89.json?alt=media&token=4a33ab6a-9a31-46d0-a7a1-d508e1d1be78>" %}

### 站点签到示例

```javascript
//queryResult
//presetPageUrl  isRefresh  lastReturn
var highlight = lastReturn.highlight;
var popup = lastReturn.popup;
var url = presetPageUrl;
var content = lastReturn.content;
var extra = lastReturn.extra;
 
 
if ($(queryResult).find('.inner').length == 0) {//1
    highlight = true;
    popup = content != '登录失效，请重新登录！';
    content = '登录失效，请重新登录！';
} else {
    if (queryResult.indexOf('领取今日的登录奖励') != -1) {//2
        var once = new RegExp(/\?once=(\d*?)\';/, 'ig').exec(queryResult)[1];
        $.ajax({
            "type": "get",
            "async": false,
            "url": "https://www.v2ex.com/mission/daily/redeem?once=" + once,
            "dataType": "html",
            "timeout": 7000,
            success: function (res) {
                highlight = true;
                content = '签到成功';
            }
        });
    } else {
        highlight = false;
        content = '已签到';
    }
}
 
 
return {'highlight': highlight, 'popup': popup, 'url': url, 'content': content, 'extra': extra};
```

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M8v0gqgq4XZUficOY6K%2F-M8v33PP8leCkfQEvii-%2F52%E7%A0%B4%E8%A7%A3%20%E7%AD%BE%E5%88%B0.json?alt=media&token=f39866a2-8b00-42af-9fcb-33f82fe22b36>" %}

{% file src="<https://320857801-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M49rkcQxZAZhvi4_qZ7%2F-M8v0gqgq4XZUficOY6K%2F-M8v37wPV1FzNvgfg70Y%2FBilibili%E7%9B%B4%E6%92%AD%20%E7%AD%BE%E5%88%B0.json?alt=media&token=4221e969-f59b-43d7-a302-cc6da5f5f9b9>" %}

## Other Extensions

最后附上本人开发的另外几个实用的 Chrome 扩展

Tab Freezer： [Chrome 商店链接](https://chrome.google.com/webstore/detail/tab-freezer/opmcmbcmkbobnbloaanbgminfokciinp)\
这个扩展是提供给海量标签页综合症 TMTS (Too Many Tabs Syndrome) 患者的（比如我自己），冻结页面节省内存（然后打开更多的标签，，？？？），相比于其他 OneTab 等扩展，有两个优点，1. 标签页不会关闭；2. 点击即可生效，不会再弹出扩展弹框

Volume Manager： [Chrome 商店链接](https://chrome.google.com/webstore/detail/volume-manager/ogpbjlhpdjmcbkocjibemdmblffnfkmm)\
这个扩展是用来控制页面内音频视频的音量的，应该是 Chrome 市场里最完善的一款音量控制扩展了。\
不仅支持 HTML5 标准的音频视频同时也支持 Flash，最关键的是可以记忆每个页面或者网站的音量修改配置。

Regex Extractor： [Chrome 商店链接](https://chrome.google.com/webstore/detail/regex-extracter/hhnkaciopdblfpomobniofiiecfiibph)\
这个扩展的功能简单来说就是用正则表达式查询当前网页内的文本，默认如果正则中有捕获就返回捕获部分的文本，\
支持文本、节点和源码三种模式，常用的场景比如：批量获取邮箱，批量获取图片链接，批量获取动漫电视剧每集的下载链接等。
