ジンジャー研究室

長めのつぶやき。難しいことは書きません。

時間帯によって特定サイトの閲覧を禁止する for macOS

f:id:jinjor:20181024032631p:plain

TL; DR

cron で /etc/hosts を書き換える。

* 6-22   * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
* 0-5,23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

以下、この方法に到るまでの経緯。

動機

SNS が時間泥棒だからアクセス出来ないようにしたい、というのは昔から言われているのだが、特にまずいのは Slack だと思っている。Twitter は流しておけばいいんだけど Slack はチャットなので会話が発生する。見るだけなら問題ないじゃんと思いつつ、見るとつい返信したくなる。そういう人が2人以上いると無限ループになり深夜に突入。で、他の人が朝に見たらなんか会話が進んでいる状態。よくない。

なんとか Slack を使うのを止める方法はないのか?

対策を考える

で、色々と検討したのをメモ。前提条件としては macOS

bot に怒ってもらう

Slack だから、深夜時間帯に使ったら個人宛に怒ってくれる bot とかがいれば、書き込みを抑止できるのではないか。

結論としては、睡眠モードに通知を出さない機能はあるが bot は無さそう 。 作ることは出来そうだが面倒。(調べてないけど個人単位で bot の導入できるんだっけ?全員にルールを適用されるのは嫌だ。それやったら朝に強制ラジオ体操やるのと変わらない。)

ペアレンタルコントロール

子供が深夜などにアプリを使用するを制限する機能のようだ。なるほど、大人の皮を被った子供は潔く子供扱いされねばなるまい。 ただし、管理者は子供になれないので子供用のアカウントを作らないといけない。大人のアカウントで設定して子供の方にログイン…うーん面倒。

SelfControl

SelfControl という自制心の効かない大人のためのアプリがある。ブラックリストに入れたサイトに一定時間アクセス出来なくなるらしいのだが、そのボタンは自分で押さなければならないようだ。いや、そんなに意志は強くない。

Airplane Mode

Airplane Mode という同じく自制心の効かない大人のためのアプリがある。てか、 Evan さん何やってんすか。デスクトップにアイコンを置いて、叩くと /etc/hosts を書き換える Python スクリプトが走る。ただこれも手動で叩かないといけないのがな〜という気分。

cron で /etc/hosts を書き換える

ズバリというものがなかったので、/etc/hosts を書き換えるというアイデアだけ拝借する。 ブロックしたいサイトに #block のような印をつけておいて、指定した時間になったらその行を sed でコメントイン・アウトすればいい。

0 06 * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
0 23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

正規表現には自信がないが、以下がコメントアウトされるはず。

...

0.0.0.0 xxx.slack.com #block
::      xxx.slack.com #block

これで OK 、のはずだった。

DNS の反映が遅い

しかし DNS の反映が遅い。

ということでググると、 DNS キャッシュをクリアする方法が OS 毎に出てくる。で、色々試して最後に残ったのが ChromeDNS キャッシュで、chrome://net-internals/ にアクセスしてボタンを押すしか方法がなく、コマンドで消せない。 「じゃあ puppeteer でボタンを押そうか」という事で調べたら、すでに同じことを試みた人が出来ないと言っていて、さらにたどると chromium のフォーラムで「headless モードで chrome://net-internals/ にはアクセス出来ないよ」という回答が付いていたので、意図的っぽい。

というわけで DNS の反映は諦めた。まあ 30 分くらい早めにすれば多少のずれは良しとしよう。

スリープ中に cron が走らない

23時にセットしたから今頃見えなくなっているはずで、と思って Slack にアクセスしたら超見え見えじゃん〜。cron の設定は正しいっぽく見えるので、やはり mac がスリープ状態だと無理なのか。

調べると mac を不眠に陥れようという酷い方法が提案されていて、心が痛んだのでやめておいた。 さらに調べると、sleepwatcher というツールを使うと起動した時にスクリプトを流すことができるらしい。が、情報少ないし信頼性もわからなかったのでやめておいた。

毎分実行する

そして、最終的に「起きてる間に毎分走らせりゃいいか」ということになった。

* 6-22   * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
* 0-5,23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

ちゃんと動いていそう!

まとめ

もっと良い方法があれば教えてください。

依存の多い npm のパッケージをあぶり出す

直接依存しているパッケージが間接的に依存しているパッケージ数を知りたい。 npm ls でそういうオプションがありそうだけどないような?

仕方がないのでスクリプト書いた。

const cp = require("child_process");
cp.exec("npm ls", (e, out, err) => {
  const results = [];
  out.split("\n").forEach(line => {
    if (line.charAt(0) === "├" || line.charAt(0) === "└") {
      const splitted = line.split("@");
      splitted.pop();
      const name = splitted
        .join("@")
        .split(" ")
        .pop();
      const p = [0, name];
      results.unshift(p);
    } else if (results.length) {
      results[0][0]++;
    }
  });
  results
    .sort((a, b) => b[0] - a[0])
    .forEach(([count, name]) => console.log(`${count}\t${name}`));
});
15   json-schema-deref-sync
12  better-ajv-errors
11  ts-node
6   chalk
5   ajv
4   axios
2   xregexp
1   @types/chalk
0   typescript
0   openapi3-ts
0   @types/xregexp
0   @types/node

