Wantedlyとぼくと自動化

この記事は [Altplus Advent Calendar 2017](https://qiita.com/advent-calendar/2017/altplus)  の7日目のエントリです。

こんにちは、自動化大好き cimadai です。またお会いしましたね。

## 概要

今日は私の会社で(もしかしたら皆さんの会社でも)よくある、ちょっとした手間を一つ減らして効率化していこう、という内容を書きます。

## どのような問題なのか

私の会社では、Wantedlyを活用していて、特にブログに注力しています。
Wantedlyのブログは会社の採用に繋がるということで有用なツールの一つとして多くの企業に使われていると思います。

多くの企業に使われているということはそれだけ多数の記事があるため、効果的に認知を高めるにはその中でどうにか目立たせないといけません。

幸いWantedlyにははてなのホッテントリのような、短期間に「いいね」が多数集まった記事を「急上昇」として取り上げる機能があります。

そこで、記事が書かれた後は社員に対して「いいね」をするよう「お願い」があります。[^1]

[^1]: もちろん重要性はわかってますよ！ぼくは真面目な社員ですからね！

もちろん、いい方に来て頂きたいので当然「いいね」するわけなのですが、記事を開き下までスクロールし、その間に目にとまる文章があれば読んでしまったりして割と時間泥棒だったりするのです。

ということで、どうにか記事を読むことなくできるだけ手間なく「いいね」できる方法はないかと思い、この記事を書くに至りました。

## なにをしたのか

AutedlyというChrome Extensionを作り、記事を開いたら自動的に「いいね」するようにしました。

https://github.com/cimadai/autedly

## 解説

Chrome Extensionを作る方法はいろいろあるので別記事に譲りますが、ここではどんなことをしたのかを解説します。

```json:manifest.json
{
    "manifest_version": 2,
    "name": "Autedly",
    "version": "0.2.0.0",
    "description": "Auto like when you open wantedly page.",
    "background": {
        "scripts": ["background.js"],
        "persistent": true
    },
    "content_scripts": [
        {
            "matches": [
                "*://www.wantedly.com/companies/altplus/*"
            ],
            "css": ["jquery.toast.min.css"],
            "js": ["jquery-2.1.4.min.js", "jquery.toast.min.js", "content.js" ],
            "run_at": "document_start"
        }
    ],
    "web_accessible_resources": [
        "background.js"
    ],
    "permissions": ["*://*/*"]
}
```

↑はExtensionの定義をしています。
簡単なDOM操作のためにjQueryを使い、ユーザーに対するフィードバックにjQuery Toastというライブラリを使いました。

実際の処理は以下になります。
Wantedlyではブログがたくさん並んでいる企業ページと、各記事個別のページがあるので、それぞれで処理を分けています。

コード中のコメントにも書いてあるのですが、Wantedlyの記事読み込みタイミングや「いいね」状態の反映のタイミングが非同期でなかなか掴めなかったので、setTimeoutを利用しています。
ここはかなりイケてない部分なので気が向いたらどうにか直したいところです。

その後`chrome.runtime.sendMessage`でbackground taskに対して処理を依頼しています。

```javascript:content.js
function likeIfNeeded($target) {
    var url = location.href;
    var re = /.*\/companies\/altplus\/post_articles\/(\d+)/i;
    var found = url.match(re);
    if (found) {
        var articleId = found[1];
        var likeUrl = 'https://www.wantedly.com/api/internal/posts/' + articleId + '/like';

        var $likeButton = $target.find(".post-like-button");
        if (!$likeButton.is(".liked")) {
            var csrfToken = $("meta[name=csrf-token]").attr("content");
            chrome.runtime.sendMessage({command: "like", csrfToken: csrfToken, likeUrl: likeUrl});
            // TODO: 単純にlikedを付けるだけだとその後もう一度ボタンを押した時に動作がおかしい。
            $likeButton.addClass("liked");
            $.toast({
                text: "「いいね!」しました。",
                position: "top-right"
            });
        } else {
            console.log("Already liked.");
        }
    }
}

$(function () {
    // 企業ページから各記事を開いた時
    $(document).on("click", ".stream-post", function() {
        var $self = $(this);
        // setTimeoutはイケてない
        setTimeout(function () { likeIfNeeded($self); }, 1000);
    });
    // 記事を直接開いた時
    // setTimeoutはイケてない
    setTimeout(function () { likeIfNeeded($("body")); }, 1000);
});
```

background taskでは、content.jsから受け取った「いいね」をつけるURLに対してXHRでPOSTを行い、「いいね」しています。
すでに「いいね」済みの記事に対して実行すると442が返ってくるのですが、基本的にcontent.js側で判定しておりめったにこないはずですので、Wantedlyサーバーに負荷がかかりすぎるということはないでしょう。 [^2]

[^2]: なので大目に見て頂けないですかね。。



こんなことをしなくともcontent.js側でjQueryを使っているんだから$.ajaxでPOSTすればいいじゃないかとも思ったのですがHTTP OnlyのCookieが必要なのでこうなりました。

```javascript:background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.command == "like") {
        xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            switch ( xhr.readyState ) {
                case 4: // データ受信完了.
                    if( xhr.status == 200 || xhr.status == 422 ) {
                        console.log('LIKED!');
                    }
            }
        };

        xhr.open("POST", request.likeUrl, true);
        xhr.setRequestHeader("x-csrf-token" , request.csrfToken);
        xhr.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded; charset=UTF-8");
        xhr.setRequestHeader("x-requested-with" , "XMLHttpRequest");
        xhr.send("location=post_action_bar");
    }
    return true;
});
```

## 動作

![autedly.gif](https://qiita-image-store.s3.amazonaws.com/0/104844/f27b5f57-513c-c585-0538-dcd2b42e21dc.gif)

「いいね」がない状態でページを読み込むと自動で「いいね」が付けられる、という動作風景です。
右上にヒョコっとでるのがjQuery Toastです。
[4日目の記事](https://qiita.com/cimadai/items/a7f041aa89805ea7b52f)にも書いたのですが、最近はあまりjQueryを多用しなくなったので久しぶりのjQueryという感じでしたがこういうちょっと書捨て、みたいな感じだととても楽ですね！

## 社内限定公開

さて、このような感じで作ったExtensionですが、気軽に使えないと困ってしまうので社内限定で公開してみました。

オルトプラスの方は「[こちら](https://chrome.google.com/webstore/detail/autedly/mecnlijcbigiipcibkfchkjehommbflk?hl=ja)」からインストールできます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104844/8f6546f5-6999-fa99-9406-0d6cb0a50696.png)
※社内限定公開なので検索しても出てこないです。

社内限定であれば無料ででき、かなり気軽に配付できることができたので楽ちんでした。

公開方法は以下の記事がとても参考になりました。
http://blog.serverworks.co.jp/tech/2016/12/05/buri-publication/


## まとめ

ちょっとの時間のロスが通年でみれば大きなロスになることってありますよね。
こうしたExtensionを駆使することでWantedlyに負荷をかけることもなく、会社は「いいね」が集まって嬉しい、自分は時間が節約できて嬉しいといういいこと尽くめなプチハックでした。


それではまた別の日に！