Archived
very first iteration
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
// WGoSlackBot
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 by Daniel Aberger
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"dev.ixab.de/WGSWATBP/WGoSlackBot/modules"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sayCh chan modules.Payload
|
||||||
|
webhookPort = flag.String("webhookport", "61321", "Webhook port")
|
||||||
|
slackHook = flag.String("slackhook", "https://hooks.slack.com/services/", "Slack webhook URL")
|
||||||
|
params = flag.String("params", "", "Module params")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sayCh = make(chan modules.Payload, 1024)
|
||||||
|
modules.Init(sayCh, *params)
|
||||||
|
|
||||||
|
go webhook()
|
||||||
|
|
||||||
|
for {
|
||||||
|
sendPayload(<-sayCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func webhook() {
|
||||||
|
http.HandleFunc("/hook", webhookHandler)
|
||||||
|
log.Fatal(http.ListenAndServe(":"+*webhookPort, nil))
|
||||||
|
}
|
||||||
|
func webhookHandler(w http.ResponseWriter, req *http.Request) {
|
||||||
|
req.ParseForm()
|
||||||
|
whp := modules.WebhookPayload{
|
||||||
|
Token: req.Form.Get("token"),
|
||||||
|
TeamID: req.Form.Get("team_id"),
|
||||||
|
TeamDomain: req.Form.Get("team_domain"),
|
||||||
|
ServiceID: req.Form.Get("service_id"),
|
||||||
|
ChannelID: req.Form.Get("channel_id"),
|
||||||
|
ChannelName: req.Form.Get("channel_name"),
|
||||||
|
Timestamp: req.Form.Get("timestamp"),
|
||||||
|
UserID: req.Form.Get("user_id"),
|
||||||
|
UserName: req.Form.Get("user_name"),
|
||||||
|
Text: req.Form.Get("text"),
|
||||||
|
TriggerWord: req.Form.Get("trigger_word"),
|
||||||
|
}
|
||||||
|
modules.HandleMessage(&whp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendPayload(payload modules.Payload) {
|
||||||
|
p, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
}
|
||||||
|
url := *slackHook
|
||||||
|
|
||||||
|
var jsonStr = p
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
||||||
|
req.Header.Set("X-Custom-Header", "myvalue")
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
log.Println("Sent payload. Response Status:", resp.Status)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Payload struct {
|
||||||
|
Channel string `json:"channel"`
|
||||||
|
IconEmoji string `json:"icon_emoji"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookPayload struct {
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
ChannelName string `json:"channel_name"`
|
||||||
|
ServiceID string `json:"service_id"`
|
||||||
|
TeamDomain string `json:"team_domain"`
|
||||||
|
TeamID string `json:"team_id"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
Timestamp string `json:"timestamp"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
TriggerWord string `json:"trigger_word"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
SayCh chan Payload
|
||||||
|
MsgHandlers = make(map[string]func(*WebhookPayload))
|
||||||
|
ModParams = make(map[string]string)
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ch chan Payload, params string) {
|
||||||
|
SayCh = ch
|
||||||
|
for _, param := range strings.Split(params, "!") {
|
||||||
|
kv := strings.Split(param, ":")
|
||||||
|
ModParams[kv[0]] = kv[1]
|
||||||
|
log.Println(kv[0], kv[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleMessage(payload *WebhookPayload) {
|
||||||
|
for _, fn := range MsgHandlers {
|
||||||
|
fn(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
+162
@@ -0,0 +1,162 @@
|
|||||||
|
// ts3.go
|
||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
users = map[string]bool{}
|
||||||
|
host string
|
||||||
|
port string
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
botname string
|
||||||
|
channel string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
MsgHandlers["ts3"] = ts3HandleMessage
|
||||||
|
log.Println("Initializing ts3 module")
|
||||||
|
go setConfig()
|
||||||
|
}
|
||||||
|
func setConfig() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
host = ModParams["tshost"]
|
||||||
|
port = ModParams["tsport"]
|
||||||
|
user = ModParams["tsuser"]
|
||||||
|
pass = ModParams["tspass"]
|
||||||
|
botname = ModParams["tsbotname"]
|
||||||
|
channel = ModParams["tschan"]
|
||||||
|
go loop()
|
||||||
|
}
|
||||||
|
func loop() {
|
||||||
|
for {
|
||||||
|
var err error
|
||||||
|
users, err = getUsers()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
log.Println("Trying again in 60 seconds.")
|
||||||
|
time.Sleep(60 * time.Second)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if channel == "" { // dont spam if no channel is set
|
||||||
|
break
|
||||||
|
}
|
||||||
|
neu, err := getUsers()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
time.Sleep(50 * time.Second)
|
||||||
|
} else {
|
||||||
|
for i, _ := range neu {
|
||||||
|
if users[i] != neu[i] {
|
||||||
|
SayCh <- GeneratePayload(channel, ":poop:", i+" joined TS3.", botname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, _ := range users {
|
||||||
|
if users[i] != neu[i] {
|
||||||
|
SayCh <- GeneratePayload(channel, ":poop:", i+" left TS3.", botname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
users = neu
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func ts3HandleMessage(payload *WebhookPayload) {
|
||||||
|
log.Println("TS3 users requested by " + payload.UserName)
|
||||||
|
users, _ := getUsers()
|
||||||
|
var s string
|
||||||
|
i := 0
|
||||||
|
s += "Current users on TS3 Server:\n"
|
||||||
|
for u, _ := range users {
|
||||||
|
i++
|
||||||
|
s += "- " + u
|
||||||
|
if i != len(users) {
|
||||||
|
s += "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SayCh <- GeneratePayload("@"+payload.UserName, ":poop:", s, botname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUsers() (u map[string]bool, e error) {
|
||||||
|
conn, err := net.Dial("tcp", host+":"+port)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
writer := bufio.NewWriter(conn)
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ { // get rid of banner
|
||||||
|
_, _, err := reader.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "EOF" {
|
||||||
|
log.Println("Connection closed by foreign host.")
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.WriteString("login " + user + " " + pass + "\n")
|
||||||
|
writer.Flush()
|
||||||
|
_, _, err = reader.ReadLine() // get rid of "OK" message
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "EOF" {
|
||||||
|
log.Println("Connection closed by foreign host.")
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteString("use sid=1\n")
|
||||||
|
writer.Flush()
|
||||||
|
_, _, err = reader.ReadLine() // get rid of "OK" message
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "EOF" {
|
||||||
|
log.Println("Connection closed by foreign host.")
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteString("clientlist\n")
|
||||||
|
writer.Flush()
|
||||||
|
line, _, err := reader.ReadLine() // get rid of "OK" message
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "EOF" {
|
||||||
|
log.Println("Connection closed by foreign host.")
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
users_raw := string(line)
|
||||||
|
|
||||||
|
re := regexp.MustCompile("client_nickname=(.*?) ")
|
||||||
|
users_still_raw := re.FindAllString(users_raw, -1)
|
||||||
|
|
||||||
|
for i := range users_still_raw {
|
||||||
|
users_still_raw[i] = strings.Trim(users_still_raw[i], " ")
|
||||||
|
users_still_raw[i] = strings.Replace(users_still_raw[i], "client_nickname=", "", 1)
|
||||||
|
users_still_raw[i] = strings.Replace(users_still_raw[i], "\\s", " ", -1)
|
||||||
|
}
|
||||||
|
users := make([]string, 0)
|
||||||
|
for i := range users_still_raw {
|
||||||
|
if !strings.HasPrefix(users_still_raw[i], "serveradmin from") {
|
||||||
|
users = append(users, users_still_raw[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result := make(map[string]bool)
|
||||||
|
for i := range users {
|
||||||
|
result[users[i]] = true
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
// flokatirc twitch module rewritten for WGoSlackBot
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Daniel Aberger <da@ixab.de>
|
||||||
|
|
||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"dev.ixab.de/WGSWATBP/WGoSlackBot/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TwitchChannelObject struct {
|
||||||
|
_id int `json:"_id"`
|
||||||
|
_links struct {
|
||||||
|
Chat string `json:"chat"`
|
||||||
|
Commercial string `json:"commercial"`
|
||||||
|
Editors string `json:"editors"`
|
||||||
|
Features string `json:"features"`
|
||||||
|
Follows string `json:"follows"`
|
||||||
|
Self string `json:"self"`
|
||||||
|
StreamKey string `json:"stream_key"`
|
||||||
|
Subscriptions string `json:"subscriptions"`
|
||||||
|
Teams string `json:"teams"`
|
||||||
|
Videos string `json:"videos"`
|
||||||
|
} `json:"_links"`
|
||||||
|
Background interface{} `json:"background"`
|
||||||
|
Banner string `json:"banner"`
|
||||||
|
BroadcasterLanguage string `json:"broadcaster_language"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
Delay interface{} `json:"delay"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
Followers int `json:"followers"`
|
||||||
|
Game string `json:"game"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Logo string `json:"logo"`
|
||||||
|
Mature bool `json:"mature"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Partner bool `json:"partner"`
|
||||||
|
ProfileBanner string `json:"profile_banner"`
|
||||||
|
ProfileBannerBackgroundColor string `json:"profile_banner_background_color"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
VideoBanner string `json:"video_banner"`
|
||||||
|
Views int `json:"views"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TwitchStreamObject struct {
|
||||||
|
_links struct {
|
||||||
|
Channel string `json:"channel"`
|
||||||
|
Self string `json:"self"`
|
||||||
|
} `json:"_links"`
|
||||||
|
Stream struct {
|
||||||
|
_id int `json:"_id"`
|
||||||
|
_links struct {
|
||||||
|
Self string `json:"self"`
|
||||||
|
} `json:"_links"`
|
||||||
|
AverageFps float64 `json:"average_fps"`
|
||||||
|
Channel struct {
|
||||||
|
_id int `json:"_id"`
|
||||||
|
_links struct {
|
||||||
|
Chat string `json:"chat"`
|
||||||
|
Commercial string `json:"commercial"`
|
||||||
|
Editors string `json:"editors"`
|
||||||
|
Features string `json:"features"`
|
||||||
|
Follows string `json:"follows"`
|
||||||
|
Self string `json:"self"`
|
||||||
|
StreamKey string `json:"stream_key"`
|
||||||
|
Subscriptions string `json:"subscriptions"`
|
||||||
|
Teams string `json:"teams"`
|
||||||
|
Videos string `json:"videos"`
|
||||||
|
} `json:"_links"`
|
||||||
|
Background interface{} `json:"background"`
|
||||||
|
Banner string `json:"banner"`
|
||||||
|
BroadcasterLanguage string `json:"broadcaster_language"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
Delay interface{} `json:"delay"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
Followers int `json:"followers"`
|
||||||
|
Game string `json:"game"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Logo string `json:"logo"`
|
||||||
|
Mature bool `json:"mature"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Partner bool `json:"partner"`
|
||||||
|
ProfileBanner string `json:"profile_banner"`
|
||||||
|
ProfileBannerBackgroundColor string `json:"profile_banner_background_color"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
VideoBanner string `json:"video_banner"`
|
||||||
|
Views int `json:"views"`
|
||||||
|
} `json:"channel"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
Delay int `json:"delay"`
|
||||||
|
Game string `json:"game"`
|
||||||
|
IsPlaylist bool `json:"is_playlist"`
|
||||||
|
Preview struct {
|
||||||
|
Large string `json:"large"`
|
||||||
|
Medium string `json:"medium"`
|
||||||
|
Small string `json:"small"`
|
||||||
|
Template string `json:"template"`
|
||||||
|
} `json:"preview"`
|
||||||
|
VideoHeight int `json:"video_height"`
|
||||||
|
Viewers int `json:"viewers"`
|
||||||
|
} `json:"stream"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
twitch = map[string]bool{
|
||||||
|
"rocketbeanstv": false,
|
||||||
|
"blizzard": false,
|
||||||
|
"ea": false,
|
||||||
|
"warcraft": false,
|
||||||
|
"starcraft": false,
|
||||||
|
"bobross": false,
|
||||||
|
}
|
||||||
|
twitchapiurlstreams = "https://api.twitch.tv/kraken/streams/"
|
||||||
|
twitchapiurlchannels = "https://api.twitch.tv/kraken/channels/"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
MsgHandlers["twitch"] = twitchHandleMessage
|
||||||
|
log.Println("Initializing twitch module")
|
||||||
|
go pollStreamData()
|
||||||
|
}
|
||||||
|
|
||||||
|
func twitchHandleMessage(payload *WebhookPayload) {
|
||||||
|
tok := strings.Split(payload.Text, " ")
|
||||||
|
if len(tok) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch tok[0] {
|
||||||
|
case "!twitch":
|
||||||
|
switch len(tok) {
|
||||||
|
case 1:
|
||||||
|
onlinestreams := 0
|
||||||
|
for streamname, _ := range twitch {
|
||||||
|
var so TwitchStreamObject
|
||||||
|
var co TwitchChannelObject
|
||||||
|
so = getTwitchStreamObject(streamname)
|
||||||
|
if so.Stream.Game != "" {
|
||||||
|
onlinestreams++
|
||||||
|
co = getTwitchChannelObject(streamname)
|
||||||
|
twitchSendMsg(co, so)
|
||||||
|
twitch[streamname] = true
|
||||||
|
} else {
|
||||||
|
twitch[streamname] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if onlinestreams == 0 {
|
||||||
|
SayCh <- GeneratePayload("@"+payload.UserName, "", "All streams offline", "Twitch_Bot")
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
streamname := tok[1]
|
||||||
|
var so TwitchStreamObject
|
||||||
|
var co TwitchChannelObject
|
||||||
|
so = getTwitchStreamObject(streamname)
|
||||||
|
if so.Stream.Game != "" {
|
||||||
|
co = getTwitchChannelObject(streamname)
|
||||||
|
twitchSendMsg(co, so)
|
||||||
|
} else {
|
||||||
|
SayCh <- GeneratePayload("@"+payload.UserName, "", streamname+" not found or offline", "Twitch_Bot")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollStreamData() {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
for {
|
||||||
|
for streamname, _ := range twitch {
|
||||||
|
var so TwitchStreamObject
|
||||||
|
var co TwitchChannelObject
|
||||||
|
so = getTwitchStreamObject(streamname)
|
||||||
|
if so.Stream.Game != "" && !twitch[streamname] {
|
||||||
|
co = getTwitchChannelObject(streamname)
|
||||||
|
twitchSendMsg(co, so)
|
||||||
|
twitch[streamname] = true
|
||||||
|
} else if so.Stream.Game == "" && twitch[streamname] {
|
||||||
|
twitch[streamname] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(180 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTwitchStreamObject(streamname string) TwitchStreamObject {
|
||||||
|
twsurl := twitchapiurlstreams + streamname
|
||||||
|
var tobj TwitchStreamObject
|
||||||
|
resp, err := http.Get(twsurl)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
} else {
|
||||||
|
reader, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
} else {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
json.Unmarshal(reader, &tobj)
|
||||||
|
return tobj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tobj
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTwitchChannelObject(streamname string) TwitchChannelObject {
|
||||||
|
twcurl := twitchapiurlchannels + streamname
|
||||||
|
var tcobj TwitchChannelObject
|
||||||
|
resp2, err := http.Get(twcurl)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
} else {
|
||||||
|
reader2, err := ioutil.ReadAll(resp2.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
} else {
|
||||||
|
defer resp2.Body.Close()
|
||||||
|
json.Unmarshal(reader2, &tcobj)
|
||||||
|
return tcobj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tcobj
|
||||||
|
}
|
||||||
|
|
||||||
|
func twitchSendMsg(tcobj TwitchChannelObject, tso TwitchStreamObject) {
|
||||||
|
SayCh <- GeneratePayload("#wgs-spam",
|
||||||
|
"",
|
||||||
|
"*"+tso.Stream.Channel.DisplayName+
|
||||||
|
"*\n*Title:* "+tcobj.Status+
|
||||||
|
"\n*Viewers:* "+util.NumberToString(tso.Stream.Viewers, '.')+
|
||||||
|
"\n*Playing:* "+tso.Stream.Game+
|
||||||
|
"\n"+tcobj.URL+"\n",
|
||||||
|
"Twitch_Bot")
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// utility.go
|
||||||
|
package modules
|
||||||
|
|
||||||
|
func GeneratePayload(target string, icon string, text string, botname string) Payload {
|
||||||
|
payload := Payload{
|
||||||
|
Channel: target,
|
||||||
|
IconEmoji: icon,
|
||||||
|
Text: text,
|
||||||
|
Username: botname,
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// vi:ts=4:sts=4:sw=4:noet:tw=72
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToInt(v interface{}) int {
|
||||||
|
switch v.(type) {
|
||||||
|
case int:
|
||||||
|
return v.(int)
|
||||||
|
case float64:
|
||||||
|
return int(v.(float64))
|
||||||
|
case string:
|
||||||
|
ret, _ := strconv.Atoi(v.(string))
|
||||||
|
return ret
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NumberToString(n int, sep rune) string {
|
||||||
|
start := 0
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
s := strconv.Itoa(n)
|
||||||
|
if n < 0 {
|
||||||
|
start = 1
|
||||||
|
buf.WriteByte('-')
|
||||||
|
}
|
||||||
|
l := len(s)
|
||||||
|
ci := 3 - ((l - start) % 3)
|
||||||
|
if ci == 3 {
|
||||||
|
ci = 0
|
||||||
|
}
|
||||||
|
for i := start; i < l; i++ {
|
||||||
|
if ci == 3 {
|
||||||
|
buf.WriteRune(sep)
|
||||||
|
ci = 0
|
||||||
|
}
|
||||||
|
ci++
|
||||||
|
buf.WriteByte(s[i])
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Random(min, max int) int {
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
return rand.Intn(max-min) + min
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user