本当はここから気になった箇所を GUI で掘っていけると便利。

画像の差分を見つけるツールを作った

f:id:jinjor:20180907111251p:plain

作ったのは大分前なんだけど、想定するユースケースで実際に使えそうだと確認できたので。

作ったもの

github.com

動機

  • デザイナーから新しいカンプをもらった時にどこが変わったのか分かりにくかった
  • 作った機能をレビューしらもらう時にスクショのどこが変わったのか分かりにくかった

微妙なところ

完成度はぶっちゃけ高くないというか、自分の用途のために使う MVP 的なやつなので最低限しかできない。 具体的には、

  • 遅い
  • PNG のみ
  • 上下にずれると全部変わったことになる

遅いのはアルゴリズムが愚直なのもあるけど、せめてファイル変わってない時は checksum 取るくらいの対策はしたい。 最後のは改善したかったけど蓋を開けたらそういう修正はほとんどなかったというか、あってもあまり問題にならなかったので放置。

ところで画像差分検知と言えばもっと有名なのがあるので、ちゃんとしたやつを使いたい人はこっちを使ってね!

github.com

こっちも試したけどリグレッション検知が目的っぽいので、ちょっと UI が合わないという些細な点が気になってしまった。

2つの順序キーの間のキーをいい感じに生成するライブラリを作った

RDB で ORDER BY するためのカラムを持つ時に、並び替えや挿入がうまく出来なくて困った。

f:id:jinjor:20180905182715p:plain

例えば、このテーブルで B と C の間に E を差し込みたい時に、

f:id:jinjor:20180905181617p:plain

こうなってくれると嬉しい。

作ったもの

🎉

github.com

TypeScript 用に書き直してくれてもいいのよ?

仕組み

  • キーは 0-9A-Za-z の 62 種類の文字が使える、ただし、最後の文字が 0 であってはいけない
  • 最初のキーは 1
  • 次のキーは「既存のキーの次」か「既存のキーの前」か「既存の2つのキーの間」のいずれかを指定して生成する
  • キーの左の桁を優先的にインクリメントしようとするが、無理な場合は桁を増やしてインクリメントする
  • 例:
    • between "1" "3" == "2"
    • between "1" "2" == "11"
    • between "1" "11" == "101"
    • after "1" == "2"
    • after "z" == "z1"
    • その他

技術的な話

Fuzzer を使って 10 万テストケースを自動生成して回しています。

今回は 0, 1, z などの境界値付近を重点的に攻めるために確率を操作しています

参考リンク:

Elm 0.19 の主な変更点

祝 Elm 0.19 リリース!

https://elm-lang.org/blog/small-assets-without-the-headache

1年半ウォッチしていたので覚えている範囲で書いてみる。

追記

↓ここに全部書いてあるじゃん。というか上の記事からリンクされてたし、この記事いらないじゃん。

github.com

コンパイルが速くなった

タプルで大量にパターンマッチした時に遅くなる件も改善。

--optimize でサイズの最適化

出力される JS のサイズが小さくなる。 関数単位のデッドコード除去が可能(Google Closure Library の advanced compile 相当) Debug モジュールを使用していると --optimize できないので注意。

単一コンストラクタでメモリを消費しなくなった

これは --optimize をつけた時だったかな、覚えてない。 type T = T Foo みたいにした時に T で包むのを省略する。

シングルバイナリになった

Elm Platform はもうない。 elm-make の代わりに elm make と打つ。

コマンドラインの刷新

  • --warn が消えた
  • elm init で最低限のプロジェクトを生成できるようになった
  • elm install をプロジェクトを初期化せずに elm make で全部やるようになった

elm-package.json が elm.json になった

アプリケーション用とライブラリ用で書き方が変わる。 アプリケーションの場合はバージョンが固定されて lock ファイルになる。 test-dependencies という項目ができたのでテスト用にもう一つ JSON を用意する必要がなくなった。 初期状態でインストールされるのは elm/coreelm/json の2つで、 HTML などは手動でインストールする必要がある。

elm-stuff の役割が変わった

パッケージやそのビルド生成物は ~/.elm にキャッシュされることになった。 CI とか Docker の設定で注意が必要かもしれない。

ユーザー定義の演算子が禁止された

もう作れない。

いくつかの演算子が消えた

  • ! はもうない
  • %modByremainderBy になった

トリッキーな関数が消えた

  • flip
  • curry
  • uncurry

人類には早かった。

シャドーイングが禁止された

同スコープに定義されている関数と同名のローカル変数を作ることができない。

公式リポジトリが elm-lang から elm になった。

ついでにバージョンが 1.0.0 にリセット。

Browser が登場

Html.program 系の関数がここに集約された。 Navigation, Mouse, Keyboard, Dom もここに統合された。 Navigation 相当の機能は fullscreen の時のみ使用可能。

Html.Events のデコーダーが柔軟になった

