diff --git a/Makefile b/Makefile
index a5b8661..d04d811 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all: clessy-broker clessy-mods clessy-stats
+all: tg-broker clessy-mods clessy-stats
deps:
go get github.com/boltdb/bolt/...
@@ -8,10 +8,10 @@ deps:
go get github.com/disintegration/imaging
install-tg:
- go install github.com/hamcha/clessy/tg
+ go get -u github.com/hamcha/tg
-clessy-broker: install-tg
- go build -o clessy-broker github.com/hamcha/clessy/broker
+tg-broker: install-tg
+ go get -u github.com/hamcha/tg/cmd/tg-broker
clessy-mods: install-tg
go build -o clessy-mods github.com/hamcha/clessy/mods
@@ -23,4 +23,4 @@ clessy-stats-import: install-tg
go build -o clessy-stats-import github.com/hamcha/clessy/stats-import
clean:
- rm -f clessy-broker clessy-mods clessy-stats
\ No newline at end of file
+ rm -f clessy-mods clessy-stats
\ No newline at end of file
diff --git a/broker/action.go b/broker/action.go
deleted file mode 100644
index 826b6a6..0000000
--- a/broker/action.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package main
-
-import (
- "net"
-
- "github.com/hamcha/clessy/tg"
-)
-
-func executeClientCommand(action tg.ClientCommand, client net.Conn) {
- switch action.Type {
- case tg.CmdSendTextMessage:
- data := *(action.TextMessageData)
- api.SendTextMessage(data)
- case tg.CmdGetFile:
- data := *(action.FileRequestData)
- api.GetFile(data, client, *action.Callback)
- case tg.CmdSendPhoto:
- data := *(action.PhotoData)
- api.SendPhoto(data)
- case tg.CmdForwardMessage:
- data := *(action.ForwardMessageData)
- api.ForwardMessage(data)
- case tg.CmdSendChatAction:
- data := *(action.ChatActionData)
- api.SendChatAction(data)
- }
-}
diff --git a/broker/clients.go b/broker/clients.go
deleted file mode 100644
index d93687f..0000000
--- a/broker/clients.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package main
-
-import (
- "bufio"
- "encoding/json"
- "fmt"
- "log"
- "net"
-
- "github.com/hamcha/clessy/tg"
-)
-
-var clients []net.Conn
-
-func startClientsServer(bind string) {
- listener, err := net.Listen("tcp", bind)
- assert(err)
-
- // Accept loop
- for {
- c, err := listener.Accept()
- if err != nil {
- log.Printf("Can't accept client: %s\n", err.Error())
- continue
- }
- clients = append(clients, c)
- go handleClient(c)
- }
-}
-
-func handleClient(c net.Conn) {
- b := bufio.NewReader(c)
- defer c.Close()
-
- // Start reading messages
- buf := make([]byte, 0)
- for {
- bytes, isPrefix, err := b.ReadLine()
- if err != nil {
- break
- }
- buf = append(buf, bytes...)
- if isPrefix {
- continue
- }
-
- // Get command
- var cmd tg.ClientCommand
- err = json.Unmarshal(buf, &cmd)
- if err != nil {
- log.Printf("[handleClient] Can't parse JSON: %s\r\n", err.Error())
- log.Printf("%s\n", string(buf))
- continue
- }
-
- // Empty buffer
- buf = []byte{}
-
- executeClientCommand(cmd, c)
- }
- removeCon(c)
-}
-
-func removeCon(c net.Conn) {
- for i, con := range clients {
- if c == con {
- clients = append(clients[:i], clients[i+1:]...)
- }
- }
-}
-
-func broadcast(message string) {
- for _, c := range clients {
- _, err := fmt.Fprintln(c, message)
- if err != nil {
- removeCon(c)
- }
- }
-}
diff --git a/broker/main.go b/broker/main.go
deleted file mode 100644
index df2469e..0000000
--- a/broker/main.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "flag"
- "log"
- "net/http"
- "os"
-)
-
-// The Config data (parsed from JSON)
-type Config struct {
- BindServer string /* Address:Port to bind for Telegram */
- BindClients string /* Address:Port to bind for clients */
- Token string /* Telegram bot token */
- BaseURL string /* Base URL for webhook */
- WebhookURL string /* Webhook URL */
-}
-
-func assert(err error) {
- if err != nil {
- panic(err)
- }
-}
-
-var api *Telegram
-
-func main() {
- cfgpath := flag.String("config", "config.json", "Path to configuration file")
- flag.Parse()
-
- file, err := os.Open(*cfgpath)
- assert(err)
-
- var config Config
- err = json.NewDecoder(file).Decode(&config)
- assert(err)
-
- // Create Telegram API object
- api = mkAPI(config.Token)
-
- // Setup webhook handler
- go func() {
- log.Println("Starting webserver..")
- http.HandleFunc(config.WebhookURL, webhook)
- err := http.ListenAndServe(config.BindServer, nil)
- assert(err)
- }()
-
- // Register webhook @ Telegram
- log.Println("Registering webhook..")
- api.SetWebhook(config.BaseURL + config.WebhookURL)
-
- // Create server for clients
- log.Println("Starting clients server..")
- startClientsServer(config.BindClients)
-}
diff --git a/broker/telegram.go b/broker/telegram.go
deleted file mode 100644
index cafcc03..0000000
--- a/broker/telegram.go
+++ /dev/null
@@ -1,220 +0,0 @@
-package main
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "log"
- "mime/multipart"
- "net"
- "net/http"
- "net/url"
- "strconv"
-
- "github.com/hamcha/clessy/tg"
-)
-
-// APIEndpoint is Telegram's current Bot API base url endpoint
-const APIEndpoint = "https://api.telegram.org/"
-
-// Telegram is the API client for the Telegram Bot API
-type Telegram struct {
- Token string
-}
-
-// mkAPI creates a Telegram instance from a Bot API token
-func mkAPI(token string) *Telegram {
- tg := new(Telegram)
- tg.Token = token
- return tg
-}
-
-// SetWebhook sets the webhook address so that Telegram knows where to send updates
-func (t Telegram) SetWebhook(webhook string) {
- resp, err := http.PostForm(t.apiURL("setWebhook"), url.Values{"url": {webhook}})
- if !checkerr("SetWebhook/http.PostForm", err) {
- defer resp.Body.Close()
- var result tg.APIResponse
- err = json.NewDecoder(resp.Body).Decode(&result)
- if err != nil {
- log.Println("[SetWebhook] Could not read reply: " + err.Error())
- return
- }
- if result.Ok {
- log.Println("Webhook successfully set!")
- } else {
- log.Printf("[SetWebhook] Error setting webhook (errcode %d): %s\n", *(result.ErrCode), *(result.Description))
- panic(errors.New("Cannot set webhook"))
- }
- }
-}
-
-// SendTextMessage sends an HTML-styled text message to a specified chat
-func (t Telegram) SendTextMessage(data tg.ClientTextMessageData) {
- postdata := url.Values{
- "chat_id": {strconv.FormatInt(data.ChatID, 10)},
- "text": {data.Text},
- "parse_mode": {"HTML"},
- }
- if data.ReplyID != nil {
- postdata["reply_to_message_id"] = []string{strconv.FormatInt(*(data.ReplyID), 10)}
- }
-
- _, err := http.PostForm(t.apiURL("sendMessage"), postdata)
- checkerr("SendTextMessage/http.PostForm", err)
-}
-
-func (t Telegram) SendPhoto(data tg.ClientPhotoData) {
- // Decode photo from b64
- photolen := base64.StdEncoding.DecodedLen(len(data.Bytes))
- photobytes := make([]byte, photolen)
- decoded, err := base64.StdEncoding.Decode(photobytes, []byte(data.Bytes))
- if checkerr("SendPhoto/base64.Decode", err) {
- return
- }
-
- // Write file into multipart buffer
- body := new(bytes.Buffer)
- writer := multipart.NewWriter(body)
- part, err := writer.CreateFormFile("photo", data.Filename)
- if checkerr("SendPhoto/multipart.CreateFormFile", err) {
- return
- }
- part.Write(photobytes[0:decoded])
-
- // Write other fields
- writer.WriteField("chat_id", strconv.FormatInt(data.ChatID, 10))
-
- if data.ReplyID != nil {
- writer.WriteField("reply_to_message_id", strconv.FormatInt(*data.ReplyID, 10))
- }
-
- if data.Caption != "" {
- writer.WriteField("caption", data.Caption)
- }
-
- err = writer.Close()
- if checkerr("SendPhoto/writer.Close", err) {
- return
- }
-
- // Create HTTP client and execute request
- client := &http.Client{}
- req, err := http.NewRequest("POST", t.apiURL("sendPhoto"), body)
- if checkerr("SendPhoto/http.NewRequest", err) {
- return
- }
-
- req.Header.Add("Content-Type", writer.FormDataContentType())
-
- _, err = client.Do(req)
- checkerr("SendPhoto/http.Do", err)
-}
-
-func (t Telegram) ForwardMessage(data tg.ClientForwardMessageData) {
- postdata := url.Values{
- "chat_id": {strconv.FormatInt(data.ChatID, 10)},
- "from_chat_id": {strconv.FormatInt(data.FromChatID, 10)},
- "message_id": {strconv.FormatInt(data.MessageID, 10)},
- }
-
- _, err := http.PostForm(t.apiURL("forwardMessage"), postdata)
- checkerr("ForwardMessage/http.PostForm", err)
-}
-
-func (t Telegram) SendChatAction(data tg.ClientChatActionData) {
- postdata := url.Values{
- "chat_id": {strconv.FormatInt(data.ChatID, 10)},
- "action": {string(data.Action)},
- }
-
- _, err := http.PostForm(t.apiURL("sendChatAction"), postdata)
- checkerr("SendChatAction/http.PostForm", err)
-}
-
-// GetFile sends a "getFile" API call to Telegram's servers and fetches the file
-// specified afterward. The file will be then send back to the client that requested it
-// with the specified callback id.
-func (t Telegram) GetFile(data tg.FileRequestData, client net.Conn, callback int) {
- fail := func(msg string) {
- errmsg, _ := json.Marshal(tg.BrokerUpdate{
- Type: tg.BError,
- Error: &msg,
- Callback: &callback,
- })
- fmt.Fprintln(client, string(errmsg))
- }
-
- postdata := url.Values{
- "file_id": {data.FileID},
- }
- resp, err := http.PostForm(t.apiURL("getFile"), postdata)
- if checkerr("GetFile/post", err) {
- fail("Server didn't like my request")
- return
- }
- defer resp.Body.Close()
-
- var filespecs = struct {
- Ok bool `json:"ok"`
- Result *tg.APIFile `json:"result,omitempty"`
- }{}
- err = json.NewDecoder(resp.Body).Decode(&filespecs)
- if checkerr("GetFile/json.Decode", err) {
- fail("Server sent garbage (or error)")
- return
- }
- if filespecs.Result == nil {
- fail("Server didn't send a file info, does the file exist?")
- return
- }
- result := *filespecs.Result
-
- path := APIEndpoint + "file/bot" + t.Token + "/" + *result.Path
- fileresp, err := http.Get(path)
- if checkerr("GetFile/get", err) {
- fail("Could not retrieve file from Telegram's servers")
- return
- }
- defer fileresp.Body.Close()
-
- rawdata, err := ioutil.ReadAll(fileresp.Body)
- if checkerr("GetFile/ioutil.ReadAll", err) {
- fail("Could not read file data")
- return
- }
-
- rawlen := len(rawdata)
- if rawlen != *result.Size {
- // ???
- log.Printf("[GetFile] WARN ?? Downloaded file does not match provided filesize: %d != %d\n", rawlen, *result.Size)
- }
- b64data := base64.StdEncoding.EncodeToString(rawdata)
-
- clientmsg, err := json.Marshal(tg.BrokerUpdate{
- Type: tg.BFile,
- Bytes: &b64data,
- Callback: &callback,
- })
- if checkerr("GetFile/json.Marshal", err) {
- fail("Could not serialize reply JSON")
- return
- }
-
- fmt.Fprintln(client, string(clientmsg))
-}
-
-func (t Telegram) apiURL(method string) string {
- return APIEndpoint + "bot" + t.Token + "/" + method
-}
-
-func checkerr(method string, err error) bool {
- if err != nil {
- log.Printf("[%s] Error: %s\n", method, err.Error())
- return true
- }
- return false
-}
diff --git a/broker/webhook.go b/broker/webhook.go
deleted file mode 100644
index 8e999d1..0000000
--- a/broker/webhook.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "log"
- "net/http"
-
- "github.com/hamcha/clessy/tg"
-)
-
-func webhook(rw http.ResponseWriter, req *http.Request) {
- defer req.Body.Close()
-
- // Re-encode request to ensure conformity
- var update tg.APIUpdate
- err := json.NewDecoder(req.Body).Decode(&update)
- if err != nil {
- log.Println("[webhook] Received incorrect request: " + err.Error())
- return
- }
-
- data, err := json.Marshal(tg.BrokerUpdate{
- Type: tg.BMessage,
- Message: &(update.Message),
- Callback: nil,
- })
- if err != nil {
- log.Println("[webhook] Cannot re-encode json (??) : " + err.Error())
- return
- }
-
- broadcast(string(data))
-}
diff --git a/config.json.sample b/config.json.sample
deleted file mode 100644
index da4887c..0000000
--- a/config.json.sample
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "BindServer" : ":7313",
- "BindClients": "127.0.0.1:7314",
- "Token" : "Bot token here",
- "BaseURL" : "https://my.bot.host",
- "WebhookURL" : "/secret_url_here"
-}
\ No newline at end of file
diff --git a/friday/main.go b/friday/main.go
index 01bc969..a95d880 100644
--- a/friday/main.go
+++ b/friday/main.go
@@ -10,7 +10,7 @@ import (
"strconv"
"strings"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
const KYMURL = "http://knowyourmeme.com/memes/it-s-finally-a-friday/photos/page/2"
diff --git a/mods/dantes.go b/mods-toupdate/dantes.go
similarity index 98%
rename from mods/dantes.go
rename to mods-toupdate/dantes.go
index 9af4a7b..6cdf22b 100644
--- a/mods/dantes.go
+++ b/mods-toupdate/dantes.go
@@ -4,7 +4,7 @@ import (
"math/rand"
"strings"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
var dantes_frasiacaso = []string{
diff --git a/mods-toupdate/roll.go b/mods-toupdate/roll.go
new file mode 100644
index 0000000..11e8294
--- /dev/null
+++ b/mods-toupdate/roll.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "strings"
+
+ "github.com/hamcha/tg"
+)
+
+func roll(broker *tg.Broker, update tg.APIMessage) {
+ if isCommand(update, "roll") {
+ parts := strings.Split(*(update.Text), " ")
+ if len(parts) < 2 {
+ broker.SendTextMessage(update.Chat, "Sintassi\n/roll cosa1 [cosa2] ..\n\nCose supportate\nNumero intero casuale (es. 300, 10-20, 34-100)\nLancio di dadi (es. d6, 2d20, 100d12+10)\nUtente casuale (\"user\")", &update.MessageID)
+ return
+ }
+ }
+}
+
+func rolltoken(token string) {
+
+}
diff --git a/mods/talk.go b/mods-toupdate/talk.go
similarity index 99%
rename from mods/talk.go
rename to mods-toupdate/talk.go
index 3fb4205..c0099c8 100644
--- a/mods/talk.go
+++ b/mods-toupdate/talk.go
@@ -11,7 +11,7 @@ import (
"strings"
"time"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
type QRequest struct {
diff --git a/mods/macro.go b/mods/macro.go
index 1993cdf..de7632c 100644
--- a/mods/macro.go
+++ b/mods/macro.go
@@ -8,7 +8,7 @@ import (
"strings"
"time"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
type Macro struct {
diff --git a/mods/main.go b/mods/main.go
index 3c333bd..64b0b4e 100644
--- a/mods/main.go
+++ b/mods/main.go
@@ -8,7 +8,7 @@ import (
"strings"
"time"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
type Mod struct {
@@ -47,10 +47,12 @@ var mods = map[string]Mod{
OnInit: proverbio_init,
OnMessage: proverbio_message,
},
- "talk": {
- OnInit: talk_init,
- OnMessage: talk_message,
- },
+ /*
+ "talk": {
+ OnInit: inittalk,
+ OnMessage: talk,
+ },
+ */
"stt": {
OnInit: stt_init,
OnMessage: stt_message,
diff --git a/mods/memegen.go b/mods/memegen.go
index b95823f..3d894e8 100644
--- a/mods/memegen.go
+++ b/mods/memegen.go
@@ -13,7 +13,7 @@ import (
"strings"
"github.com/golang/freetype"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dimg"
)
diff --git a/mods/metafora.go b/mods/metafora.go
index da6b117..5fd83fb 100644
--- a/mods/metafora.go
+++ b/mods/metafora.go
@@ -3,7 +3,7 @@ package main
import (
"math/rand"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
var metaactions = []string{
diff --git a/mods/proverbio.go b/mods/proverbio.go
index e263180..28e79b3 100644
--- a/mods/proverbio.go
+++ b/mods/proverbio.go
@@ -8,7 +8,7 @@ import (
"log"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
type ProverbioData struct {
diff --git a/mods/remind.go b/mods/remind.go
index 3665a00..6b08f13 100644
--- a/mods/remind.go
+++ b/mods/remind.go
@@ -10,7 +10,7 @@ import (
"time"
"unicode"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
var remindpath *string
diff --git a/mods/search.go b/mods/search.go
index 70c2750..f1d055a 100644
--- a/mods/search.go
+++ b/mods/search.go
@@ -9,7 +9,7 @@ import (
"net/url"
"strings"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
type SearchResult struct {
diff --git a/mods/snapchat.go b/mods/snapchat.go
index 4b134ef..f6d4e1a 100644
--- a/mods/snapchat.go
+++ b/mods/snapchat.go
@@ -18,7 +18,7 @@ import (
"time"
"github.com/golang/freetype"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dimg"
)
diff --git a/mods/stt.go b/mods/stt.go
index 6553e6f..5ced77a 100644
--- a/mods/stt.go
+++ b/mods/stt.go
@@ -8,7 +8,7 @@ import (
"encoding/base64"
speech "cloud.google.com/go/speech/apiv1"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
"google.golang.org/api/option"
speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1"
)
diff --git a/mods/unsplash.go b/mods/unsplash.go
index 9162263..1ff84f2 100644
--- a/mods/unsplash.go
+++ b/mods/unsplash.go
@@ -13,7 +13,7 @@ import (
"strings"
"github.com/golang/freetype"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
"github.com/llgcode/draw2d"
"github.com/llgcode/draw2d/draw2dimg"
diff --git a/mods/viaggi.go b/mods/viaggi.go
index 4127c57..ff358c0 100644
--- a/mods/viaggi.go
+++ b/mods/viaggi.go
@@ -10,7 +10,7 @@ import (
"strconv"
"strings"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
const viaggiurl = "http://free.rome2rio.com/api/1.2/json/Search?key=X5JMLHNc&languageCode=IT¤cyCode=EUR"
diff --git a/mspa/main.go b/mspa/main.go
index 85ef8fa..dd5aada 100644
--- a/mspa/main.go
+++ b/mspa/main.go
@@ -9,7 +9,7 @@ import (
"strings"
"time"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
func assert(err error) {
diff --git a/stats/main.go b/stats/main.go
index a71d1b3..6a39754 100644
--- a/stats/main.go
+++ b/stats/main.go
@@ -4,7 +4,7 @@ import (
"flag"
"github.com/boltdb/bolt"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
func assert(err error) {
@@ -42,6 +42,5 @@ func main() {
go startWebServer(*webBind)
- _, err = tg.CreateBrokerClient(*brokerAddr, process)
- assert(err)
+ assert(tg.CreateBrokerClient(*brokerAddr, process))
}
diff --git a/stats/stats.go b/stats/stats.go
index fcfc53b..1470224 100644
--- a/stats/stats.go
+++ b/stats/stats.go
@@ -9,7 +9,7 @@ import (
"time"
"github.com/boltdb/bolt"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
const (
diff --git a/stats/users.go b/stats/users.go
index 444fad6..7bd2744 100644
--- a/stats/users.go
+++ b/stats/users.go
@@ -5,7 +5,7 @@ import (
"strings"
"github.com/boltdb/bolt"
- "github.com/hamcha/clessy/tg"
+ "github.com/hamcha/tg"
)
var users map[string]string
diff --git a/tg/api.go b/tg/api.go
deleted file mode 100644
index 274d291..0000000
--- a/tg/api.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package tg
-
-// APIUser represents the "User" JSON structure
-type APIUser struct {
- UserID int64 `json:"id"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name,omitempty"`
- Username string `json:"username,omitempty"`
-}
-
-// ChatType defines the type of chat
-type ChatType string
-
-const (
- // ChatTypePrivate is a private chat (between user and bot)
- ChatTypePrivate ChatType = "private"
-
- // ChatTypeGroup is a group chat (<100 members)
- ChatTypeGroup ChatType = "group"
-
- // ChatTypeSupergroup is a supergroup chat (>=100 members)
- ChatTypeSupergroup ChatType = "supergroup"
-
- // ChatTypeChannel is a channel (Read-only)
- ChatTypeChannel ChatType = "channel"
-)
-
-// APIChat represents the "Chat" JSON structure
-type APIChat struct {
- ChatID int64 `json:"id"`
- Type ChatType `json:"type"`
- Title *string `json:"title,omitempty"`
- Username *string `json:"username,omitempty"`
- FirstName *string `json:"first_name,omitempty"`
- LastName *string `json:"last_name,omitempty"`
-}
-
-// APIMessage represents the "Message" JSON structure
-type APIMessage struct {
- MessageID int64 `json:"message_id"`
- User APIUser `json:"from"`
- Time int64 `json:"date"`
- Chat *APIChat `json:"chat"`
- FwdUser *APIUpdate `json:"forward_from,omitempty"`
- FwdTime *int `json:"forward_date,omitempty"`
- ReplyTo *APIMessage `json:"reply_to_message,omitempty"`
- Text *string `json:"text,omitempty"`
- Audio *APIAudio `json:"audio,omitempty"`
- Document *APIDocument `json:"document,omitempty"`
- Photo []APIPhotoSize `json:"photo,omitempty"`
- Sticker *APISticker `json:"sticker,omitempty"`
- Video *APIVideo `json:"video,omitempty"`
- Voice *APIVoice `json:"voice,omitempty"`
- Caption *string `json:"caption,omitempty"`
- Contact *APIContact `json:"contact,omitempty"`
- Location *APILocation `json:"location,omitempty"`
- NewUser *APIUser `json:"new_chat_partecipant,omitempty"`
- LeftUser *APIUser `json:"left_chat_partecipant,omitempty"`
- PhotoDeleted *bool `json:"delete_chat_photo,omitempty"`
- GroupCreated *bool `json:"group_chat_created,omitempty"`
- SupergroupCreated *bool `json:"supergroup_chat_created,omitempty"`
- ChannelCreated *bool `json:"channel_chat_created,omitempty"`
- GroupToSuper *int64 `json:"migrate_to_chat_id,omitempty"`
- GroupFromSuper *int64 `json:"migrate_from_chat_id,omitempty"`
-}
-
-// APIPhotoSize represents the "PhotoSize" JSON structure
-type APIPhotoSize struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APIAudio represents the "Audio" JSON structure
-type APIAudio struct {
- FileID string `json:"file_id"`
- Duration int `json:"duration"`
- Performer *string `json:"performer,omitempty"`
- Title *string `json:"title,omitempty"`
- MimeType *string `json:"mime_type,omitempty"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APIDocument represents the "Document" JSON structure
-type APIDocument struct {
- FileID string `json:"file_id"`
- Thumbnail *APIPhotoSize `json:"thumb,omitempty"`
- Filename string `json:"file_name"`
- MimeType *string `json:"mime_type,omitempty"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APISticker represents the "Sticker" JSON structure
-type APISticker struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- Thumbnail *APIPhotoSize `json:"thumb,omitempty"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APIVideo represents the "Video" JSON structure
-type APIVideo struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- Duration int `json:"duration"`
- Thumbnail *APIPhotoSize `json:"thumb,omitempty"`
- MimeType *string `json:"mime_type,omitempty"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APIVoice represents the "Voice" JSON structure
-type APIVoice struct {
- FileID string `json:"file_id"`
- Duration int `json:"duration"`
- MimeType *string `json:"mime_type,omitempty"`
- FileSize *int `json:"file_size,omitempty"`
-}
-
-// APIContact represents the "Contact" JSON structure
-type APIContact struct {
- PhoneNumber string `json:"phone_number"`
- FirstName string `json:"first_name"`
- LastName *string `json:"last_name,omitempty"`
- UserID *int64 `json:"user_id,omitempty"`
-}
-
-// APILocation represents the "Location" JSON structure
-type APILocation struct {
- Longitude float64 `json:"longitude"`
- Latitude float64 `json:"latitude"`
-}
-
-// APIUpdate represents the "Update" JSON structure
-type APIUpdate struct {
- UpdateID int64 `json:"update_id"`
- Message APIMessage `json:"message"`
-}
-
-// APIFile represents the "File" JSON structure
-type APIFile struct {
- FileID string `json:"file_id"`
- Size *int `json:"file_size,omitempty"`
- Path *string `json:"file_path,omitempty"`
-}
-
-// APIResponse represents a response from the Telegram API
-type APIResponse struct {
- Ok bool `json:"ok"`
- ErrCode *int `json:"error_code,omitempty"`
- Description *string `json:"description,omitempty"`
-}
diff --git a/tg/broker.go b/tg/broker.go
deleted file mode 100644
index 8ed3e3e..0000000
--- a/tg/broker.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package tg
-
-import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- "log"
- "net"
-)
-
-// Broker is a broker connection handler with callback management functions
-type Broker struct {
- Socket net.Conn
- Callbacks []BrokerCallback
-
- cbFree int
-}
-
-// ConnectToBroker creates a Broker connection
-func ConnectToBroker(brokerAddr string) (*Broker, error) {
- sock, err := net.Dial("tcp", brokerAddr)
- if err != nil {
- return nil, err
- }
-
- broker := new(Broker)
- broker.Socket = sock
- broker.Callbacks = make([]BrokerCallback, 0)
- broker.cbFree = 0
- return broker, nil
-}
-
-// Close closes a broker connection
-func (b *Broker) Close() {
- b.Socket.Close()
-}
-
-// SendTextMessage sends a HTML-styles text message to a chat.
-// A reply_to message ID can be specified as optional parameter.
-func (b *Broker) SendTextMessage(chat *APIChat, text string, original *int64) {
- b.sendCmd(ClientCommand{
- Type: CmdSendTextMessage,
- TextMessageData: &ClientTextMessageData{
- Text: text,
- ChatID: chat.ChatID,
- ReplyID: original,
- },
- })
-}
-
-// SendPhoto sends a photo with an optional caption to a chat.
-// A reply_to message ID can be specified as optional parameter.
-func (b *Broker) SendPhoto(chat *APIChat, data []byte, filename string, caption string, original *int64) {
- b.sendCmd(ClientCommand{
- Type: CmdSendPhoto,
- PhotoData: &ClientPhotoData{
- ChatID: chat.ChatID,
- Filename: filename,
- Bytes: base64.StdEncoding.EncodeToString(data),
- Caption: caption,
- ReplyID: original,
- },
- })
-}
-
-// ForwardMessage forwards a message between chats.
-func (b *Broker) ForwardMessage(chat *APIChat, message APIMessage) {
- b.sendCmd(ClientCommand{
- Type: CmdForwardMessage,
- ForwardMessageData: &ClientForwardMessageData{
- ChatID: chat.ChatID,
- FromChatID: message.Chat.ChatID,
- MessageID: message.MessageID,
- },
- })
-}
-
-// SendChatAction sets a chat action for 5 seconds or less (canceled at first message sent)
-func (b *Broker) SendChatAction(chat *APIChat, action ChatAction) {
- b.sendCmd(ClientCommand{
- Type: CmdSendChatAction,
- ChatActionData: &ClientChatActionData{
- ChatID: chat.ChatID,
- Action: action,
- },
- })
-}
-
-// GetFile sends a file retrieval request to the Broker.
-// This function is asynchronous as data will be delivered to the given callback.
-func (b *Broker) GetFile(fileID string, fn BrokerCallback) int {
- cid := b.RegisterCallback(fn)
- b.sendCmd(ClientCommand{
- Type: CmdGetFile,
- FileRequestData: &FileRequestData{
- FileID: fileID,
- },
- Callback: &cid,
- })
- return cid
-}
-
-// RegisterCallback assigns a callback ID to the given callback and puts it on the callback list.
-// This function should never be called by clients.
-func (b *Broker) RegisterCallback(fn BrokerCallback) int {
- cblen := len(b.Callbacks)
- // List is full, append to end
- if b.cbFree == cblen {
- b.Callbacks = append(b.Callbacks, fn)
- b.cbFree++
- return cblen
- }
- // List is not full, use empty slot and find next one
- id := b.cbFree
- b.Callbacks[id] = fn
- next := b.cbFree + 1
- for ; next < cblen; next++ {
- if b.Callbacks[next] == nil {
- break
- }
- }
- b.cbFree = next
- return id
-}
-
-// RemoveCallback removes a callback from the callback list by ID.
-// This function should never be called by clients.
-func (b *Broker) RemoveCallback(id int) {
- b.Callbacks[id] = nil
- if id < b.cbFree {
- b.cbFree = id
- }
- b.resizeCbArray()
-}
-
-// SpliceCallback retrieves a callback by ID and removes it from the list.
-// This function should never be called by clients.
-func (b *Broker) SpliceCallback(id int) BrokerCallback {
- defer b.RemoveCallback(id)
- return b.Callbacks[id]
-}
-
-func (b *Broker) sendCmd(cmd ClientCommand) {
- data, err := json.Marshal(cmd)
- if err != nil {
- log.Printf("[sendCmd] JSON Encode error: %s\n", err.Error())
- }
- fmt.Fprintln(b.Socket, string(data))
-}
-
-func (b *Broker) resizeCbArray() {
- var i int
- cut := false
- for i = len(b.Callbacks); i > 0; i-- {
- if b.Callbacks[i-1] != nil {
- break
- }
- cut = true
- }
- if cut {
- b.Callbacks = b.Callbacks[0:i]
- if b.cbFree > i {
- b.cbFree = i
- }
- }
-}
diff --git a/tg/client.go b/tg/client.go
deleted file mode 100644
index af3002b..0000000
--- a/tg/client.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package tg
-
-import (
- "bufio"
- "encoding/json"
- "io"
- "log"
-)
-
-// UpdateHandler is an update handler for webhook updates
-type UpdateHandler func(broker *Broker, message APIMessage)
-
-// BrokerCallback is a callback for broker responses to client requests
-type BrokerCallback func(broker *Broker, update BrokerUpdate)
-
-// CreateBrokerClient creates a connection to a broker and sends all webhook updates to a given function.
-// This is the intended way to create clients, please refer to examples for how to make a simple client.
-func CreateBrokerClient(brokerAddr string, updateFn UpdateHandler) error {
- broker, err := ConnectToBroker(brokerAddr)
- if err != nil {
- return err
- }
- defer broker.Close()
-
- return RunBrokerClient(broker, updateFn)
-}
-
-// RunBrokerClient is a slimmer version of CreateBrokerClient for who wants to keep its own broker connection
-func RunBrokerClient(broker *Broker, updateFn UpdateHandler) error {
- in := bufio.NewReader(broker.Socket)
- var buf []byte
- for {
- bytes, isPrefix, err := in.ReadLine()
- if err != nil {
- break
- }
- buf = append(buf, bytes...)
-
- if isPrefix {
- continue
- }
-
- var update BrokerUpdate
- err = json.Unmarshal(buf, &update)
- if err != nil {
- log.Printf("[tg - CreateBrokerClient] ERROR reading JSON: %s\r\n", err.Error())
- log.Printf("%s\n", string(buf))
- continue
- }
-
- if update.Callback == nil {
- // It's a generic message: dispatch to UpdateHandler
- go updateFn(broker, *(update.Message))
- } else {
- // It's a response to a request: retrieve callback and call it
- go broker.SpliceCallback(*(update.Callback))(broker, update)
- }
-
- // Empty buffer
- buf = []byte{}
- }
-
- return io.EOF
-}
diff --git a/tg/client_test.go b/tg/client_test.go
deleted file mode 100644
index 5cd4dd9..0000000
--- a/tg/client_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package tg_test
-
-// This example creates a basic client that connects to a broker and checks for message containing greetings.
-// If it finds a greeting message it will greet back the user (using the reply_to parameter)
-func ExampleCreateBrokerClient() {
- CreateBrokerClient("localhost:7314", func(broker *Broker, message APIMessage) {
- // Check if it's a text message
- if message.Text != nil {
- // Check that it's a greeting
- if *(message.Text) == "hello" || *(message.Text) == "hi" {
- // Reply with a greeting!
- broker.SendTextMessage(message.Chat, "Hello!", message.MessageID)
- }
- }
- })
-}
diff --git a/tg/command.go b/tg/command.go
deleted file mode 100644
index 021108c..0000000
--- a/tg/command.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package tg
-
-// BrokerUpdateType distinguishes update types coming from the broker
-type BrokerUpdateType string
-
-const (
- // BMessage is a message update (mostly webhook updates)
- BMessage BrokerUpdateType = "message"
-
- // BFile is a file retrieval response update
- BFile BrokerUpdateType = "file"
-
- // BError is an error the broker occurred while fulfilling a request
- BError BrokerUpdateType = "error"
-)
-
-// BrokerUpdate is what is sent by the broker as update
-type BrokerUpdate struct {
- Type BrokerUpdateType
- Callback *int `json:",omitempty"`
- Error *string `json:",omitempty"`
- Message *APIMessage `json:",omitempty"`
- Bytes *string `json:",omitempty"`
-}
-
-// ClientCommandType distinguishes requests sent by clients to the broker
-type ClientCommandType string
-
-const (
- // CmdSendTextMessage requests the broker to send a text message to a chat
- CmdSendTextMessage ClientCommandType = "sendText"
-
- // CmdSendPhoto requests the broker to send a photo to a chat
- CmdSendPhoto ClientCommandType = "sendPhoto"
-
- // CmdForwardMessage requests the broker to forward a message between chats
- CmdForwardMessage ClientCommandType = "forwardMessage"
-
- // CmdGetFile requests the broker to get a file from Telegram
- CmdGetFile ClientCommandType = "getFile"
-
- // CmdSendChatAction requests the broker to set a chat action (typing, etc.)
- CmdSendChatAction ClientCommandType = "sendChatAction"
-)
-
-// ClientTextMessageData is the required data for a CmdSendTextMessage request
-type ClientTextMessageData struct {
- ChatID int64
- Text string
- ReplyID *int64 `json:",omitempty"`
-}
-
-// ClientPhotoData is the required data for a CmdSendPhoto request
-type ClientPhotoData struct {
- ChatID int64
- Bytes string
- Filename string
- Caption string `json:",omitempty"`
- ReplyID *int64 `json:",omitempty"`
-}
-
-// ClientForwardMessageData is the required data for a CmdForwardMessage request
-type ClientForwardMessageData struct {
- ChatID int64
- FromChatID int64
- MessageID int64
-}
-
-// ClientChatActionData is the required data for a CmdSendChatAction request
-type ClientChatActionData struct {
- ChatID int64
- Action ChatAction
-}
-
-// ChatAction is the action name for CmdSendChatAction requests
-type ChatAction string
-
-const (
- ActionTyping ChatAction = "typing"
- ActionUploadingPhoto ChatAction = "upload_photo"
- ActionRecordingVideo ChatAction = "record_video"
- ActionUploadingVideo ChatAction = "upload_video"
- ActionRecordingAudio ChatAction = "record_audio"
- ActionUploadingAudio ChatAction = "upload_audio"
- ActionUploadingDocument ChatAction = "upload_document"
- ActionFindingLocation ChatAction = "find_location"
-)
-
-// FileRequestData is the required data for a CmdGetFile request
-type FileRequestData struct {
- FileID string
-}
-
-// ClientCommand is a request sent by clients to the broker
-type ClientCommand struct {
- Type ClientCommandType
- TextMessageData *ClientTextMessageData `json:",omitempty"`
- PhotoData *ClientPhotoData `json:",omitempty"`
- ForwardMessageData *ClientForwardMessageData `json:",omitempty"`
- ChatActionData *ClientChatActionData `json:",omitempty"`
- FileRequestData *FileRequestData `json:",omitempty"`
- Callback *int `json:",omitempty"`
-}