Slackのアイコンを毎日違う嫁にする

2022/01/12 追記

WaifuLabsのAPIが非公開になり形式が変わったので非対応になりました。悲しい。

概要

Go言語+AWS LambdaでSlackのアイコンを定期的に変えます。

アイコンはWaifuLabsから自動で生成します。

WaifuLabsを利用することで毎日違うアイコンになります。新鮮。

嫁サンプル
f:id:tetsujp84:20200409024045p:plain:w100 f:id:tetsujp84:20200409024247p:plain:w100 f:id:tetsujp84:20200409024250p:plain:w100 f:id:tetsujp84:20200409024413p:plain:w100

プロジェクト

コード全体はGitHubで公開しています。
auto-waifu-lab

アイコン変更のコード

get_image.go

WaifuLabs から嫁画像を取得します。

取得APIhttps://api.waifulabs.com/generate_bigを使用しました。

https://api.waifulabs.com/generateはパラメータ不要で取得できますが、
1回で無駄に16枚分の画像を返してしまうのでこちらは使っていません。

func GetImage() {
    // WaifuLabsはいつくかのAPIをよんでおり、そのうちの一つがgenerate_big
    URL := "https://api.waifulabs.com/generate_big"

    rand.Seed(time.Now().UnixNano())

    // JSON形式でパラメータ生成
    // currentGirlのあとに16個のパラメータ値を指定する
    values := `{"currentGirl" : [`
    param := ""
    val := strconv.Itoa(rand.Intn(999999))
    for i := 0; i < 16; i++ {
        param += val + ","
    }
    param += "0"
    values += param
    values += "]}"

    req, err := http.NewRequest("POST", URL, bytes.NewBufferString(values))
    if err != nil {
        fmt.Println(err)
        return
    }
    req.Header.Add("Content-Type", "application/json")

    // API実行
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        log.Println(err)
        return
    }

    // Res解析
    b, err := ioutil.ReadAll(resp.Body)
    if err == nil {
        // Base64デコード
        base64Data := new(Base64Data)
        if err := json.Unmarshal(b, &base64Data); err != nil {
            fmt.Println(err)
            return
        }
        data, err := base64.StdEncoding.DecodeString(base64Data.girl)
        if err != nil {
            fmt.Println(err)
        }
         // レスポンスデータを使用してpng生成
         // send_to_slackでtoday.pngの名前を指定してSlackで送っているため
        file, err := os.Create("/tmp/today" + ".png")
        if err != nil {
            fmt.Println(err)
            defer file.Close()
            return
        }
        file.Write(data)
        defer file.Close()
    }
    defer resp.Body.Close()
}

send_to_slack.go

Slackのアイコン変更APIを実行します。

Slack用ライブラリはnlopes/slackを使用しました。

func trySend(trycount int) {
    // Lambda側でTOKENを設定する
    token := os.Getenv("SLACKTOKEN")
    api := slack.New(token)

    err := api.SetUserPhoto("/tmp/today.png", slack.NewUserSetPhotoParams())
    if err != nil {
        fmt.Println(err)
        // 何度が失敗することがあったので再度送っている、不要かもれしない
        if trycount == 1 {
            trycount++
            trySend(trycount)
        }
        return
    }
    return
}

Slack Tokenの取得

リンクを参考にSlackのAppを作成します。

APIとしてusers.profile.setを使用するのでPermissionsにusers.profile:writeを追加します。

このとき生成されるOAuth Access Token(xoxp-で始まる)を環境変数として後で使用します。

AWS Lambdaでの実行

こちらを参考に設定を進めます。

entry.goがlambdaのエントリーポイントになります。

entry.go

package main

import (
    "fmt"

    "./mywaifulab"
    "github.com/aws/aws-lambda-go/lambda"
)
// mainは必須
func main() {
    // lambda側で呼ぶ
    lambda.Start(entry)
}

func entry() {
    // 画像を取得→Slackに投げる
    mywaifulab.GetImage()
    mywaifulab.SendToSlack()
}

windowsでパッケージをZIPにする際はAWSから提供されているビルドツールを使用します。

こちらでZIP化しないとメソッドの呼び出しが正しく行われませんでした。

Lambdaで関数を作成し、関数コードとしてZIPファイルをアップロードします。

環境変数にSLACKTOKENを追加し、ValueはSlackのAccess Tokenにします。

定期実行にはLambdaのCloudWatch Events/EventBridgeを使用します。参考

スケジュール式はrate式かcron式で記述します。参考

保存すると定期実行されます。

結果

アイコンを毎日変えると混乱します。