「デコードした時に特定の条件だった時に preventDefault しない」のようなことが可能になった。

DOM のイベントを同期的に実行するようになった

ブラウザのセキュリティ機能で、ユーザーインタラクションの直後じゃないとコピペなどが正しくハンドリングされない問題を解消した。

Debug モジュールの刷新

  • Debug.crash が Debug.todo になった。
  • toString が Debug モジュールに入った。

String.fromInt, String.fromFloat

toString は使わない。 型を変えた時に人知れず表示がバグっていたので嬉しい。

(,) が消えた

今は Tuple.pair

Html.Lazy が 8 引数まで拡張された

今まで3だった。

Array, Dict, Set の実装が新しくなった

速くなった。 Array は今までバグがあった。

Random の実装が新しくなった

PCG アルゴリズムを使うようになった。

Time の実装が新しくなった

より実用的になって elm/time として生まれ変わった。

Color が core から消えた

旧石器時代からあったやつ。

Regex が core から消えた

Parser を使って欲しそう。

elm-tools/parser が elm/parser に昇格

API も色々刷新された。

再帰的な関数のバグが直った

どれのことだったか忘れた。

リテラルで巨大なリストを作れないバグが直った

[1,2,3, ... 5800 ] みたいなやつ。

Module.Record.property を正しくパースするようになった

定数を使う時に苦労していたので地味に嬉しい。

エラーメッセージがさらに改善された

どれのことだったか忘れた。

Native -> Kernel

Native モジュールが Kernel モジュールに名称変更。 JS を書くのが許されているのは elm と elm-exploration の2つだけ。

ドキュメントが充実した

公式サイト・ガイド、コアライブラリの解説が増えた。

Union Type という表記が消えた

名称が紛らわしかった。今は Custom Type と書いてある。

個人的によく使う npm ライブラリを紹介してみる

偏ってます。

もっと有名なのは沢山あるけど、自分が普段よく使うのじゃないと紹介できないので。

argv

引数をパースするやつ。

chalk

色をつけるやつ。

dotenv

環境変数をファイルから読むやつ。

fs-extra

fs に欲しいけどないやつ。

watch

ファイルを監視してコマンドを実行するやつ。

nodemon

ファイルを監視してサーバーを再起動するやつ。

mocha

テスト。

prettier

フォーマッター。

puppeteer

ヘッドレス Chrome

express

サーバー。

passport

OAuth 。

typescript

TypeScript 。

elm

Elm 。

npm

Node.js 用のパッケージマネージャー。

puppeteer + express + mocha で快適 TDD している話(続編)

前回の記事の続き。

jinjor-labo.hatenablog.com

会社で開発中でオープンソース化していないテストツールがまたいくらか便利になったので進捗報告してみる。 ツールの概要は上の記事で説明しているけど、一言で言うと「mocha から puppeteer 叩いて express に届いたリクエストにアサーションをかける」ようなテストが楽に書ける。

前との差分

以下、前回より便利になったポイントを自慢していく。

APIカバレッジが取れるようになった

API が一度でも叩かれたかどうかを調べて網羅率を見る。 テストが一通り終わった後、こういうのが出る。

[ OK ] GET /foo/foo
[ OK ] PUT /foo/foo
[ OK ] GET /bar/:barId/bar
[ NG ] POST /bar/:barId/bar
covered 3/4

ページのカバレッジが取れるようになった

こちらはテストケースで訪問したページの網羅率を見る。 全体でどんなURLがあるかはサイト内をクローリングして調べる。

[ OK ] /#/
[ OK ] /#/config
[ OK ] /#/articles
[ NG ] /#/articles/(number)
covered 3/4

UI のカバレッジが取れるようになった

こちらはページ内の UI をどれだけ網羅したか。

/#/articles/(number)
[ OK ] #article-tilte-input
[ OK ] #article-body-input
[ OK ] #submit-button
[ NG ] #submenu-toggle
covered 3/4

テストケースに併せてモックデータを差し替え可能になった

今まで一枚岩のデータしか無かったのが、柔軟に適切なデータをサーバーから返してもらえるようになった。 これでログイン中のユーザーの権限を変えてみたり、ページネーションのテストために大量のデータを放り込める。

おかしな HTML 要素を警告するようになった

<a> なのに href が無いぞーだったり a11y 的によろしくないものを警告する。 まあこの辺は普通の E2E のツールにありそうな機能ではある。

記法が進化した

前回ちょっとダサかったアサーションpower-assert でいい感じになった。

    it("should send fields correctly", async () => {
      await inputText("#signup-email-address", "a@b.c");
      await inputText("#signup-password", "Passw0rd");
      await inputText("#signup-user-name", "A B");
      await $.click("#signup-submit");
      at("POST /auth/signup", results => {
        assert(results.length === 1);
        assert(results[0].body.email_address === "a@b.c");
        assert(results[0].body.password === "Passw0rd");
        assert(results[0].body.user_name === "A B");
      });
    });

TypeScript 化した

時代は TypeScript らしいですよ。

以上

応援してもらってオープンソース化と出社のモチベーションを高めたい。