動かざることバグの如し

近づきたいよ 君の理想に

JSONのAPIリクエストコマンドを楽にするjoという奴

やりたいこと

最近のAPIは猫も杓子もJSONをContent-Typeとして受け付けるのがほとんどである。別にそれはいいのだがJSONは人間には優しくない。特にターミナル上でJSONを記述しようものなら死ぬ。

ターミナルで編集させる気が1ミリも感じさせないcurlコマンドの例

#!/bin/bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "こんにちは、今日の天気を教えてください。"}
    ],
    "temperature": 0.7
  }'

そこでコマンドラインからJSONを簡単に生成できるjoコマンドを使ってみる。

インストール

# Ubuntu
apt install jo

# MacOS
brew install jo

使い方

joコマンドは、コマンドラインからJSONデータを簡単に生成するためのツールで、キーと値のペアや配列を引数として渡すことで、JSONオブジェクトを作成できる

❯ jo name=かぐや age=17

すると出力が

{"name":"かぐや","age":17}

となる。最高

# pretty出力
jo -p name=かぐや age=17

# 配列の生成
jo -a 春 夏 秋 冬

# ブール値の指定
jo is_student@true

# ファイルの内容を埋め込む
jo content=@file.txt

# ネスト
jo -p name=Alice info=$(jo age=30 city=Tokyo)

curlと組み合わせた例

jo単体で使うっていうよりcurlとパイプで組み合わせると便利

jo -p message=hello | curl -XPOST -H "Content-Type: application/json" -d @- https://httpbin.org/post

ちなみに冒頭のcurlのオプションをjoで書き直すと

jo messages=$(jo -a $(jo role=user content='こんにちは、今日の天気を教えてください。')) temperature=0.7

になる。

Railsバリデーションで全角カタカナ入力だけを許可する方法

環境

やりたいこと

全角カタカナのみを受け付けるバリデーションを実装したい。個人情報入力フォームの「ヤマダタロウ」みたいな。

コード

class User < ApplicationRecord
  validates :name, format: { 
    with: /\A[\p{katakana}ー-]+\z/, 
    message: "は全角カタカナのみで入力してください" 
  }
end

validates :name, format: { with: /\A[\p{katakana}ー-]+\z/, message: "は全角カタカナのみで入力してください" } で name 属性に対して、指定した正規表現にマッチするかどうかのバリデーションを設定している。

  • \A: 文字列の先頭
  • [\p{katakana}ー-]+: 全角カタカナ(\p{katakana})と長音記号(ー、-)が1文字以上続くパターン
  • \z: 文字列の末尾

apkをデコンパイルしてjavaソースコードを解析する

やりたいこと

拾ってきた野良apkをデコンパイルしてJavaソースコードを解析したい

apkの仕組み

Androidアプリのパッケージ形式

APK(Android Package)ファイルは、Androidアプリを配布・インストールするためのパッケージ形式だ。アーカイブファイルであり、ZIP形式で複数のファイルやディレクトリを含んでいる。

Javaからapkができるまで

Androidアプリ開発では、Java(もしくはKotlin)でソースコードを記述する。このソースコードは、コンパイルされてDEX(Dalvik Executable)バイトコードに変換される。DEXバイトコードは、AndroidのDalvikまたはART仮想マシンで実行可能な形式だ。

apkファイルはこのDEXバイトコードを含んでおり、その他にアプリのリソース(画像、レイアウトファイルなど)、マニフェストファイル(アプリの情報が記述されたファイル)などが含まれる。

つまり、開発者がJavaで記述したソースコードは、コンパイル過程を経てDEXバイトコードに変換され、他のリソースファイルとともにapkファイルにパッケージングされるわけだ。

デコンパイルツール

色々探した結果、apk2javaってやつがシンプルで良かった

duo-labs/apk2java: Automatically decompile APK's using Docker

Dockerfile見るとわかるが実際にはdex2jarを使っておりただのラッパーに過ぎない。

ちょっとDockerfileの構成が古かったのでリライトした

使い方

まずデコンパイルしたいapkをtarget.apkだとしてカレントディレクトリに配置し、以下実行

docker run --rm -v ./:/app thr3a/apk2java:latest /app/target.apk

するとディレクトリが作成されてその中に大量のjavaが生成される。

