preface

Demand is introduced

Recently had a friend sea-front see nana meters seven seas live every day, as a friend of me was to see not bottom go to, in line with the idle fun to play than attitude suddenly wants to notice the whole a QQ robot dynamic, haizi elder sister live a premiere is pushed to the news group, convenient friends online charge a gift in a timely manner

In this paper, characteristics of

This article is mainly used to briefly introduce the construction of QQ robot, so everything is simple, mainly about the basic principles and implementation functions, if you want to further understand please read the official document

The article is targeted at groups: zero-based groups, patients who do not want to read official documents, togele readers, and crisp sharks

If you are part of the audience, get started!!


Environment to prepare

Knock on the code

There are two main things you need to type code:

  • Node: code environment
  • Vscode: code editor

The code used this time is based on node environment development, so you must install node environment, node download address

Of course, if you don’t want to use the universe super easy to use vscode to knock code, with notepad is not impossible, vscode download address

After downloading the Node environment, enter NPM on the terminal with the following information (or success as long as the command is not found)

If you have any questions, see: How do I Configure the Node Environment


Access to the QQ

Note: QQ robot is the risk of risk control, so do not use your own QQ as a robot, please register a new trumpet

First of all we need a tool to login QQ, this tool can get all the chat information on our QQ, and can output these information to other places, and even control our QQ to send specified information, so where there is so good tool??

This has to say the famous GO-CQHTTP, using it can be very convenient to access QQ and open data communication services, can be understood as we logged in a QQ without an operation interface

First of all, we need to download, download the address, please choose the download package according to your own operating system, if access failure, please scientific Internet access

In the following example, I take Windows as an example. After downloading the application, the terminal may prompt you which service you need to connect to. You can choose multiple services here, but select 2 to select forward WebSocket service, which will automatically generate the default configuration file config.yml in the current directory

If you are a MAC user, the generated configuration file will be placed in the user’s home directory

The following is a brief introduction to the configuration information: First, you need to fill in the login information, here only need to fill in the QQ number and password (here to 123456 as an example), start the application again can realize the login QQ

# config.yml
account: # Account related
  uin: 123456 # QQ account
  password: '123456' If the password is empty, use scan to log in
  encrypt: false  # Whether to enable password encryption
  status: 0      # online status Please refer to the https://docs.go-cqhttp.org/guide/config.html# online status
  relogin: # reconnection Settings
    delay: 3   # First reconnect delay, in seconds
    interval: 3   Reconnection interval
    max-times: 0  # Maximum number of reconnections, 0 is unlimited

  # Whether to use the new address delivered by the server for reconnection
  Note that this setting may result in worse connections on overseas servers
  use-sso-address: true
Copy the code

Remember the address of the enabled Websocket service, which indicates that the local machine will serve as the server and the service port is 6700

# Connect service list
servers:
  - ws:
      # forward WS server listening address
      host: 127.0. 01.
      # forward WS server listening port
      port: 6700
      middlewares:
        < < : *default # reference default middleware
Copy the code

In fact, you can input an account and password to act as a robot, and the other configuration is not changed by default. If you are interested, you can check the official configuration information. The principle of this article is: It works

If the startup is successful, the following information is displayed

At this time, if you use the QQ to speak or receive messages, you will see in the terminal. Yes, the GO-CQHTTP service can monitor all the behavior of the user

Note: Please keep the service open and do not close the terminal


Operating robot

We have been able to log in QQ to get user behavior information, so now we also need to use a thing to control our QQ user to do something we want to do, that is, to turn it into a robot

There are quite a few mature chatbot frameworks out there, and THIS time I chose Koishi for the following reasons:

  • There are a lot of mature community plugins, you can use directly, can not write code to write code, switch man ecstasy
  • Use JS language to write code, cut diagram son ecstasy

Start by creating a new directory, which I will call Koishi -robot. Open the directory path terminal and type in sequence (please make sure you have installed the Node environment before).

npm init -y
npm install koishi koishi-adapter-onebot koishi-plugin-common
Copy the code

First of all, we need to configure QQ information and service information, create a file config.js under the koishi- Robot folder and enter it

// koishi-robot/config.js
module.exports = {
  // Koishi server listens to the port
  port: 8080.onebot: {
    path: ' '.secret: ' ',},bots: [{
    type: 'onebot:ws'.server: 'http://localhost:6700'.selfId: 'Fill in the QQ number here'.token: 'Fill in the QQ password here',}],plugins: {
    'common': {}}}Copy the code

