chrome插件開發(fā) | 掘金簽到助手

前言

碰巧掘金新上簽到活動(dòng)史侣,碰巧喝了咖啡睡不著惊橱,碰巧雙休不用上班回季,所以寫了個(gè)插件,方便工作日簽到(順道練練手)

先來看看成品

image-20210717064346915
image-20210717103555717
image-20210717064223932

總的來看,插件需要實(shí)現(xiàn)以下幾個(gè)目標(biāo):

  1. 檢測(cè)當(dāng)前用戶登錄態(tài)
  2. 判斷用戶今天是否已簽到
  3. 發(fā)送簽到請(qǐng)求
  4. 展示信息(用戶信息涵但,獎(jiǎng)勵(lì)信息)
搞事情、搞事情澈侠、整天就知道搞事情B窠А(熊貓人)

請(qǐng)求分析

用戶登錄憑證

通過登錄請(qǐng)求[POST] /passport/web/user/login可以看到棘催,請(qǐng)求響應(yīng)設(shè)置的Cookie中有好幾個(gè)鍵值對(duì),選擇一個(gè)普通的請(qǐng)求在postman上分析呼猪,可以看到掘金通過Cookie中的sessionid作為用戶登錄憑證

image-20210717143831542

簽到相關(guān)的接口

在簽到功能的請(qǐng)求中砸琅,跟這次要實(shí)現(xiàn)功能相關(guān)的接口有4個(gè)谚赎,分別是:

  1. 獲取簽到天數(shù)的匯總信息 [GET]/growth_api/v1/get_counts
  2. 獲取當(dāng)前的礦石數(shù)量 [GET]/growth_api/v1/get_cur_point
  3. 判斷用戶今天是否已簽到 [GET]/growth_api/v1/get_today_status
  4. 用戶簽到 [POST]/growth_api/v1/check_in

這里大致分析一下功能對(duì)應(yīng)的請(qǐng)求即可壶唤,具體傳參以及返回值的含義可以通過瀏覽器控制臺(tái)查看(F12

流程圖

下面通過幾個(gè)場(chǎng)景的時(shí)序圖來闡述清楚插件的工作流程

未登錄場(chǎng)景

image.png

未簽到場(chǎng)景

image.png

已簽到場(chǎng)景

image.png

搭建chrome插件開發(fā)工程

通過vue-web-extension實(shí)現(xiàn)快速搭建chrome插件開發(fā)工程(Vue)

首先確保這兩個(gè)已經(jīng)安裝了

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

然后通過vue-web-extension創(chuàng)建工程琳省,我選擇vue-web-extension的版本是v1

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

按需選擇自己需要的功能(axios必選)

image-20210717152313855

安裝element ui(按需加載)

cd juejin-auto-sign && vue add element
image-20210717174346824

由于element ui的配置會(huì)寫在package.json文件中babel部分酵幕,跟工程原有的.babelrc配置文件重疊了韭邓,需要將package.json中關(guān)于babel部分的配置合并到.babelrc文件中

合并前

# .babelrc配置文件
{
  "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.json配置文件
{
  .......
  "babel": {
    "plugins": [
      [
        "component",
        {
          "libraryName": "element-ui",
          "styleLibraryName": "theme-chalk"
        }
      ]
    ]
  }
}

合并后,將package.jsonbabel部分刪除荧缘,.babelrc配置文件如下

在工程根目錄下執(zhí)行yarn build,能夠正常打包

yarn build

![image-20210717175823529](/Users/luoxiongjian/Library/Application Support/typora-user-images/image-20210717175823529.png)

至此绸罗,工程已經(jīng)基本搭建完成了珊蟀!可以正式投入開發(fā)

工程常用命令:

  • yarn build 構(gòu)建插件育灸,輸出到dist目錄下
  • yarn build-zip 按照插件名+版本號(hào)的形式磅崭,構(gòu)建插件壓縮包
  • yarn watch 構(gòu)建插件,輸出到dist目錄下杭煎,如果發(fā)生改動(dòng)羡铲,會(huì)即時(shí)刷新

關(guān)鍵代碼

manifest.json配置文件

manifest.json文件中記載著插件的原信息扑媚,其中包括插件的基礎(chǔ)信息(插件名稱费坊,版本號(hào)附井,ICON等)永毅,以及插件涉及頁面(popup,options意蛀,background等)县钥,還有插件需要向chrome申請(qǐng)的權(quán)限

{
  // 插件名稱
  "name": "juejin-auto-sign",
  // 插件描述
  "description": "掘金簽到助手",
  // 插件版本號(hào)
  "version": "1.0.0",
  "manifest_version": 2,
  "icons": {
    "48": "icons/icon.png",
    "128": "icons/icon.png"
  },
  ......
  // [1] 申請(qǐng)掘金的cookie、網(wǎng)絡(luò)請(qǐng)求的權(quán)限
  "permissions": [
    "cookies",
    "*://*.juejin.cn/",
    "webRequest",
    "webRequestBlocking"
  ]
}

[1]處可以看到,插件需要申請(qǐng)網(wǎng)絡(luò)權(quán)限 webRequestwebRequestBlocking细移,這兩個(gè)權(quán)限是跟用戶簽到請(qǐng)求有關(guān)系的(POST請(qǐng)求),后面會(huì)詳細(xì)介紹為什么需要這兩個(gè)權(quán)限

popup頁面

目前插件的功能實(shí)現(xiàn)都是在popup頁面碗殷,所謂popup頁面就是在瀏覽器插件欄處點(diǎn)擊展示的頁面

image-20210717224513506

Google翻譯插件來看精绎,紅色箭頭指向的頁面就是popup頁面

chrome插件開發(fā)有分好幾種頁面以及腳本
頁面有:popup,optional锌妻,background代乃,插件上不同頁面的展示位置是不同,用途也不同仿粹,目前只需要了解到popup頁面即可
腳本有:background.js搁吓,content script等原茅,不同的腳本聲明周期也是不同的

下面展示簽到助手插件popup頁面的主要代碼

<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">
      當(dāng)前礦石數(shù)量:<el-tag size="mini" type="success">{{ currentPoint }}</el-tag>
    </div>
    <div class="sign-label">
      連續(xù)簽到天數(shù):<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: 'null',
      // 當(dāng)前礦石數(shù)量
      currentPoint: 0,
      // 連續(xù)簽到天數(shù)
      continueSignDays: 0,
      // 是否登錄
      login: false,
      // 今日是否已簽到
      todaySign: true,
      loading: true,
      signing: false,
    };
  },
  .......
  async mounted() {
    this.loading = true;
    // 獲取用戶信息
    let resp = await getUserInfo();
    // 判斷cookie有效性
    this.login = !resp.data.err_no && resp.data.data;
    if (!this.login) {
      this.loading = false;
      return;
    }
    // 頭像,昵稱
    this.imageUrl = resp.data.data.avatar_large;
    this.nickName = resp.data.data.user_name;
    // 礦石數(shù)量
    resp = await getCurrentPoint();
    this.currentPoint = resp.data.data;
    // 連續(xù)簽到天數(shù)
    resp = await getSignData();
    this.continueSignDays = resp.data.data.cont_count;
    // 當(dāng)前簽到狀況
    resp = await getTodaySign();
    this.todaySign = resp.data.data;
    this.loading = false;
  },
};
</script>

