preface

I have always had this idea, but I didn’t do it. Recently, I realized it in my spare time, which also saved me a lot of time looking for articles every day. Isn’t it beautiful

The project structure

|- package.json
|- README.md
|- tsconfig.json
|- src
    |- main.ts // Get the collected data in batches and send an email
    |- email.ts // Configure the message and define the method to send the message
    |- render.ts // Render HTML methods
    |- collection // Collect articles folder|- cnode.ts |- segmentfault.ts |- cloudTencent.ts ... | - making | - workflows | - deploy. Yml # this customCopy the code

Project address github.com/tcly861204/…

Familiarize yourself briefly with the front-end libraries used by the project

  • First: NodeMailer library knowledge

Node uses this library to send mail

const nodemailer = require('nodemailer');
const ejs = require('ejs');
const fs  = require('fs');
const path = require('path');

let transporter = nodemailer.createTransport({
  // host: 'smtp.ethereal.email',
  service: 'qq'.// Use the built-in transport to send mail to view the supported list
  port: 465./ / SMTP port
  secureConnection: true./ / using SSL
  auth: {
    user: '[email protected]'.// This password is not qq password, is your SMTP authorization code
    pass: 'xxxxxx',}});let mailOptions = {
  from: '<[email protected]>'.// sender address
  to: '[email protected]'.// list of receivers
  subject: 'Hello'.// Subject line
  // Send text or HTML
  // text: 'Hello world? ', // plain text body
  html: fs.createReadStream(path.resolve(__dirname, 'email.html')) / / flow
};

// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) = > {
  if (error) {
    return console.log(error);
  }
  console.log(' ');
});


Copy the code
  • Second: Understanding the request library

This library is mainly used by the server to send requests, the interface back to the request to do code analysis, in this project only need to know this point is enough, detailed usage can be Baidu

const request = require('request')
request.get('https://www.baidu.com/'.(error, response, body) = > {
  if(! err && response.statusCode ==200) { 
    console.log(body)
  }
})
Copy the code
  • Third: cheerio

This library is the Node version of jQuery

const cheerio = require('cheerio'),
$ = cheerio.load('<h2 class = "title">Hello world</h2>');
$('h2.title').text('Hello there! ');
$('h2').addClass('welcome');
$.html();
Copy the code

The source code parsing

First look at how to collect the article, take cnode for example, here there is no interface to read, write cnode need not seal my huh

import request, { RequestCallback } from 'request'
import cheerio from 'cheerio'
const uri = 'https://cnodejs.org'
const cnode = function () {
  return new Promise((reslove, reject) = > {
    const callback: RequestCallback = function (error, response, body) {
      if (error) {
        reject(error)
      } else {
        const $ = cheerio.load(body, {
          decodeEntities: false
        })
        const group = $('body').find('#topic_list').find('.cell')
        const data: Array<string> = []
        group.each(function(i) {
          if (i > 4 && i < 20) {
            let title = $(this).find('.topic_title_wrapper').html() title = title! .replace(/(\<span.*\<\/span\>)/g.' ').trim()
            title = title.replace(/ (? <=(href="))/.'https://cnodejs.org').replace('class="topic_title"'.` style=" color: #999; font-weight: normal; text-decoration: none; font-size: 13px;" `)
            data.push(`\t<dl style="list-style-type: none; margin: 0 0 15px 0; padding: 0;" > <span style="color: #999; font-size: 13px;" >${i - 4}. </span>
              ${title}
            </dl>`)
          }
        })
        reslove({
          name: 'cnode',
          data
        })
      }
    }
    return request.get(uri, callback)
  })
}

export default cnode

Copy the code

Configuring Email Sending

import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
  // Send it to QQ
  service: 'QQ'.// Permission authentication
  auth: {
    user: '[email protected]'./ /!!!!! Here read github inside the environment variable, is my own information, local run must need to change here
    pass: process.env.QQ_PASS
  }
})

// To receive a message defined here, you need to leave the email address of the message receiver
const ACCOUNTS = [
  '[email protected]'.'[email protected]'
]

const sendMail = function(options: string) {
  let mailOptions = {
    from: `"cobill"<[email protected]>`.// The email account
    to: ACCOUNTS.join(', '), // The account to receive the mail
    subject: 'Front End must See every day'.// The subject of the message
    html: `${options}`      // The contents of the mail
  }
  transporter.sendMail(mailOptions, (err: any, info: any) = > {
    if(! err) {console.log('The mail has been sent')}}}export default sendMail

Copy the code

Finally is github configuration, do not understand the words can actually Baidu, more detailed than I

name: collection-blog
on:
  push:
    branches: [main]
  schedule:
    # Timed task, push message to mailbox at 5 o 'clock every day
    - cron: '0 21 * * *'

env:
    cache-name: note
    
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Setup Node.js v14.x
        uses: actions/setup-node@v1
        with:
          node-version: '14.x'
  
      - name: Cache nodemodules
        uses: actions/cache@v1
        env:
            cache-name: cache-node-modules
        with:
            The path to the file to cache
            path: ./node_modules 
            A unique identifier to specify for the cached file
            key: The ${{ runner.os }}-build-${{ env.cache-name ${{}} - hashFiles('./package.json') }} 
            Backup option for cache where no target key is found
            restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}-
      - name: Install
        run: npm install # install dependencies

      - name: Build
        env:
          ## QQ_PASS is configured in github Actions secrets
          QQ_PASS: ${{secrets.QQ_PASS}}
        run: npm run build

Copy the code

Project summary

The project is still relatively simple, and then put all the places that need to collect articles together, use fs module to read at one time, use Promise callback to get the collected numbers, and then send emails,

The final look

Only part of it, because I collected several articles