AndroidからSlack WebHookを利用

Android から Slack WebHookにPOSTしてみます。

使用ライブラリ

  • Gson
  • ButterKnife
  • OkHttp

build.gradle の dependencies に追加

    compile 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    compile 'com.google.code.gson:gson:2.8.0'
    compile 'com.squareup.okhttp:okhttp:2.0.0'

コード

送るメッセージを入れるクラス

public class Slack {
    public String text;
    public Slack(String text) {
        this.text = text;
    }
}

ボタンを押したらPOSTする

@OnClick(R.id.button)
    public void getRequest(final Button button) {
        button.setEnabled(false);

        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String result = null;

                Gson gson = new Gson();
                RequestBody requestBody = RequestBody.create(
                    MediaType.parse("text/plain"), gson.toJson(new Slack("Hello"))
                );

                Request request = new Request.Builder()
                    .url("WebHook URL")
                    .post(requestBody)
                    .build();

                OkHttpClient client = new OkHttpClient();
                try {
                    Response response = client.newCall(request).execute();
                    result = response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                // 返す
                return result;
            }

            @Override
            protected void onPostExecute(String result) {
                Log.d("result", result);
                button.setEnabled(true);
            }
        }.execute();
    }

各言語のテストコードのメモ

テストの書き方のメモ

たまに忘れるので、随時更新。 プログラムの例は 足し算するだけの add関数

Python

テストツールは nose を使います。

$ pip install nose

で入ります。

add関数

# calc.py
def add(a: int, b: int) -> int:
    return a+b

テストコード

# test_calc.py
import unittest
from nose.tools import ok_, eq_
import calc

class TestCalc(unittest.TestCase):
    def test_add(self):
        value = calc.add(1,5)
        eq_(6, value)

テスト実行

$ nosetests -v

Golang

add関数

# calc.go
package main

func add(a, b int) int {
        return a + b
}

テストコード

# calc_test.go
package main

import (
    "testing"
    "fmt"
)
func TestSum(t *testing.T) {
        if add(1, 2) != 3 {
                // Failed Message
                t.Fatal("sum(1,2) should be 3, but doesn't match")
        }
}

テスト実行

$ go test -cover -v

glide 入れてるなら

$ go test -cover -v `glide novendor`

Ruby

rspec を用いて Ruby のコードをテストします。

Gemfileを使って rspec をインストール

Gemfile を使って rspec を入れます。

Gemfile生成

$ bundle init

Gemfileをいじる

$ vim Gemfile

source "https://rubygems.org"

gem "rspec"

インストール

$ bundle install

入ってるか確認

$ bundle exec rspec -v
3.5.4

add関数

# calc.rb
def add(a, b)
  a + b
end

テストコード

テストコードをまとめるディレクトリを作ります。

$ mkdir spec

テストコード

# spec/calc_test.rb
require "./calc"

describe 'add' do
  it '1 + 1 = 2' do
    expect(add(1, 2)).to eq 3
  end
  it '10 - 1 は 9 になること' do
    expect(add(10, -1)).to eq 9
  end
end

テスト実行

$ bundle exec rspec

recipe でよく使うコマンド

recipeでよく使うコマンドのメモです。

パッケージインストール

NTPサーバの例

%w{
  ntp
}.each do |pkg|
  package pkg do
    action :install
  end
end

サービスの起動

service "ntpd" do
  action [:enable, :start]
end

テンプレートファイル切り替え

template "/etc/ntp.conf" do
  source "ntp.conf.erb"
  user "root"
  group "root"
  mode 0644
end

コマンド実行

execute "ntpdate ntp.nict.jp" do
  command "ntpdate ntp.nict.jp"
  user "root"
  group "root"
end

コマンド連続実行

zabbixでの例

bash "create user, database" do
  code <<-EOH
    mysql -u root -e "create database zabbix character set utf8 collate utf8_bin;"
    mysql -u root -e "grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbix';"
    mysql -u root -e "flush privileges;"
  EOH
end

rpmファイルのインストール

nginxの場合

remote_file "#{Chef::Config[:file_cache_path]}/nginx-release-rhel-6-0.el6.ngx.noarch.rpm" do
  source "http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm"
  not_if "rpm -qa | grep -q '^nginx-release'"
  action :create
  notifies :install, "rpm_package[nginx-release]", :immediately
end

rpm_package "nginx-release" do
  source "#{Chef::Config[:file_cache_path]}/nginx-release-rhel-6-0.el6.ngx.noarch.rpm"
  action :nothing
end

githubリポジトリを入れる

%w{
  https://github.com/k2la/tuning.git
}.each do |repo|
  file = repo.split("/")[-1].split(".")[0]
  git "/home/vagrant/#{file}" do
    repository repo
    revision "master"
    user "vagrant"
    group "vagrant"
    action :sync
  end
end

俺を支えた専門書 「コンピュータシステム」

今までに読んだコンピュータシステムに関する専門書を書いていきます。

コンピュータシステム

OS

Linuxシステムプログラミング

Linuxシステムプログラミング

改訂 新Linux/UNIX入門

改訂 新Linux/UNIX入門

オペレーティングシステムの仕組み (情報科学こんせぷつ)

オペレーティングシステムの仕組み (情報科学こんせぷつ)

Inside Linux Software オープンソースソフトウェアのからくりとしくみ

Inside Linux Software オープンソースソフトウェアのからくりとしくみ

Linuxシステム[実践]入門 (Software Design plus)

Linuxシステム[実践]入門 (Software Design plus)

Linuxカーネル解析入門 (I・O BOOKS)

Linuxカーネル解析入門 (I・O BOOKS)

アーキテクチャ

コンピュータアーキテクチャ (電子情報通信レクチャーシリーズ)

コンピュータアーキテクチャ (電子情報通信レクチャーシリーズ)

コンピュータアーキテクチャ 改訂4版

コンピュータアーキテクチャ 改訂4版

コンピュータの構成と設計 第4版 上 (Computer Organization and Design: The Hardware/Software Interface, Fourth Edition)

コンピュータの構成と設計 第4版 上 (Computer Organization and Design: The Hardware/Software Interface, Fourth Edition)

データベース

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

マンガでわかるデータベース

マンガでわかるデータベース

ネットワーク

インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門

インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門

マスタリングTCP/IP 入門編 第5版

マスタリングTCP/IP 入門編 第5版

[改訂新版] 3分間ネットワーク基礎講座

[改訂新版] 3分間ネットワーク基礎講座

〔改訂新版〕 3分間ルーティング基礎講座 (3分間NetWorkingシリーズ)

〔改訂新版〕 3分間ルーティング基礎講座 (3分間NetWorkingシリーズ)

3分間HTTP&メールプロトコル基礎講座

3分間HTTP&メールプロトコル基礎講座

図解でわかるネットワークプロトコル (日経BPムック)

図解でわかるネットワークプロトコル (日経BPムック)

実践 パケット解析 第2版 ―Wiresharkを使ったトラブルシューティング

実践 パケット解析 第2版 ―Wiresharkを使ったトラブルシューティング

3分間DNS基礎講座

3分間DNS基礎講座

セキュリティ

マスタリングTCP/IP 情報セキュリティ編

マスタリングTCP/IP 情報セキュリティ編

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践

リバースエンジニアリングバイブル ~コード再創造の美学~

リバースエンジニアリングバイブル ~コード再創造の美学~

デバッガによるx86プログラム解析入門【x64対応版】

デバッガによるx86プログラム解析入門【x64対応版】

デジタル・フォレンジック概論?フォレンジックの基礎と活用ガイド?

デジタル・フォレンジック概論?フォレンジックの基礎と活用ガイド?

俺を支えた専門書 「数学系」

今までに読んだ数学系の内容に関する専門書を書いていきます。

数学系

微分積分

まずはこの一冊から 意味がわかる微分・積分 (BERET SCIENCE)

まずはこの一冊から 意味がわかる微分・積分 (BERET SCIENCE)

線形代数

プログラミングのための線形代数

プログラミングのための線形代数

まずはこの一冊から 意味がわかる線形代数 (BERET SCIENCE)

まずはこの一冊から 意味がわかる線形代数 (BERET SCIENCE)

確率統計

プログラミングのための確率統計

プログラミングのための確率統計

まずはこの一冊から 意味がわかる統計学 (BERET SCIENCE)

まずはこの一冊から 意味がわかる統計学 (BERET SCIENCE)

まずはこの一冊から 意味がわかる統計解析 (BERET SCIENCE)

まずはこの一冊から 意味がわかる統計解析 (BERET SCIENCE)

まずはこの一冊から意味がわかる多変量解析 (BERET SCIENCE)

まずはこの一冊から意味がわかる多変量解析 (BERET SCIENCE)

機械学習

イラストで学ぶ 人工知能概論 (KS情報科学専門書)

イラストで学ぶ 人工知能概論 (KS情報科学専門書)

ITエンジニアのための機械学習理論入門

ITエンジニアのための機械学習理論入門

実践 機械学習システム

実践 機械学習システム

暗号

暗号技術入門 第3版 秘密の国のアリス

暗号技術入門 第3版 秘密の国のアリス

マンガでわかる暗号

マンガでわかる暗号

トコトンやさしい暗号の本 (B&Tブックス―今日からモノ知りシリーズ)

トコトンやさしい暗号の本 (B&Tブックス―今日からモノ知りシリーズ)

アルゴリズム

アルゴリズムクイックリファレンス

アルゴリズムクイックリファレンス

アルゴリズムの絵本-プログラミングが好きになる9つの扉

アルゴリズムの絵本-プログラミングが好きになる9つの扉

俺を支えた専門書 「プログラミング言語」

今までに読んだプログラミング言語に関する専門書を書いていきます。

言語

今現在で書ける言語は以下のとおりです。

C

苦しんで覚えるC言語

苦しんで覚えるC言語

Cの絵本 第2版 C言語が好きになる新しい9つの扉

Cの絵本 第2版 C言語が好きになる新しい9つの扉

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

C++

独習C++ 第4版

独習C++ 第4版

C++ の絵本

C++ の絵本

Java

明快入門Java (林晴比古実用マスターシリーズ)

明快入門Java (林晴比古実用マスターシリーズ)

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)

HTML/CSS

スラスラわかるHTML&CSSのきほん

スラスラわかるHTML&CSSのきほん

JavaScript

パーフェクトJavaScript (PERFECT SERIES 4)

パーフェクトJavaScript (PERFECT SERIES 4)

PHP

独習PHP 第3版

独習PHP 第3版

MySQL

基礎からのMySQL 改訂版 (基礎からシリーズ)

基礎からのMySQL 改訂版 (基礎からシリーズ)

Python

みんなのPython 第3版

みんなのPython 第3版

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

Ruby

たのしいRuby 第5版

たのしいRuby 第5版

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

Golang

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

Go言語入門

Go言語入門

指定した単語を含むパワポファイル出力ツールを作ったよ

作ったきっかけ

Golang系のスライドどこいった...?」 っていうことが度々起こったため作りました。

slideshareのスライドを電車の中で読むために、いっぱいダウンロードするんですよね。 で、何日か経つと「あのときのあのスライドどこいった〜?」ってなるわけ。

作ったもの

-w word で指定するとwordを含むパワポファイルのフルパスを表示。

$ ./pptgrep -w GOOGLE
/home/k2la/test.pptx

-p startpoint で指定するとstartpoint内のファイルから探してくれる。

$ ./pptgrep -w APPLE -p ~
/home/k2la/test1.pptx
/home/k2la/test2.pptx
/home/k2la/test3.pptx

-r をつけて再帰的に探すこともできます

$ ./pptgrep -w Docker -r -p ~/Downloads
/home/k2la/Downloads/docker/test.pptx
/home/k2la/Downloads/docker/test02.pptx
/home/k2la/Downloads/slide0706/test.pptx

実装

パワポファイル(.pptx)

file コマンドで調べてみると

$ file test.pptx
test.pptx: Microsoft PowerPoint 2007+

こんな感じに出力されます。

で、これを unzip コマンドで解凍してみると

$ unzip test.pptx -d test
Archive:  test.pptx
  inflating: test/[Content_Types].xml
  inflating: test/_rels/.rels
  inflating: test/ppt/slides/_rels/slide1.xml.rels
  inflating: test/ppt/slides/_rels/slide2.xml.rels
  inflating: test/ppt/slides/_rels/slide3.xml.rels
  inflating: test/ppt/slides/_rels/slide4.xml.rels
  inflating: test/ppt/_rels/presentation.xml.rels
  inflating: test/ppt/presentation.xml
  inflating: test/ppt/slides/slide4.xml
  inflating: test/ppt/slides/slide3.xml
  inflating: test/ppt/slides/slide2.xml
  inflating: test/ppt/slides/slide1.xml
  inflating: test/ppt/slideLayouts/_rels/slideLayout3.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout6.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout8.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout9.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout7.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout4.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout5.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout1.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout2.xml.rels
  inflating: test/ppt/slideMasters/_rels/slideMaster1.xml.rels
  inflating: test/ppt/slideLayouts/_rels/slideLayout10.xml.rels
  inflating: test/ppt/slideLayouts/slideLayout10.xml
  inflating: test/ppt/slideLayouts/slideLayout2.xml
  inflating: test/ppt/slideLayouts/slideLayout1.xml
  inflating: test/ppt/slideLayouts/_rels/slideLayout11.xml.rels
  inflating: test/ppt/slideMasters/slideMaster1.xml
  inflating: test/ppt/slideLayouts/slideLayout3.xml
  inflating: test/ppt/slideLayouts/slideLayout4.xml
  inflating: test/ppt/slideLayouts/slideLayout5.xml
  inflating: test/ppt/slideLayouts/slideLayout9.xml
  inflating: test/ppt/slideLayouts/slideLayout11.xml
  inflating: test/ppt/slideLayouts/slideLayout8.xml
  inflating: test/ppt/slideLayouts/slideLayout6.xml
  inflating: test/ppt/slideLayouts/slideLayout7.xml
  inflating: test/ppt/theme/theme1.xml
 extracting: test/ppt/media/image1.jpeg
  inflating: test/ppt/theme/_rels/theme1.xml.rels
 extracting: test/docProps/thumbnail.jpeg
  inflating: test/ppt/presProps.xml
  inflating: test/ppt/tableStyles.xml
  inflating: test/ppt/viewProps.xml
  inflating: test/docProps/app.xml
  inflating: test/docProps/core.xml

こんな感じに解凍されます。

スライドのタイトルや内容の文字列は ppt/slides/slide*.xml に含まれています。

この中を調べていくことになります。

ソースコードの一部

以下のコードは

  • isPpt(ファイル): パワポファイルかどうかの判定や
  • containWord(パワポファイル, 検索語): unzipと文字列の検索

で構成されています。

package main

import (
    "archive/zip"
    "path/filepath"
    "regexp"
)

var slide = regexp.MustCompile(filepath.Join("ppt", "slides", "slide"))

func isPpt(path string) bool {
    e := filepath.Ext(path)
    if e == ".ppt" || e == ".pptx" {
        return true
    }
    return false
}

func containWord(archive, word string) bool {
    reader, err := zip.OpenReader(archive)
    if err != nil {
        return false
    }

    for _, file := range reader.File {
        if slide.MatchString(file.Name) {
            fileReader, err := file.Open()
            if err != nil {
                return false
            }
            var p = make([]byte, file.FileInfo().Size())
            fileReader.Read(p)
            defer fileReader.Close()
            r := regexp.MustCompile(word)
            if r.MatchString(string(p)) {
                return true
            }
        }
    }
    return false
}

パワポファイルかどうかの判定は、あまりよろしくないですが拡張子で判定しています。

文字列の検索部分は、正規表現で含んでいるかどうかを見ています。

リポジトリはこちら

GitHub - k2la/pptgrep