cirry

cirry

我的原生博客地址:https://cirry.cn

Installing Comment Function in Hexo(4)

Update on 2022-11-17#

Today I found that the comment functionality on the blog suddenly stopped working, and it turned out to be an issue with version updates. Previously, I was using the latest waline code, but now I have switched to using a fixed version of the waline code.

In the themes/maupassant/layout/_partial/comments.pug file, modify the following line of code:

This line of code:

script(src='//unpkg.com/@waline/client@v2/dist/waline.js')

Replace it with:

script(src='//unpkg.com/@waline/[email protected]/dist/waline.js')

Prerequisites#

  1. A server with a Docker environment
  2. Familiarity with docker-compose, postgres, and caddy

Here we will use docker + waline + postgres + caddy to set up our own comment system. For detailed information, please refer to the waline official website.

Configure PostgreSQL Database#

Note: If you do not have a database, you can also use the built-in sqlite database for deployment.

First, check the official multi-database service support documentation for PostgreSQL database support. You need to create the tables and table structures first.

In https://github.com/walinejs/waline/blob/main/assets/waline.pgsql, simply copy the content and run it in the PostgreSQL command line to create it successfully. Here I am using pgAdmin (a management tool for PostgreSQL).

If you cannot access the official website, you can also copy the content below directly into the database command line and press enter.

CREATE SEQUENCE wl_comment_seq;

CREATE TABLE wl_comment (
  id int check (id > 0) NOT NULL DEFAULT NEXTVAL ('wl_comment_seq'),
  user_id int DEFAULT NULL,
  comment text,
  insertedAt timestamp(0) without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
  ip varchar(100) DEFAULT '',
  link varchar(255) DEFAULT NULL,
  mail varchar(255) DEFAULT NULL,
  nick varchar(255) DEFAULT NULL,
  pid int DEFAULT NULL,
  rid int DEFAULT NULL,
  sticky boolean DEFAULT NULL,
  status varchar(50) NOT NULL DEFAULT '',
  "like" int DEFAULT NULL,
  ua text,
  url varchar(255) DEFAULT NULL,
  createdAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  updatedAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) ;


CREATE SEQUENCE wl_counter_seq;

CREATE TABLE wl_counter (
  id int check (id > 0) NOT NULL DEFAULT NEXTVAL ('wl_counter_seq'),
  time int DEFAULT NULL,
  url varchar(255) NOT NULL DEFAULT '',
  createdAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  updatedAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) ;


CREATE SEQUENCE wl_users_seq;

CREATE TABLE wl_users (
  id int check (id > 0) NOT NULL DEFAULT NEXTVAL ('wl_users_seq'),
  display_name varchar(255) NOT NULL DEFAULT '',
  email varchar(255) NOT NULL DEFAULT '',
  password varchar(255) NOT NULL DEFAULT '',
  type varchar(50) NOT NULL DEFAULT '',
  label varchar(255) DEFAULT NULL,
  url varchar(255) DEFAULT NULL,
  avatar varchar(255) DEFAULT NULL,
  github varchar(255) DEFAULT NULL,
  twitter varchar(255) DEFAULT NULL,
  facebook varchar(255) DEFAULT NULL,
  google varchar(255) DEFAULT NULL,
  weibo varchar(255) DEFAULT NULL,
  qq varchar(255) DEFAULT NULL,
  "2fa" varchar(32) DEFAULT NULL,
  createdAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  updatedAt timestamp(0) without time zone NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) ;

The specific process for creating the tables is as follows:

image

Deploy Waline with Docker#

Create a new docker-compose.yml file in an appropriate location with the following content:

# docker-compose.yml

version: '3'  

services:

  waline:

    container_name: waline

    image: lizheming/waline:latest

    restart: unless-stopped

    ports:

      - 9015:8360 # The port number 9015 can be modified arbitrarily, as long as it does not conflict with other applications

    environment:

      TZ: 'Asia/Shanghai'

      SITE_NAME: "Cai Xiao Niu's Blog"

      SITE_URL: 'https://cirry.cn' # Website URL

      SECURE_DOMAINS: 'cirry.cn' # Domain name

      AUTHOR_EMAIL: '[email protected]' # Email
 
      PG_HOST: ******.cirry.fun # Database address, please fill in your own database address

      PG_PORT: 5432 # Database port, the default port for PostgreSQL is 5432

      PG_DB: hexo # Database name

      PG_USER: ****** # Database user, please fill in your own username

      PG_PASSWORD: ****** # Database password, please fill in your own password

