preface

It happened that the Nuggets had a new sign-in activity. It happened that they couldn’t sleep after drinking coffee and didn’t have to go to work during the double holidays. So I wrote a plug-in to facilitate weekday sign-in (by the way of practicing hands).

Let’s look at the finished product first

In summary, the plug-in needs to achieve the following goals:

  1. Detects the current user login status
  2. Determine if the user has checked in today
  3. Send a check-in request
  4. Display information (user information, reward information)

Analysis of the request

User login credentials

[POST] / Passport/Web/User/Login: The Cookie set by the request response contains several key-value pairs. If you select a normal request for PostMan analysis, you can see that the Nugget uses the SESSIONID in the Cookie as the login credentials of the user

Check-in to the relevant interface

In the request of check-in function, there are 4 interfaces related to the function to be realized this time, respectively:

  1. Gets a summary of the number of days you signed in[GET]/growth_api/v1/get_counts
  2. Get the current number of ores[GET]/growth_api/v1/get_cur_point
  3. Determine if the user has checked in today[GET]/growth_api/v1/get_today_status
  4. User sign in[POST]/growth_api/v1/check_in

Here is a brief analysis of the function corresponding to the request, the specific parameters and the meaning of the return value can be viewed through the browser console (
F12)

The flow chart

The following is a sequence diagram of several scenarios to illustrate the workflow of the plug-in

Unlogged scenario

Scenes not checked in

Checked in scene

Build Chrome plugin development project

Quickly build Chrome plugin development project (VUE) with VUE-Web-Extension

First, make sure these two are installed

npm install -g @vue/cli
npm install -g @vue/cli-init

I then created the project with Vue-Web-Extension. I selected Vue-Web-Extension as version V1

vue init kocal/vue-web-extension#v1 juejin-auto-sign

Select the features you want on demand (Axios must)

Install Element UI (load on demand)

cd juejin-auto-sign && vue add element

Because the Element UI configuration is written in the Babel section of the package.json file, which overlaps with the project’s original.babelrc configuration file, the configuration for Babel in the package.json file needs to be merged into the.babelrc file

Before the merger

#.babelrc configuration file {"plugins": ["@babel/plugin-proposal-optional-chaining"], "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3, "targets": { // https://jamie.build/last-2-versions "browsers": [" > 0.25% ", "not ie 11", "not op_mini all"]}}}]] # package. The json configuration file {... "babel": { "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] } }

After the merge, remove the Babel part of package.json. The.babelrc configuration file is as follows

Execute yarn build in the root of the project, and it will pack normally

yarn build

So far, the project has been basically completed! It can be formally put into development

Common engineering commands:

  • Yarn Build builds the plug-in and outputs it to the dist directory
  • Yarn Build-Zip builds a plug-in archive in the form of a plug-in name + version number
  • yarn watchBuild the plug-in, export it to the dist directory, and refresh it immediately if any changes are made

The key code

MANIFEST. JSON configuration file

The manifest. Json file records the original information of the plug-in, including the basic information of the plug-in (plug-in name, version number, ICON, etc.), the related page of the plug-in (popup, options, background, etc.), and the permissions that the plug-in needs to apply to Chrome