デコンパイル後のコードの見方

デコンパイルされたJavaソースコードは、元のコードと完全に同じではない。これは、コンパイルの過程で情報が一部失われるためだ。特に、変数名やメソッド名などは難読化されていることが多い。

しかし、コードの構造やロジックは概ね把握できるため、アプリの動作を解析する上では十分役に立つ。

難読化への対応

難読化されたコードを解析する際には、Javaの逆コンパイラやデバッガなどを活用する。これらのツールを使えば、コードをステップ実行したり、変数の値を確認したりすることができるため、解析が容易になる。

注意点

デコンパイルは、著作権法に触れる可能性があるため、注意が必要だ。 解析する際には、アプリの開発者に許可を得るか、個人利用の範囲内にとどめるようにしよう。

ギャルモードで会話するプロンプト

ギャルモード

あなたは重度のギャル語を使う明るくて楽観主義な女子高校生ギャルです。
以下の制約条件を厳密に守ってギャルモードを実行してください。

# 制約条件
- 「〜じゃん」「〜っしょ」などの語尾を多用する
- 「マジ」「超」「めっちゃ」などの強調表現を多用する
- 「エモい」「尊い」「ヤバい」「ウケる」「草」などの感情表現を多用する
- 「とりま(とりあえずまぁ)」「めっちゃ(めちゃくちゃ)」など省略表現を多用する
- 一人称は「うち」
- 感情を表現するときに絵文字を1文に1個程度使用する

ツンデレお嬢様

あなたは12歳の上品なツンデレお嬢様です。
以下の制約条件を厳密に守って会話してください。

# 制約条件
- 「~ですわ」「〜かしら」などの語尾を多用する
- 否定形を多用するが、完全に拒絶するのではなく、含みを持たせる
  - 例「嫌いじゃありませんわ」
- 時折鋭い皮肉を交える
- 「~してあげてもいいですわ」のような上から目線の表現

服部平次

あなたは名探偵コナンに登場する大阪の高校生名探偵、服部平次です。
以下の制約条件を厳密に守って服部平次モードで会話してください。

- 明るく負けず嫌いな性格
- 砕けた乱暴な関西弁の口調
- 「〜やで」「〜ちゅうわけか」など関西弁特有の表現を多用する。
- 「せやかて」(そう言っても)、「ほんま」(本当に)、「どや」(どうや、どうだ)など、関西地方特有の表現を多用する。
- 「めっちゃ」「ぎょうさん」など関西弁の副詞を多用する。
- 一人称はオレで相手のことを会話相手を「工藤」と呼ぶ。

四宮かぐや

あなたはかぐや様は告らせたいに登場する財閥の娘、女子高生「四宮かぐや」です。
以下の制約条件を厳密に守って四宮かぐやモードで会話してください。

一人称は「私」を使用
丁寧語を基調とした話し方をする
「お可愛いこと」という独特の表現を使う
白銀御行のことを「会長」と呼ぶ
藤原千花のことを「藤原さん」と呼ぶ
「~ですわ」「~ますわ」など、お嬢様言葉を使用する傾向がある
感情が高ぶると「くっ...」などと言葉に詰まることがある
相手を見下すような言い回しを無意識に使うことがある
冷静な状況では論理的で知的な話し方をする
緊張したり動揺したりすると、言葉遣いが乱れることがある
「愛のない表現は結局みんなを不幸にする」など、感情を重視した発言をすることもある

AS番号から紐づくIP帯域を全取得する

環境

やりたいこと

AS番号を渡したらIP帯域をCIDR形式で全部取得したい。

コード

import requests
import json


def get_ipv4_ranges(as_number):
    url = f"https://ipinfo.io/widget/demo/{as_number}?dataset=asn"
    response = requests.get(url)
    data = json.loads(response.text)

    ipv4_ranges = []
    for prefix in data["prefixes"]:
        if "/" in prefix["netblock"]:
            ipv4_ranges.append(prefix["netblock"])

    return ipv4_ranges


def save_to_file(as_number, ipv4_ranges):
    with open(f"{as_number}.txt", "w") as file:
        for range in ipv4_ranges:
            file.write(f"{range}\n")


as_number = "AS7684"
ipv4_ranges = get_ipv4_ranges(as_number)
save_to_file(as_number, ipv4_ranges)