Configure Caddy#

Expose the waline service running on port 9015 through caddy for reverse proxy and add SSL encryption.

# Caddyfile
# Configure your own website, each person's configuration is different, please do not copy directly
https://waline.cirry.cn:66666 {

    reverse_proxy localhost:9015

}

Configure Theme#

In _config.maupassant.yml, modify the following content:

waline: ## See: https://waline.js.org/  
  enable: true ## If you want to use the Waline comment system, please set the value to true.  
  serverURL: https://waline.cirry.cn:66666 ## Your server URL, e.g. https://your-domain.vercel.app  
  pageSize: 10 ## The desired number of comments shown on each page.

At this point, the comment functionality has been fully set up on your own server. After clearing the cache and restarting, the style is as follows:

image

Enable Recent Comments Function in Sidebar#

Although the configuration option for recent comments is enabled in _config.maupassant.yml, the style does not display after configuration.

widgets: ## Seven widgets in the sidebar provided: search, info, category, tag, recent_posts, recent_comments, and links.  
  - search  
  - info  
  - category  
  - tag  
  - recent_posts  
  - recent_comments  # Mount recent comments functionality
  - links

In themes/maupassant/layout/_widget/recent_comments.pug, we can see that the theme only configures the recent comments functionality for disqus by default, so next, we will write our own waline recent comments functionality.

if theme.disqus.enable == true  
  .widget  
    .widget-title  
      i.fa.fa-comment-o= ' ' + __('recent_comments')  
    script(type='text/javascript', src='//' + theme.disqus.shortname + '.disqus.com/recent_comments_widget.js?num_items=5&hide_avatars=1&avatar_size=32&excerpt_length=20&hide_mods=1')

First step, add a new configuration item in _config.maupassant.yml:

waline: ## See: https://waline.js.org/  
  enable: true ## If you want to use the Waline comment system, please set the value to true.  
  serverURL: https://************ ## Your server URL, e.g. https://your-domain.vercel.app  
  pageSize: 20 ## The desired number of comments shown on each page.  
  wordLimit: 500 ## Limit input word count, 0 means no limit  
  requiredMeta: ['nick','mail'] ## required user information e.g. ['nick','mail','link']  
  count: 6 ## The number of recent comments, default is 10

Second step: In themes/maupassant/layout/_widget/recent_comments.pug, modify the content as follows:

if theme.disqus.enable == true  
  .widget  
    .widget-title  
      i.fa.fa-comment-o= ' ' + __('recent_comments')  
    script(type='text/javascript', src='//' + theme.disqus.shortname + '.disqus.com/recent_comments_widget.js?num_items=5&hide_avatars=1&avatar_size=32&excerpt_length=20&hide_mods=1')  
  
if theme.waline.enable == true  
  .widget  
    .widget-title  
      i.fa.fa-comment-o= ' ' + __('recent_comments')  
    #widget-waline-list  
    script(type='text/javascript', id="recent-comment", serverURL=theme.waline.serverURL, count=theme.waline.count , src=url_for(theme.js) + '/recent-comments.js' + '?v=' + theme.version, async)

Third step: Since this involves sending requests, we first need to create a js file named recent-comments.js in the themes/maupassant/source/js/ directory.

Fill in the content of recent-comments.js as follows:

!function () {  
  let serverURL = document.getElementById("recent-comment").getAttribute("serverURL")  
  let count = document.getElementById("recent-comment").getAttribute("count")  
  if (!count) {  
    count = 10  
  }  
  
  // Format time  
  function format( date ) {  
    return new Date(date).toLocaleString()  
  }  
  
  // Handle comments  
  function dealComment( commentStr ) {  
    let re = /<a[^>]*href=['"]([^\\"]*)['"][^>]*>(.*?)<\/a>/g;  
    let arr = [];  
    while (re.exec(commentStr) != null) {  
      arr.push(RegExp.$1); // If it is RegExp.$1, then the matched part is the href attribute!  
      arr.push(RegExp.$2)  
    }  
    if (arr.length > 0) { // Indicates that a reply has been matched  
      commentStr = commentStr.replace(/<a[^>](.*?)<\/a>/, arr[1])  
      return {  
        href: arr[0],  
        author: arr[1],  
        str: commentStr  
      }  
    }  
    return ''  
  }  
  
  $.ajax({  
    url: serverURL + '/comment?type=recent',  
    dataType: 'json',  
    data: {  
      count  
    },  
    success: function ( response ) {  
      let comments = '<ul>'  
      response.forEach(( comment, index ) => {  
        comments += '<li>' + (index + 1) + '、 ' + format(comment.insertedAt)  
        if (comment.pid) {  
          let {href, author, str} = dealComment(comment.comment)  
          comments += '<div class="waline-comment-content"><a style="display: block" href=' + window.location.origin + comment.url + href + '>'+ str + '</a></div>'  
        } else {  
          comments += '<div class="waline-comment-content"><a style="display: block" href=' + window.location.origin + comment.url + '#' + comment.objectId + '>' + comment.comment + '</a></div>'  
        }  
        comments += '<div class="waline-comment-content-author">' + '--' + comment.nick + '</div></li>'  
      })  
      comments += '</ul>'  
      $('#widget-waline-list').append(comments)  
    },  
  })  
}()

This involves the recent comments interface provided by waline. You can check the waline provided API here.

Fourth step: Adjust styles

This step is only for cases where users have entered emoji expressions in comments, as emojis may appear too large. We will locate the style in themes/maupassant/source/css/style.scss, specifically in the following position:

image

Add the following code under #sidebar --> .widget --> ul --> li.

.wl-emoji{  
  width: 16px;  
}

Finally, append the following style at the end of themes/maupassant/source/css/style.scss:

/* recent-comments waline style*/  
.waline-comment-content {  
    padding: 6px;
    background-color: #f8f8f8;
    border-radius: 6px;
    overflow: auto;
  
    p {  
        margin: 0;  
        display : -webkit-box;  
        overflow: hidden;  
        -webkit-box-orient: vertical;  
        -webkit-line-clamp: 2; /* Here you can set how many lines to show before truncating with ellipsis */  
    }  
}  
  
.waline-comment-content-author {  
    text-align: end;  
    margin-bottom: 6px;  
}

Enable Word Count Limit and Disable Anonymity#

In themes/maupassant/layout/_partial/comments.pug, find the waline.init method and add a configuration item in the method.

Waline.init({  
  el: '#waline',  
  comment: true,  
  serverURL: '#{theme.waline.serverURL}',  
  pageSize: '#{theme.waline.pageSize}',  
  wordLimit: 300,  
  requiredMeta:['nick', 'mail'],
})

Note: Waline has its own spam filtering feature, but it is still better to limit the input from visitors to prevent malicious actions.

Enable Email Notifications#

Here I will directly use QQEmail as the email service provider.

In the docker-compose.yml under environment, add the following email service provider configuration information:

SMTP_HOST: "smtp.qq.com"

SMTP_PORT: 465

SMTP_USER: "your qq email"

SMTP_PASS: "authorization code provided by qq email"

SMTP_SECURE: "true"

Note: The authorization code for qq email can be obtained by going to Login to qq email --> Settings --> Account --> Generate Authorization Code.

Waline also has a feature to count reading times. I have already used a service called "不蒜子" (Bu Suan Zi) for this, so I won't repeat it here. If it becomes unusable later, I may switch to this one.

This article requires a lot of knowledge. If you have any questions, feel free to leave a comment, and I can write a detailed article on specific topics.

Disable Comment Functionality on Certain Pages#

If you do not want the comment functionality on pages like About Me or History, simply set comments: false in the front matter of the corresponding document.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.