Note: The server must be the same as the go-CqHTTP enabled service address. It can be seen that the configuration information of the server above is the go-CqHTTP address and port

Now you need to generate the robot control service, create a new file app.js under the koishi- Robot folder and enter it

// koishi-robot/app.js
const { App } = require('koishi')
const config = require('./koishi.config')
require('koishi-adapter-onebot')

// Inject the configuration
const app = newApp({ ... config })// Register the plug-in
app.plugin(require('koishi-plugin-common'))

app.start()
Copy the code

Here is the terminal input in the Koishi – Robot path to start our service

node app.js
Copy the code

If successful, the following information is displayed:

At this point we have successfully started the service to control the QQ robot. The koishi-plugin-common plug-in introduced just now has some basic functions built in. You can try to use the echo command to make our robot reply to specified messages

Thus, we have basically created a QQ robot that can be easily understood using the following model


Write a function

The plug-in

Koishi mainly controls our robot behavior in the form of plug-ins, writing a set of logic and then configuring it to use in the service

First of all, for the convenience of development and debugging, we will first install a Nodemon package to enable our service to achieve hot update: that is, to modify the code to update the service immediately without manual restart, and to enter the project path terminal

npm install nodemon
Copy the code

Then modify the package.json in our directory to add the project startup command. At this time, the content of my file is:

{
  "name": "koishi-robot"."version": "1.0.0"."main": "index.js"."license": "MIT"."scripts": {
    "start": "nodemon ./src/app.js"
  },
  "dependencies": {
    "koishi": "^ 3.14.2"."koishi-adapter-onebot": "^ 3.1.0"."koishi-plugin-common": "^ 4.3.5." "."nodemon": "^ 2.0.13"}}Copy the code

Next try to start the service, enter the project path terminal

npm run start
Copy the code

The following is a brief introduction to the writing of the plug-in. In the project directory, create a new file plugin.js

// koishi-robot/plugin.js
function apply(ctx) {}module.exports = {
  name: 'plugin-my-plugin',
  apply
}
Copy the code

You then need to reference the plug-in in the service

// index.js
/ /... Other code
app.plugin(require('./plugin'))
Copy the code

Finally, configure it in the configuration file. (Here, you can use it if you don’t like it, but you should still be in awe of the official document.)

The path to the plugin with a key name, such as.plugin here, corresponds to our plugin.js file

// koishi-robot/config.js
module.exports = {
  / /... Other configuration
  plugins: {
    './plugin': true.// true is equivalent to {}}},Copy the code

Now that we have imported the plug-in, we can write functions for the plug-in. First, we will introduce how to write the middleware

// koishi-robot/plugin.js
function apply(ctx) {
  ctx.middleware((session, next) = > {
    // Here is what the robot should do after receiving the message
    return next()
  })
}
Copy the code

Any message received by the robot will trigger the middleware. We can set here what the robot should do after receiving any message. We can first take a look at what data we get after receiving the message

In order to make the performance more vivid, we don’t mind exposing two small messages of our own. Here are the session information obtained by using 850300443 as the carrier of the robot and 2536671541 as the speaker of the trigger robot

It can be seen that the following main information can be easily obtained at this time:

  • Spokesperson information, such as QQ number, nickname, etc
  • QQ group information, such as QQ group number
  • Chat content, such as text and picture messages, channel (private chat or group chat) and sending time, etc

For example, we could easily write out a feature where a bot sends a message when it finds a specific user in a group

function apply(ctx) {
  ctx.middleware((session, next) = > {
  	// If the user whose QQ id is 2536671541 is detected to speak, send the specified statement
    if(session.userId === '2536671541') {
   	  session.send('Listen to the specified user')}return next()
  })
}
Copy the code

Session.send () is used to send the specified content to the corresponding channel after the robot receives the message, that is, it will reply to the corresponding group or private chat after the message is monitored. Generally, it needs to add a judgment statement, otherwise any speech (no matter what channel) will be replied


instruction

Sometimes, we want to be able to trigger the robot’s actions with commands, such as the original Echo operation, which requires commands

function apply(ctx) {
  ctx
    .command('live'.'Query The broadcast Status of Sister Hai Zi')
    .shortcut("Haizi Sister on the air?")
    .action(({ session }) = > {
      session.send("Got the order? Is Haizi on the air?")})}Copy the code

Description shortcut: command alias which can be used to trigger the command Action: the operation to be done after receiving the command


radio

Now that we know that the machine will send the message only after receiving the message, what is the method that can directly control the robot to send the message to the designated channel? The following is the basic writing method of broadcast

function apply(ctx) {
  ctx.broadcast(
    ['onebot:private:123456'.'onebot:group:654321'].'Sent message')}Copy the code

The above code functions: Manually send the message “sent message” to qq 123456 and QQ group 654321. Onbot refers to a platform, because Koishi can access not only QQ but also other platforms. Onebot refers to QQ platform


News section

Sometimes we hope that the robot can not only make ordinary speeches, but also use message segments to enrich the behavior of the robot. Its principle is to use CQcode to let QQ know the operation of a user. Since go-CQHTTP is used to access QQ, the message segment in Koishi is completely corresponding to the framework. CQcode reference

For example, if we want the robot to poke someone, we could write this

const { segment } = require('koishi')

function apply(ctx) {
  ctx
    .command('live'.'Query The broadcast Status of Sister Hai Zi')
    .shortcut("Haizi Sister on the air?")
    .action(({ session }) = > {
      return segment('poke', {qq: 123456})})}Copy the code

SQL > select segment 123456 from ‘CQcode’


Formally started

Broadcast room information

The basic functions are almost finished, and there are more than the following side to write while introducing it, in fact, according to the above knowledge, at this Time you should almost be able to create a robot function you want, the following began to enter the formal construction link, to create a direct formal entry into the haizi sister live notification robot Time

The following writing method is mainly copied from the community plug-in writing method: Koishi-plugin-blive, a plug-in for b station live

The basic principle is very simple, Hai Zi elder sister live in B station, then request b station live related interface, get hai Zi elder sister live room information

First of all, according to the mysterious power, we got the request interface of the direct broadcast room of station B, and the requested content and returned content are shown in the figure:

  • The id value after the requested address is the room number of station B, for example, the room number of Sister Hai Zi is 21452505

  • The returned content can get the relevant information of the live broadcast room. Here we mainly focus on the live_status field, and the meaning of the value is as follows

    • 0: not aired
    • 1: Live
    • 2: in rotation

And then we need to actively request this interface in our code, so I’m going to send the requestaxiosPackage, so you need to download it in the project

npm install axios
Copy the code

Then in our plug-in to use, here in line with the principle of all simple, not the code to write elegant and consider reuse packaging, all for haizi sister service!!

const axios = require('axios')

async function apply(ctx) {
  const { data } = await axios.get(
    'https://api.live.bilibili.com/room/v1/Room/room_init',
    {
      params: { id: 21452505 },
      headers: {
        'User-Agent':'the Mozilla / 5.0 (Windows NT 10.0; Win64; x64; The rv: 88.0) Gecko / 20100101 Firefox 88.0 / '}})const liveStatus = {
    '0': 'Not on air'.'1': 'Live'.'2': 'In rotation'
  }[data.live_status]
  
  ctx.broadcast(
    ['onebot:group:123456'].'Sister Hai Zi's live status:${liveStatus}`)}Copy the code

The function of the above code: request to obtain the status of haizi sister broadcast, send information to qq group 123456


Loop request

What we need is to get the information immediately as soon as Sister Haizi starts broadcasting. The above code obviously does not meet the requirements. Therefore, what we need is to request the interface every minute and only push the message to the group when the status of sister Haizi’s live broadcast changes

const axios = require('axios')

let preStatus = 0              // Stores the status of the last request
let statusSwitch = false       // Used to store whether the state of the broadcast room has changed since the last request

function apply(ctx) {
  // The following code is triggered when Koishi accesses the GO-CQHTTP service
  ctx.on('connect'.() = > {
    setInterval(async() = > {const { data } = await axios.get(
        'https://api.live.bilibili.com/room/v1/Room/room_init',
        {
          params: { id: 21452505 },
          headers: {
            'User-Agent':'the Mozilla / 5.0 (Windows NT 10.0; Win64; x64; The rv: 88.0) Gecko / 20100101 Firefox 88.0 / '}})if(preStatus ! == data.live_status) { statusSwitch =true
        preStatus = data.live_status
      } else {
        statusSwitch = false
      }

      // If the live stream status changes, send messages to the designated QQ group
      if(statusSwitch) {
        const message = preStatus ? 'Sister Haizi is playing it.' : 'Hai Zi Jie is on the air'

        ctx.broadcast(
          ['onebot:group:123456'],
          message
        )
      }
    }, 60 * 1000)   // Repeat for 60 seconds})}Copy the code

The function of the above code is: request the live broadcast information once every minute, once the live broadcast status changes, send push message to the QQ group, pay attention to the repetition time is not too short, do not high-frequency request interface may be limited by B station request (do not ask me how to know)


QQxml

Note: XML is a black technology, sending qq number many times will lead to risk control, resulting in the normal sending OF XML, here is just a brief introduction, the specific implementation can be used to try new small (the author has been risk control 4 small in order to debug the code

Now we have a simple live push robot haizi Sister to complete the function, but there are still some shortcomings in the speech, only to send a text is not elegant, so we introduced QQxml to realize the function of sending QQ cards

Koishi can send a piece of XML code through QQcode, which is parsed internally by QQ and turned into a specific message effect, such as QQ’s card information

Since I don’t know much about risk, I’ll just take a look at the two templates and effects of XML. XML code requires a special header declaration, as shown below


      
Copy the code

QQ cards use the < MSG >
tag to wrap content

<msg serviceID="1" templateID="1" action="web" brief="Click to go to the studio." sourceMsgId="0" url="https://live.bilibili.com/21452505?spm_id_from=333.999.0.0" flag="0" adverSign="0" multiMsgFlag="0">
  <! -- Card content -->
</msg>
Copy the code

Brief: Preview information seen outside the chat box URL: Click the card to jump to the other unknown what effect ~

The following are the templates for two XML cards that were tried out, while other configuration attempts were somewhat problematic


      
  <msg serviceID="1" templateID="1" action="web" brief="Click to go to the studio." sourceMsgId="0" url="https://live.bilibili.com/21452505?spm_id_from=333.999.0.0" flag="0" adverSign="0" multiMsgFlag="0">
  <item layout="6" advertiser_id="0" aid="0">
  <picture cover="http://gchat.qpic.cn/gchatpic_new/0/530077417-0-094758B3DD39603D0E8563D47959D8E7/0" w="0" h="0" />
  </item>
  <item layout="6" advertiser_id="0" aid="0">
  <title>Sister Haizi live broadcast room</title>
    <summary>${liveStatus}${liveStartTime}${liveTime}</summary>
  </item>
  <source name="Billie Billie" icon="http://gchat.qpic.cn/gchatpic_new/0/530077417-0-01006648643525F8630A9A97C5959700/0" action="" appid="1" />
</msg>
Copy the code


      
<msg serviceID="1" templateID="1" action="web" brief="Click to go to the studio." sourceMsgId="0" url="https://live.bilibili.com/21452505?spm_id_from=333.999.0.0" flag="0" adverSign="0" multiMsgFlag="0">
  <item layout="2" advertiser_id="0" aid="0">
    <picture cover="http://gchat.qpic.cn/gchatpic_new/0/530077417-0-094758B3DD39603D0E8563D47959D8E7/0" w="0" h="0" />
    <title>Sister Haizi live broadcast room</title>
    <summary>${liveStatus}${liveStartTime}${liveTime}</summary>
  </item>
  <source name="Billie Billie" icon="http://gchat.qpic.cn/gchatpic_new/0/530077417-0-01006648643525F8630A9A97C5959700/0" action="" appid="1" />
</msg>
Copy the code

By contrast, you have noticed that the picture address here is not the address of any picture on the network. This is the picture bed inside QQ. Pictures directly used on the Network can be normally displayed in the card on the mobile phone, but will be cracked on the PC

This is because THE PC card reference is QQ’s own map in the bed, if you really want to normal display on the PC can be operated as follows:

  • Manually get the MD5 value of a downloaded image (all uppercase)
  • Use QQ to send a messagehttp://gchat.qpic.cn/gchatpic_new/0/530077417-0- < fill in this md5 value, do not need Angle brackets > / 0, this step is equivalent to the picture saved to QQ inside
  • B station detailed tutorial

Afterword.

So far we’ve implemented all the features we want, and I’m sure you don’t have to be a crunchy shark to figure out how to make a robot you want

There is a problem that is now we are using the computer ACTS as a server, it means that we want our robot work will have to open the computer all day, this is not realistic, so we need to buy a server, then put our project to the server, and run on the server

The choice of the server has a lot of, such as Ali cloud, Tencent cloud, if you have been determined to spend money to get the server, then I believe you can go to Baidu search out how to buy a server and deployment project, here is not introduced