2015/05/21


slack から stackoverflow を検索出来る slack-overflow の lingr 版を作ってみた。

karan/slack-overflow - GitHub
https://github.com/karan/slack-overflow
akechi/stackoverflow-lingrbot - GitHub
https://github.com/akechi/stackoverflow-lingrbot

今回はなんとなく gin で書いた。

Gin Web Framework

Low Overhead Powerful API You can add global, per-group, and per-route middlewares, thousands of nes...

https://gin-gonic.github.io/gin/

コード短いのでのっけておく。

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "net/http"
    "net/url"
    "os"
    "regexp"

    "github.com/gin-gonic/gin"
    "github.com/mattn/go-lingr"
)

type resp struct {
    Items []struct {
        Tags  []string `json:"tags"`
        Owner struct {
            Reputation   int    `json:"reputation"`
            UserID       int    `json:"user_id"`
            UserType     string `json:"user_type"`
            ProfileImage string `json:"profile_image"`
            DisplayName  string `json:"display_name"`
            Link         string `json:"link"`
        } `json:"owner"`
        IsAnswered       bool   `json:"is_answered"`
        ViewCount        int    `json:"view_count"`
        AnswerCount      int    `json:"answer_count"`
        Score            int    `json:"score"`
        LastActivityDate int    `json:"last_activity_date"`
        CreationDate     int    `json:"creation_date"`
        QuestionID       int    `json:"question_id"`
        Link             string `json:"link"`
        Title            string `json:"title"`
    } `json:"items"`
    HasMore        bool `json:"has_more"`
    QuotaMax       int  `json:"quota_max"`
    QuotaRemaining int  `json:"quota_remaining"`
}

var re = regexp.MustCompile(`^stackoverflow(?:\w+) (.+)$`)

func defaultAddr() string {
    port := os.Getenv("PORT")
    if port == "" {
        return ":80"
    }
    return ":" + port
}

var addr = flag.String("addr", defaultAddr(), "server address")

func main() {
    flag.Parse()

    r := gin.Default()

    r.GET("/"func(c *gin.Context) {
        c.String(200"")
    })
    f := func(c *gin.Context) {
        site := c.Params.ByName("site")
        if site == "" {
            site = "stackoverflow"
        }
        var status lingr.Status
        if !c.EnsureBody(&status) {
            return
        }
        urls := ""
        for _, event := range status.Events {
            message := event.Message
            if message == nil {
                continue
            }
            if !re.MatchString(message.Text) {
                continue
            }
            question := re.FindStringSubmatch(message.Text)[1]
            params := url.Values{}
            params.Add("intitle", question)
            params.Add("site", site)
            params.Add("sort""activity")
            params.Add("order""desc")
            res, err := http.Get("https://api.stackexchange.com/2.2/search?" + params.Encode())
            println("https://api.stackexchange.com/2.2/search?" + params.Encode())
            if err != nil {
                println(err.Error())
                continue
            }
            defer res.Body.Close()
            var resp resp
            if err := json.NewDecoder(res.Body).Decode(&resp); err != nil {
                println(err.Error())
                continue
            }
            for _, item := range resp.Items {
                u := item.Link
                if len(u) > 300 {
                    u = fmt.Sprintf("http://%s.com/q/%d", site, item.QuestionID)
                }
                s := fmt.Sprintf("%s\n%s\n", item.Title, u)
                println(s)
                if len(urls+s) > 1000 {
                    break
                }
                urls += s
            }
        }
        c.String(200, urls)
        return
    }
    r.POST("/", f)
    r.POST("/:site", f)
    r.Run(*addr)
}

僕がこういうのを書く時は、一度 JSON を何等かの方法で得て

JSON-to-Go: Convert JSON to Go instantly

JSON-to-Go Convert JSON to Go struct This tool instantly converts JSON into a Go type definition. Pa...

http://mholt.github.io/json-to-go/

このサイトで golang の struct に変換、クライアント処理として stackoverflow の検索処理を実装しながら最後に Web のガワを付けていく。実質20~30分程度で出来た。

困ったのが stackoverflow の日本語版にも対応したのだけど、日本語版は URL にタイトルの日本語が含まれていて平気で1000文字を超える。しかし lingr の API は1000文字までしか発言出来なくて(bot triggered アクションで分割送信なら可能)困った。どうやら URL の日本語部分は無くてもアクセス出来るのが分かったので300文字(適当)超えたらそっちを使う様に対応した。

lingr だと stackoverflow という名前で居ますので invite して「stackoverflow jquery」とか「stackoverflowja ウェブ」とか発言すると反応します。

Posted at by



2015/05/20


C++er ならみんな見てるいう噂の江添さんの ask.fm。見ているだけも面白いですが、質問もしたくなりますよね。

Ryou Ezoe | ask.fm/EzoeRyou
http://ask.fm/EzoeRyou

質問したいだけなのにいちいちブラウザ起動するのもダルいので、コマンドラインから質問を投げられるコマンド「ezoe」を作りました。

mattn/ezoe · GitHub
https://github.com/mattn/ezoe

インストールは簡単で golang が入ってる状態なら

$ go get github.com/mattn/ezoe

これだけで ok。使い方も簡単で

$ ezoe

とすると質問の一覧が色付きで表示される。

しかも「質問ではない」と「自由」がハイライトされるので江添フリークも安心。そして引数を付けて起動すると ask.fm に質問を投げられます。

$ ezoe 僕は梅干しが大好きです

あとは江添さんの回答を待つだけ。「質問ではない」って返事が返ってきたら素直に喜びましょう。

オマケ機能ですが、-u フラグで江添さん以外の人にも使えます。

$ ezoe -u mattn_jp golangをご覧ください

質問ではない。

Posted at by



2015/05/18


dufferzafar/cheat - GitHub

Cheatsheets for command line, because, you know, life is too short to read manpages.

https://github.com/dufferzafar/cheat

人生は短い。

$ go get github.com/dufferzafar/cheat

してインストール。ホームディレクトリ直下に .cheatsheets というフォルダを作り、そこに

jahendrie/cheat - GitHub
https://github.com/jahendrie/cheat

このリポジトリにある data フォルダ内のファイルをコピーすればよろし。

cheat - Create and view command-line cheatsheets.

Version: 0.5

Usage:
    cheat <command> [cheatsheet] [<args>]


Commands:
    show        Show cheats related to a command
    edit        Add/Edit a cheat
    list        List all available cheats
    config      Edit the config file
    help        Shows a list of commands or help for one command


Global Options:
    --help, -h          show help
    --version, -v       print the version


Examples:
    cheat show git              Shows git cheatsheet
    cheat show git -c 12        Copy the 12th git cheat

    cheat edit at               Edit cheatsheet named at
$ cheat edit curl

でエディタが起動するので自分で追加する事も可能。Windows 対応もしておきましたので、その内マージされるかも。

Support Windows by mattn · Pull Request #1 · dufferzafar/cheat - GitHub
https://github.com/dufferzafar/cheat/pull/1
Posted at by