├── .gitignore ├── .travis.yml ├── Dockerfile ├── README.md └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | ompiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | secret.env 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - '1.3' 4 | - 'tip' 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.6-onbuild 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | o3o - Telegram Bot 2 | ------------------ 3 | 4 | [![Build Status](https://travis-ci.org/kamikat/o3o_bot.svg?branch=master)](https://travis-ci.org/kamikat/o3o_bot) 5 | 6 | `o3o` is a telegram bot about kaomoji (顔文字) written in Go use library from [o3o](https://github.com/guo-yu/o3o) 7 | which is a Node.js kaomoji library. 8 | 9 | License 10 | ------- 11 | 12 | (The MIT License) 13 | 14 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "log" 6 | "time" 7 | "net/http" 8 | "encoding/json" 9 | "strings" 10 | "encoding/hex" 11 | "crypto/md5" 12 | "math/rand" 13 | "github.com/tucnak/telebot" 14 | ) 15 | 16 | type KaomojiDict struct { 17 | Tag string `json:"tag"` 18 | Yan []string `json:"yan"` 19 | } 20 | 21 | var bot *telebot.Bot 22 | var dict []KaomojiDict 23 | var tags []string 24 | var next map[string][]string = make(map[string][]string) 25 | 26 | func main() { 27 | 28 | token := os.Getenv("BOT_API_TOKEN") 29 | if len(token) > 0 { 30 | log.Printf("Telegram Bot Token: %v\n", token) 31 | } else { 32 | log.Fatal("Please set 'BOT_API_TOKEN' from environment variable") 33 | } 34 | 35 | updateDict() 36 | 37 | if newBot, err := telebot.NewBot(token); err != nil { 38 | log.Fatal(err); 39 | } else { 40 | bot = newBot 41 | } 42 | 43 | bot.Messages = make(chan telebot.Message, 1000) 44 | bot.Queries = make(chan telebot.Query, 1000) 45 | 46 | go messages() 47 | go queries() 48 | 49 | log.Printf("Started.") 50 | 51 | bot.Start(1 * time.Second) 52 | } 53 | 54 | func updateDict() { 55 | log.Println("Updating kaomoji dictionary...") 56 | 57 | body := map[string][]KaomojiDict{} 58 | 59 | resp, err := http.Get("https://raw.githubusercontent.com/guo-yu/o3o/master/yan.json") 60 | 61 | if err != nil { 62 | log.Fatal(err) 63 | } 64 | 65 | decoder := json.NewDecoder(resp.Body) 66 | 67 | if err := decoder.Decode(&body); err != nil { 68 | log.Fatal(err) 69 | } else { 70 | dict = body["list"] 71 | tags = make([]string, len(dict)) 72 | for i, e := range dict { 73 | tags[i] = e.Tag 74 | for _, o3o := range e.Yan { 75 | next[o3o] = e.Yan 76 | } 77 | } 78 | log.Println("Kaomoji dictionary initialized.") 79 | } 80 | } 81 | 82 | func messages() { 83 | for message := range bot.Messages { 84 | log.Println("--- new message ---") 85 | log.Println("from:", message.Sender) 86 | log.Println("text:", message.Text) 87 | switch text := message.Text; { 88 | case message.Text == "/start": 89 | bot.SendMessage(message.Chat, `Here is o3o bot.`, nil) 90 | case message.Text == "/tags": 91 | bot.SendMessage(message.Chat, 92 | "List of kaomoji tags:\n\n" + strings.Join(tags, "\n") + 93 | "\n\nFull list of kaomojies: https://github.com/guo-yu/o3o/blob/master/yan.json ", 94 | &telebot.SendOptions { DisableWebPagePreview: true }) 95 | default: 96 | if yans, found := next[text]; found { 97 | bot.SendMessage(message.Chat, yans[rand.Intn(len(yans))], nil) 98 | } else { 99 | bot.SendMessage(message.Chat, `o3o is in panic.`, nil) 100 | } 101 | } 102 | } 103 | } 104 | 105 | type Result struct { 106 | Id string `json:"id"` 107 | Type string `json:"type"` 108 | Title string `json:"title"` 109 | Text string `json:"message_text"` 110 | Description string `json:"description"` 111 | } 112 | 113 | type KaomojiWrapper struct { 114 | Result Result 115 | } 116 | 117 | func (wrapper KaomojiWrapper) MarshalJSON() ([]byte, error) { 118 | r := wrapper.Result 119 | r.Type = "article"; 120 | bytes, err := json.Marshal(r); 121 | return bytes, err 122 | } 123 | 124 | func queries() { 125 | for query := range bot.Queries { 126 | log.Println("--- new query ---") 127 | log.Println("from:", query.From) 128 | log.Println("text:", query.Text) 129 | 130 | results := make([]telebot.Result, 0, 19) 131 | result_guard := make(map[string]bool) 132 | 133 | for _, entry := range dict { 134 | if tag, q := entry.Tag, query.Text; strings.Contains(" " + tag, " " + q) { 135 | for _, y := range entry.Yan { 136 | if len(results) < cap(results) { 137 | sum := md5.Sum([]byte(y)) 138 | result_id := string(hex.EncodeToString(sum[:])) 139 | if _, found := result_guard[result_id]; !found { 140 | results = append(results, &KaomojiWrapper { 141 | Result { Id: result_id, Title: y, Text: y, Description: tag }, 142 | }) 143 | result_guard[result_id] = true 144 | } 145 | } 146 | } 147 | } 148 | } 149 | 150 | // And finally respond to the query: 151 | if err := bot.Respond(query, results); err != nil { 152 | log.Println("ouch:", err) 153 | } 154 | } 155 | } 156 | --------------------------------------------------------------------------------