主要的邏輯都包含在頁面mounted階段堕仔,該階段需要執(zhí)行一系列操作仿吞,包括獲取用戶信息你虹,判斷cookie有效性董饰,獲取用戶當(dāng)前簽到狀態(tài)以及獎(jiǎng)勵(lì)信息等等

忽略<template>中的一堆笨拙的<div>標(biāo)簽也祠,前端我只會(huì)寫<div>

img

修改請(qǐng)求頭

簽到請(qǐng)求/growth_api/v1/check_in是一個(gè)POST請(qǐng)求昔字,瀏覽器會(huì)自動(dòng)帶上origin請(qǐng)求頭所坯,其值為chrome-extension://xxxxx无蜂,此時(shí)掘金會(huì)校驗(yàn)請(qǐng)求頭中的origin酣倾,非掘金的origin會(huì)直接報(bào)403(應(yīng)該是網(wǎng)關(guān)層做了請(qǐng)求來源的校驗(yàn))

image-20210717230835866

此時(shí)插件就需要修改請(qǐng)求頭中的origin字段,然而origin字段并不能隨意修改

比方說axios強(qiáng)制指定請(qǐng)求頭中origin的值是不生效的抬伺,并且插件的控制臺(tái)會(huì)有對(duì)應(yīng)的錯(cuò)誤提示,該操作不符合規(guī)范

此時(shí)就需要使用到manifest.json中注冊(cè)的網(wǎng)絡(luò)請(qǐng)求的權(quán)限

一個(gè)正常響應(yīng)的請(qǐng)求在chrome中會(huì)經(jīng)歷如下圖所示的聲明周期

Life cycle of a web request from the perspective of the webrequest API

如果我們需要修改請(qǐng)求頭字段的話钥屈,則可以在onBeforeSendHeaders發(fā)送請(qǐng)求頭之前通過事件監(jiān)聽的方式修改origin字段,同時(shí)锯玛,該事件監(jiān)聽?wèi)?yīng)該是貫穿整個(gè)插件的生命周期的肯腕,所以代碼應(yīng)該寫在background.js

// background.js文件
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']
);