{// Plugin name" name": "Juejin-auto-sign ", // Plugin description" description":" Nugget Sign-in Helper ", // Plugin version number "version": "1.0.0", "Manif_version ": 2, "icons": { "48": "icons/icon.png", "128": "icons/icon.png" }, ...... // Permissions: [" Cookies ", "*://*.juejin.cn ", "WebRequest "," WebRequest "]} Permissions: [" Cookies ", "*://*.juejin.cn ", "WebRequest "," WebRequest "]}

As can be seen in [1], the plugin needs to apply for network permissions WebRequest and WebRequestblocking. These two permissions are related to user login request (POST request). We will explain in detail why these two permissions are required

Popup page

At present, the function of the plug-in is realized in the popup page. The so-called popup page is the page displayed by clicking in the browser plug-in bar

In the case of the Google Translate plugin, the red arrow points to a popup page

There are several pages and scripts for Chrome plugin development


The pages are: popup, optional, background. The display position of different pages on the plug-in is different, and the purpose is also different. At present, you only need to know about the popup page


Scripts include: background.js, content script, etc., and different script declaration cycles are also different

The following shows the main code for the popup page of the check-in helper plug-in

<template> <div class="sign-body"> <div class="sign-image"> <el-avatar size="large" :src="imageUrl"></el-avatar> </div> <div class="sign-text">{{NICKNAME}}</div> <div class="sign-label"> {{NICKNAME}} }</el-tag> </div> <div class="sign-label"> <div class="sign-label"> <div class="sign-label"> <div class="sign-label"> <div class="sign-label" <el-tag size="mini" type="success">{{ continueSignDays }}</el-tag> </div> <div class="sign-btn" v-if="! loading"> <el-button v-if="! Login" type="primary" @click="toLogin"> </el-button> <el-button v-else type="primary" :loading="signing" :disabled="todaySign" @click="toSign">{{ todaySign ? }}</el-button> </div> </div> </template> <script> export default {data() {return {// ImageURL: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', / / nickName nickName: 'null', / / the current ore quantity currentPoint: 0, // ContinuesignDays: 0, // Login: false, // ToDaySign: true, Loading: true, Signing: false,}; },... async mounted() { this.loading = true; Let resp = await getUserInfo(); // verify the validity of cookie this.login =! resp.data.err_no && resp.data.data; if (! this.login) { this.loading = false; return; } // avatar_large; this.imageURL = resp.data.data.avatar_large; this.nickName = resp.data.data.user_name; Resp = await getCurrentPoint(); this.currentPoint = resp.data.data; // await getSignData(); resp = await getSignData(); this.continueSignDays = resp.data.data.cont_count; Resp = await gettoDaySign (); this.todaySign = resp.data.data; this.loading = false; }}; </script>

The main logic is contained in the page mounted stage, which needs to perform a series of operations, including obtaining user information, judging the validity of the cookie, obtaining the user’s current check-in status and reward information, and so on

Ignore a bunch of clumsy \<div\> tags in \<template\>, I just write \<div\> at the front end

Modify the request header

Check-in request /growth_api/v1/check_in is a POST request, and the browser will automatically take the Origin header with the value chrome-extension:// XXXXX. Nuggets will then check the Origin header, Non – nugget Origin will be sent to 403 (Gateway layer checks the source of the request)

At this point, the plug-in needs to modify the Origin field in the request header. However, the Origin field cannot be modified at will

For example, Axios forcing the origin value in the request header does not work, and the plug-in’s console will get an error message. This action is not compliant

At this point, you need to use the permissions of the network request registered in MANIFEST.json

A normally responding request in Chrome will go through the declaration cycle shown in the figure below

If we need to change the request header field, we can change the Origin field by listening for an event before OnBeforeSendHeaders sends the request header. This event listening should run throughout the life of the plug-in, so the code should be written in backdate.js

/ / background. Js file chrome. WebRequest. OnBeforeSendHeaders. AddListener (function (details) {details. RequestHeaders. Push ({ name: 'origin', value: 'https://juejin.cn' }); return { requestHeaders: details.requestHeaders }; }, { urls: ['*://*.juejin.cn/*'] }, ['blocking', 'requestHeaders', 'extraHeaders'] );

The code above you can see, chrome. WebRequest. OnBeforeSendHeaders. AddListener accepts three parameters:

  1. The listener callback method in which changes to the request header should be placed
  2. Filter to control the range of listening URLs, where listening on nuggets related requests is selected
  3. Meta information (OPT_EXTRainfospec), which is simply, [‘blocking’, ‘requestHeaders’, ‘extraHeaders’] The listener metadata contains [‘blocking’, ‘requestHeaders’, ‘extraHeaders’]. These values represent:

    • blockingThis means that the callback method is called synchronously, which means that the callback method of one request is executed before the next callback method is turned on
    • requestHeadersRepresents the parameters of the callback methoddetailsContains the data for the request header
    • extraHeadersThis field is kind of magical becauseoriginThe request header is not a quick fix,chromeIf you really want to change it, you have to fill in this field. That’s rightoriginTo take effect

As you can see in the manifest configuration file, the plug-in applies for permissions other than
webRequestIn addition to that,
webRequestBlockingThis permission is added because it is used in the listening method
blockingWays of Synchronizing

conclusion

So far, the implementation of the plug-in idea is basically finished, in general, the implementation of the plug-in difficulty is not high, interested can try to try to achieve it

, of course, in the form of a plug-in to realize the sign-in function there is no great extent to improve the efficiency of check-in, or in the server of the best ways to check in regularly, so even if not on the website, also can harvest full ore to draw, but it inevitably user login credentials will be exposed to go out, there may be some security risks, It also lost the point of the Nuggets hosting this event

In case someone gets his cookie and runs to delete his article, it is really want to cry without tears

This time the nuggets sign in the activity personal feel or do can

  • The task difficulty is very low, the rules are simple, the activity entrance is obvious
  • Sign in the reward is more, a month sign in, should have thousands of ore, should be able to draw dozens of times

The only bad thing is that I smoked for days without a switch, lol