18

新肺炎态势自动通知服务

 4 years ago
source link: https://juejin.im/post/5e3285c8f265da3e097e9e7c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
2020年01月30日 阅读 3541

新肺炎态势自动通知服务

为抗击新肺炎贡献一份技术力量 项目的拓展应用

对技术细节不感兴趣的同学,可以直接拉到部署环节

├── README.md
├── app.js   # 应用主入口
├── assets
│   └── data  # 数据存储目录
├── config.js # 配置文件
├── info
│   └── info-core.js # 信息采集
├── package.json
├── sender
│   └── email-sender.js # 邮件发送
├── store
│   └── db-store.js  # 数据库API封装
├── templete
│   └── email-templete.js # 邮件模板
└── test.js
复制代码

使用的相关技术构成:

  • 网络请求 : axios
  • 数据采集 : cheerio
  • 数据导出 : nodejs vm
  • 数据存储 : nedb
  • 发送邮件 : nodemailer

应用的处理流程非常简单:

① 获取最新的事件

② 对比数据库中记录的最后一个事件节点,

找出节点之后的事件入库并发送邮件通知

代码比较简单,也有比较详细的注释,直接贴了:

async function refresh(){
    let infos = await info.getInfos();
    if(!infos || infos.length <=0){
        return;
    }
    //时间排序找到最后一个
    let docs = await db.findAndSort({
        sortQuery:{
            createTime:-1
        },
        limit:1
    });
    let newArr = [];
    if(docs && docs.length > 0){
        let doc = docs[0];
        for(let i = 0; i < infos.length; i++){
            let info = infos[i];
            //从新数据中对比逐个插入,直到发现已插入的数据为止. id 作为标记依据
            if(info.id > doc.id){
                //新数据
                newArr.push(info);
                //存入数据库
                await db.insert(info);
            }
        }
    }else{
        //取最新一条作为事件提醒
        newArr.push(infos[0]);
        //没有旧数据,全部存入
        await db.insert(infos);
    }
    if(newArr.length > 0){
        //发送邮件通知
        for(let i = 0; i < newArr.length; i++){
            let info = newArr[i];
            for(let j = 0; j < emails.length; j++){
                let email = emails[j];
                await sender.send({
                    to:email,
                    subject:info.title,
                    html:emailFactory.createEmailHtml({//模板可以自己修改
                        title:info.title,
                        content:info.summary,
                        baseUrl:baseUrl
                    })
                });
            }
        }
    }
}
复制代码

整个项目需要配置的内容都在根路径下的 config.js 中:

const account = {
    from : `"sender-email" <[email protected]>`,  //改成你的邮箱
    host:'smtp.qq.com', //改成对应的邮箱服务商主机,QQ邮箱不用修改可以用这个
    port:'465', //改成对应邮箱服务商端接口,QQ邮箱不用修改可以用这个
    secureConnection:true, // 使用了 ssl
    auth:{
        user:'[email protected]',//用来发送邮件的邮箱,改成你的邮箱
        pass:'password'//邮箱的授权码,改成对应邮箱服务商的授权密码
    }
}

//接收者的邮箱数组
const emails = [
    '[email protected]'
]
复制代码

注释写的很详细,就是配置个人的发送邮箱和收件人邮箱。

收件人配置项是个数组,可以配置多人邮箱,考虑到个人发送邮件还有数量限制,建议不要配置太多。如果有大量的需求,可以购买相关邮箱服务,关于这方面拓展,后面会讲一下。

关于发件人邮箱account的配置参数,每个邮件服务商提供的可能略有区别,到对应的邮箱服务商查看一下相关说明即可。

这里简单说一些QQ邮箱的配置,登录QQ邮箱 -> 设置 -> 账户 -> IMAP/SMTP 服务 -> 开启

开启后会得到一个授权码,是当做密码来用的,这个授权码可以多次产生,配置到 pass 字段上当密码用即可。

项目源码地址

配置好邮箱以后,部署非常的简单。

1. git clone 项目到本地,并进入项目根路径
2. npm install -g pm2 # 安装pm2
3. pm2 start app.js --no-autorestart -c "*/2 * * * *" --name notify # 启动2分钟刷新一次
复制代码

更换为购买的邮箱服务

sender/email-sender.js 中的函数实现改为对应邮箱服务的API实现即可。

邮件内容模板修改

对编写HTML我完全不会,邮件的模板只能是能读到信息流,需要更好看邮件样式的同学,可以修改 templete/email-templte 来实现。

为编写模板可提供的数据有:

{
    "id": 951,
    "pubDate": 1580358836000,
    "pubDateStr": "55分钟前",
    "title": "北京小汤山医院启动修缮",
    "summary": "今天上午,北京市召开了新型冠状病毒感染的肺炎疫情防控工作新闻发布会。会后,北京市卫健委主任雷海潮介绍,目前小汤山医院已经启动修缮。当前,新型冠状病毒感染肺炎疫情防控形势严峻。各地版的“小汤山”医院都在紧锣密鼓的开工当中,北京小汤山康复医院此次修缮,是为了提供更好的就诊条件。这里将视疫情变化启用作为补充。",
    "infoSource": "人民日报",
    "sourceUrl": "http://m.weibo.cn/2803301701/4466411038836152",
    "provinceId": "11",
    "provinceName": "北京市",
    "createTime": 1580359817000,
    "modifyTime": 1580359817000
}
复制代码

数据应该足够了,不够的话需要其他信息也可以提 issues。

如果有人编写了好看模板,可以给我提一个 Pull requests ,感谢。

有些同学邮件是可以正常到达的,但是收不到提醒。

需要注意一下,应用可以送达邮件,但通知提醒是邮箱客户端来实现的.

所以可能需要一个类似QQ邮箱客户端,网易邮箱大师之类的邮箱客户端来登录你的邮箱。

为了避免产生外部依赖,没有直接使用 API项目 的API,信息采集的核心代码是复用的。

如果不介意依赖我提供的线上接口,可以将info-core 中的数据来源改为 data/getTimelineService

1
1

如果有任何问题,可以留言或者加我微信交流:

1

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK