Mercurial > lbo > hg > goe_bot
view webhook.go @ 35:fc1164117cb5
Revert last commit
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 10 Dec 2016 13:52:56 +0100 |
parents | d35d389fa9fb |
children |
line wrap: on
line source
package main import ( "bytes" "context" "encoding/json" "errors" "fmt" "io/ioutil" "log" "net/http" "time" ) // Register webhook func registerWebhook() error { setWebhhokRq := setWebhook{URL: *flagMyURL + "?" + *flagWebhookToken} body, err := json.Marshal(setWebhhokRq) if err != nil { log.Println("Couldn't serialize setWebhook request:", err) return err } rp, err := defaultClient.Post(buildURL(setWebhookMethod), jsonBodyType, bytes.NewBuffer(body)) if err != nil { log.Println("Couldn't register webhook:", err) return err } if rp.StatusCode == http.StatusOK { return nil } else { return errors.New(fmt.Sprint("Bad return code for setWebhook:", rp.StatusCode)) } } func deleteWebhook() error { rp, err := defaultClient.Post(buildURL(deleteWebhookMethod), jsonBodyType, bytes.NewBuffer(nil)) if err != nil { return err } if rp.StatusCode == http.StatusOK { return nil } else { errMsg := fmt.Sprintf("Bad return code for deleteWebhook:", rp.StatusCode) log.Println(errMsg) return errors.New(errMsg) } } func getWebhookInfo(ctx context.Context) (string, error) { srvStatus.apiCalls++ rq, err := http.NewRequest(http.MethodGet, buildURL(getWebhookInfoMethod), bytes.NewBuffer(nil)) if err != nil { log.Println("Couldn't create request for getWebhookInfo:", err) return "", err } rq = rq.WithContext(ctx) rp, err := defaultClient.Do(rq) if err != nil { log.Println("Couldn't getWebhookInfo:", err) return "", err } if rp.StatusCode == http.StatusOK { body, err := ioutil.ReadAll(rp.Body) if err != nil { return "", err } info := webhookInfo{} err = json.Unmarshal(body, &info) if err != nil { log.Println("Couldn't parse getWebhookInfo result:", err) return "", err } return fmt.Sprintf("pending=%d last-error='%s'", info.Pending_Update_Count, info.Last_Error_Message), nil } else { srvStatus.apiErrors++ log.Println("Couldn't getWebhookInfo:", rp.StatusCode) return "", errors.New("Bad response code") } } // Webhook handler (push method; /hook) // Receives `update`s as JSON func updatesHandler(rp http.ResponseWriter, rq *http.Request) { ctx, cancel := context.WithTimeout(rq.Context(), time.Duration(*flagDeadline)*time.Second) defer cancel() body, err := ioutil.ReadAll(rq.Body) if err != nil { rp.WriteHeader(400) log.Println("Couldn't read body for webhook request:", err) return } log.Println("Received update:", string(body)) upd := update{} err = json.Unmarshal(body, &upd) if err != nil { rp.WriteHeader(400) log.Println("Couldn't deserialize webhook update:", err) return } if !checkAuthToken(rq) { rp.WriteHeader(http.StatusUnauthorized) return } responseMsg, err := dispatch(ctx, upd) if err != nil { rp.WriteHeader(http.StatusInternalServerError) log.Println("Error from dispatch; returning 500") return } // Empty response, e.g. for callback handlers if responseMsg.Chat_ID == 0 { rp.WriteHeader(http.StatusOK) return } responseMsg.Method = sendMessageMethod responseBody, err := json.Marshal(responseMsg) if err != nil { rp.WriteHeader(http.StatusInternalServerError) log.Println("Couldn't serialize webhook response:", err) return } log.Println("Replied:", string(responseBody)) rp.Header().Set("Content-Type", jsonBodyType) rp.WriteHeader(http.StatusOK) rp.Write(responseBody) } // Checks if the supplied auth token is correct. Only we and Telegram should know it. // The webhook URL has the format https://some.hook.com/?TOKENTOKENTOKEN // If the token is empty, no check is done. func checkAuthToken(rq *http.Request) bool { if *flagWebhookToken == "" { return true } if err := rq.ParseForm(); err != nil { log.Println("Error parsing request form:", err) return false } if _, ok := rq.Form[*flagWebhookToken]; !ok { log.Println("Bad token on webhook request!") return false } return true }