上述代碼中可以看到,chrome.webRequest.onBeforeSendHeaders.addListener接受三個(gè)參數(shù):

  1. 監(jiān)聽器回調(diào)方法妖泄,修改請(qǐng)求頭的操作應(yīng)該放在這個(gè)方法中
  2. 過濾器荷并,用于控制監(jiān)聽的URL范圍幻工,這里選擇監(jiān)聽掘金相關(guān)的請(qǐng)求
  3. 元信息(opt_extraInfoSpec)嗅骄,簡(jiǎn)單來說就是,這個(gè)參數(shù)填寫的值代表監(jiān)聽器的回調(diào)方法的執(zhí)行方式以及回調(diào)時(shí)傳入的數(shù)據(jù)
    本次監(jiān)聽器的元數(shù)據(jù)中包含['blocking', 'requestHeaders', 'extraHeaders']炊林,這三個(gè)值分別表示:
    • blocking 表示回調(diào)方法是同步調(diào)用的饵逐,就是說一個(gè)請(qǐng)求的回調(diào)方法執(zhí)行完之后才會(huì)輪到下一個(gè)請(qǐng)求的回調(diào)方法
    • requestHeaders 表示回調(diào)方法的參數(shù)details 中包含請(qǐng)求頭的數(shù)據(jù)
    • extraHeaders 這個(gè)字段比較神奇题画,由于origin請(qǐng)求頭這玩意不是說改就改的课梳,chrome也不推薦步势,如果真的要修改的話灾搏,就必須要填寫這個(gè)字段,這樣對(duì)origin的修改才會(huì)生效

在manifest配置文件中可以看到立润,插件申請(qǐng)的權(quán)限除了webRequest之外,還有webRequestBlocking媳板,添加這個(gè)權(quán)限是因?yàn)楸O(jiān)聽方法中使用blocking同步的方式

總結(jié)

至此桑腮,這個(gè)插件的實(shí)現(xiàn)思路基本介紹完了,總的來看蛉幸,插件的實(shí)現(xiàn)難度不高破讨,有興趣的可以自己試著嘗試實(shí)現(xiàn)一下

當(dāng)然,以插件的形式來實(shí)現(xiàn)簽到的功能其實(shí)并沒有極大幅度地提高簽到的效率奕纫,最好的方式肯定還是在服務(wù)器中定時(shí)簽到提陶,這樣即使不上掘金網(wǎng)站,也能收獲滿滿的礦石用以抽獎(jiǎng)匹层,但是這樣不可避免地將用戶登錄憑證暴露出去隙笆,可能存在一些安全風(fēng)險(xiǎn)锌蓄,同時(shí)也喪失了掘金舉辦這個(gè)活動(dòng)的意義

萬一被別人拿到自己的cookie跑去刪除自己的文章,那真的是欲哭無淚

這次掘金的簽到活動(dòng)個(gè)人覺得還是辦的可以的

  • 任務(wù)難度很低撑柔,規(guī)則簡(jiǎn)單瘸爽,活動(dòng)入口明顯

  • 簽到獎(jiǎng)勵(lì)比較多,一個(gè)月簽到下來铅忿,應(yīng)該都有好幾千礦石剪决,應(yīng)該能抽獎(jiǎng)好幾十次

唯一不好的地方就是我抽了好幾天都沒抽到switch,哈哈哈哈

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末檀训,一起剝皮案震驚了整個(gè)濱河市柑潦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峻凫,老刑警劉巖渗鬼,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蔚晨,居然都是意外死亡乍钻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門铭腕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來银择,“玉大人,你說我怎么就攤上這事累舷『瓶迹” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵被盈,是天一觀的道長(zhǎng)析孽。 經(jīng)常有香客問我,道長(zhǎng)只怎,這世上最難降的妖魔是什么袜瞬? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮身堡,結(jié)果婚禮上邓尤,老公的妹妹穿的比我還像新娘。我一直安慰自己贴谎,他們只是感情好汞扎,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著擅这,像睡著了一般澈魄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仲翎,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天痹扇,我揣著相機(jī)與錄音铛漓,去河邊找鬼。 笑死帘营,一個(gè)胖子當(dāng)著我的面吹牛票渠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芬迄,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼问顷,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了禀梳?” 一聲冷哼從身側(cè)響起杜窄,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎算途,沒想到半個(gè)月后塞耕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘴瓤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年扫外,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廓脆。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡筛谚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出停忿,到底是詐尸還是另有隱情驾讲,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布席赂,位于F島的核電站吮铭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏颅停。R本人自食惡果不足惜谓晌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望癞揉。 院中可真熱鬧扎谎,春花似錦、人聲如沸烧董。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逊移。三九已至,卻和暖如春龙填,著一層夾襖步出監(jiān)牢的瞬間胳泉,已是汗流浹背拐叉。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扇商,地道東北人凤瘦。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像案铺,于是被迫代替她去往敵國(guó)和親蔬芥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容