もしものために，香川県からのアクセスを避ける

# 茶番
「どうも〜、セミコロンつけない派です。お願いします」
「お願いします」
「あ〜、ありがとうございます。今、LGTMを頂きました。こんなんなんぼあってもいいですからね」

「あのな、おかんがな、思い出せない都道府県があるらしいねん」
「ほな、その特徴教えてくれる？」
「おかんが言うにはな、最近ゲームが

**「香川やないか！」**


(ミルクボーイやりたかっただけ。)

# ちまたで噂のネット・ゲーム依存症対策条例
ネットやゲーム依存症を防ぐため、18歳未満の使用時間を制限するというやつです。
今はちょっと変わってコンピュータゲームだけになったみたいです。
これに関する議論は尽きないですが、ここでは置いておきます。

# 仮にサービス側が何とかしろと言われたら...
ネット界隈では、「香川県民ですか？ はい/いいえ」のような香川認証がネタになってます。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">香川県の条例案、よく読んだら我々サービス提供者側（特定電気通信役務提供者）も県民が「ネット・ゲーム依存症」に陥らないように必要な対策を実施しなくちゃいけないらしい。<br>これ、つまりサービス提供時に「あなたは香川県民ですか？」とか聞いてYesと言ったら時間制限つけるみたいな話になるぞ。 <a href="https://t.co/TtOdC9LDqa">pic.twitter.com/TtOdC9LDqa</a></p>&mdash; 佐藤大哲-DaitetsuSato@地学オリンピック中の人 (@SatoDaitetsu) <a href="https://twitter.com/SatoDaitetsu/status/1219487463091003392?ref_src=twsrc%5Etfw">2020年1月21日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


しかし、本当にサービス側が対策しないと行けなくなったらやばい。(絶対ないと思うけど)

そこで、**JavaScriptのGeolocation APIを使って香川からのアクセスを避けてみます。**

ソースコードは[こちら](https://github.com/ni-no/geo-kagawa)にあります。

# 香川ブロックプログラム
## 概略
回避法としては下の図のようになります。

Geolocation APIで緯度経度を取得し、逆ジオコーティングAPIで都道府県を割り出し、香川県だった場合はブロックします。
今回は簡易的に香川県だった場合は、香川県のホームページに飛ばします。
メインの部分は以下の感じです。

```index.js
document.addEventListener('DOMContentLoaded', async () => {
    const message_id = document.getElementById('message')

    // 位置情報取得対応かチェック
    if (navigator.geolocation) {
        // 現在位置をPromiseとして取得  - (1)
        const postion = await getCurrentPositionAsPromise().catch(error => {
            console.log(error)
            message_id.innerHTML = '現在位置を取得できませんでした'
        })
        // 逆ジオコーディングにかける - (2)
        const json = await getPrefecture(postion.coords.latitude, postion.coords.longitude).catch(error => {
            console.log(error)
            message_id.innerHTML = '都道府県を特定できませんでした'
        })
        const prefecuture = json.result.prefecture.pname
        // 香川県なら県のホームページへ
        if (prefecuture === '香川県') {
            location.href = 'https://www.pref.kagawa.lg.jp/'
        } else {
            message_id.innerHTML = 'ようこそ'
        }
    } else {
        message_id.innerHTML = '位置情報取得を許可してください'
    }
})
```

## (1) 位置情報取得
Geolocation APIは、`getCurrenctPosition(successFunc, errorFunc, options)`で現在位置を取得することができます。
ただし、位置情報取得は許可されてる時のみです。
また、この許可をポップアップによって求めることがあるのですが、この応答待ちが必要なので、`Promise`で包みます。

```index.js
async function getCurrentPositionAsPromise() {
    return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(resolve, reject)
    })
}
```


## (2) 都道府県情報照合
Geolocation APIで取得した位置情報を逆ジオコーディングAPIにかけます。
位置情報は`getCurrentPosition()`の返り値を`position`とすると、
緯度: `position.coords.latitude`
経度: `position.coords.longitude`
で受け取れます。

逆ジオコーディングにはfinds.jsの[簡易逆ジオコーディングサービス](https://www.finds.jp/rgeocode/index.html.ja)を使いました。
APIキー取得が不要で使いやすいです。

APIには`fetch`を使って投げます。
ここも取得待ちが必要なので、`fetch`をそのまま`Promise`として返します。

```index.js
const API_URL = 'http://www.finds.jp/ws/rgeocode.php'

async function getPrefecture(latitude, longitude) {
    const response = await fetch(`${API_URL}?json&lat=${latitude}&lon=${longitude}`,{
        mode: 'cors'
    })
    if (response.ok) {
        return response.json()
    } else {
        throw new Error(`${response.status}: ${response.statusText}`)
    }
}
```

## 注意
このプログラムを動かす時、Web APIを使ってるためCORS要求がうまくいかず、失敗する場合があります。
Chromeだと、拡張機能として[Moesif Origin&CORS Changer](https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc?hl=ja&)を入れるとなんとかできる場合があります。

あと位置情報取得にもAPIの応答待ちも少し時間がかかるため、待つ必要があります。

# 位置偽造実験
香川県にいないので、実際に香川からアクセスした場合の挙動がわかりません。
なので、Chromeの機能を使って位置情報を香川県に変更します。
香川県の高松市の緯度経度を使用します。

![香川デモ](https://gyazo.com/46c846bfc892c1c08ea220ddd402104d/raw)

結果、無事香川県のホームページに飛ばされました。
位置情報変えられるのであれば、香川県からのアクセスを別のところからにもできますが(笑)。

# まとめ
今回はGeolocation APIを使って香川県からアクセスされた場合、ブロックしてみました。
というか、香川県のゲーム規制をネタにGeolocation APIで遊んでみました。

実際、ゲーム規制どうなるんですかね。
記事執筆段階では、親に努力義務が課せられるという状態ですが、果たして。

(追記)
*1: @alt さんがタグを修正して下さいました。
*2: @proudust さんが`async/await`で書き換えて下さいました。
*3: @yukiyukki さんがエラー修正してくださいました。
ありがとうございます。

(追記2)
ねとらぼさんでこの記事を取り上げて頂きました。
よろしければ、ご一読ください。
[「香川県からのアクセスをブロックするプログラム」が話題に　ネット・ゲーム依存症対策条例への問題提起として](https://nlab.itmedia.co.jp/nl/articles/2001/27/news096.html)

(追記3)
いいねをLGTMに変更しました。

# 参考文献
[Geolocation APIをPromiseでラップして扱う（TypeScript）](https://qiita.com/makotoyc/items/aee473b341cd3a7bd31f)
[簡易逆ジオコーディングサービス](https://www.finds.jp/rgeocode/index.html.ja)
[Moesif Origin&CORS Changer](https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc?hl=ja&)
[ローカルのHTMLファイルでfetchを試す & CORSとその回避策](https://qiita.com/k-shimoji/items/acbbbb49530fb97f5893)
[【Google Chrome】位置情報を変更してPCの現在地を自由自在に設定](https://www.atmarkit.co.jp/ait/articles/1907/31/news020.html)
[香川県の市町村ごとの緯度経度一覧](http://tide.jpn.org/ll/?l=%E9%A6%99%E5%B7%9D%E7%9C%8C)