Adding basic Bot functionality

This commit is contained in:
Andreas Mieke 2020-03-24 15:50:49 +01:00
parent 9101453bb7
commit a2e793a6c3
5 changed files with 141 additions and 14 deletions

View file

@ -3,9 +3,11 @@ package main
import (
"flag"
"log"
"os"
"os/signal"
"git.1750studios.com/ToddShepard/DB640/internal/bot"
"git.1750studios.com/ToddShepard/DB640/internal/config"
"git.1750studios.com/ToddShepard/DB640/internal/twitter"
)
func main() {
@ -15,18 +17,13 @@ func main() {
log.Fatalf("Config file must not be empty!")
}
log.Println("Hello World!")
config.LoadConfig(*cfg)
twitter.Init()
stream, err := twitter.GetStreamForTag("#NationalPuppyDay")
if err != nil {
log.Fatalf("Could not establish twitter stream: %+v", err)
}
bot.Init()
twitter.StreamDemux(stream, showTweet)
}
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
func showTweet(tweet *twitter.Tweet) {
log.Printf("%s\n", tweet.Text)
bot.DeInit()
config.WriteConfig(*cfg)
}

83
internal/bot/bot.go Normal file
View file

@ -0,0 +1,83 @@
package bot
import (
"log"
"strings"
"git.1750studios.com/ToddShepard/DB640/internal/config"
"git.1750studios.com/ToddShepard/DB640/internal/database"
"git.1750studios.com/ToddShepard/DB640/internal/twitter"
"github.com/jinzhu/gorm"
)
var stream *twitter.Stream
// Init initzializes the bot and subscribes the magic hashtag feed
func Init() {
var err error
err = database.Open(config.C.Database.Dialect, config.C.Database.Connection)
if err != nil {
log.Fatalf("could not establish database connection: %+v", err)
}
twitter.Init()
stream, err = twitter.GetStreamForTag(config.C.Twitter.MagicHashtag)
if err != nil {
log.Fatalf("Could not establish twitter stream: %+v", err)
}
twitter.StreamDemux(stream, handleHashtagTweet)
}
// DeInit stops the stream and deinitzializes the bot
func DeInit() {
stream.Stop()
database.Close()
}
func handleHashtagTweet(tweet *twitter.Tweet) {
msg, tags := twitter.GetTextAndHashtags(tweet)
// Ignore retweets
if tweet.RetweetedStatus != nil {
log.Printf("%s: %s - IGNORED (RT)\n", tweet.User.ScreenName, msg)
return
}
// Ignore replys
if tweet.InReplyToStatusID != 0 {
log.Printf("%s: %s - IGNORED (RPLY)\n", tweet.User.ScreenName, msg)
return
}
// Ignore if only magic hashtag is given
if len(tags) < 2 {
log.Printf("%s: %s - IGNORED (<2#)\n", tweet.User.ScreenName, msg)
return
}
log.Printf("%s: %s\n", tweet.User.ScreenName, msg)
go findCodes(tweet)
}
func findCodes(tweet *twitter.Tweet) {
_, tags := twitter.GetTextAndHashtags(tweet)
var betriebsstellen []database.Betriebsstelle
for _, tag := range tags {
code := strings.ReplaceAll(tag.Text, "_", " ")
var bs database.Betriebsstelle
if database.Db.First(&bs, "code = ?", code).Error != gorm.ErrRecordNotFound {
betriebsstellen = append(betriebsstellen, bs)
}
}
sendReply(tweet, betriebsstellen)
}
func sendReply(tweet *twitter.Tweet, betriebsstellen []database.Betriebsstelle) {
var reply string
for _, bs := range betriebsstellen {
reply = reply + bs.Code + ": " + bs.Name + "\n"
}
reply = reply[0 : len(reply)-1]
_, _, err := twitter.SendTweet(reply, tweet)
if err != nil {
log.Printf("Cannot send reply, error: %+v", err)
}
}

View file

@ -12,7 +12,8 @@ import (
// Config main type
type Config struct {
Twitter Twitter
Twitter Twitter
Database Database
}
// Twitter related config
@ -21,6 +22,13 @@ type Twitter struct {
ConsumerSecret string
AccessKey string
AccessSecret string
MagicHashtag string
}
// Database related config
type Database struct {
Dialect string
Connection string
}
// C holds the loaded configuration
@ -32,6 +40,10 @@ func LoadDefaults() {
C.Twitter.AccessSecret = "ACCESSSECRET"
C.Twitter.ConsumerKey = "CONSUMERKEY"
C.Twitter.ConsumerSecret = "CONSUMERSECRET"
C.Twitter.MagicHashtag = "#DB640"
C.Database.Dialect = "sqlite3"
C.Database.Connection = ":memory:"
}
// LoadConfig loads the configuration from given path

View file

@ -18,6 +18,9 @@ func TestWriteConfig(t *testing.T) {
C.Twitter.AccessSecret = "SuperNiceSecret"
C.Twitter.ConsumerKey = "ConsumeMe"
C.Twitter.ConsumerSecret = "EatASecret"
C.Twitter.MagicHashtag = "#notsomagic"
C.Database.Dialect = "somedia"
C.Database.Connection = "conn"
err := WriteConfig(filepath.Join("..", "..", "test", "data", "doesnotexist.toml"))
if err != nil {
t.Errorf("Could not write config, got error: %+v", err)
@ -30,7 +33,13 @@ func TestLoadConfig(t *testing.T) {
if err != nil {
t.Errorf("Cannot read config, error: %+v", err)
}
if C.Twitter.AccessKey != "§OneNiceKey" || C.Twitter.AccessSecret != "SuperNiceSecret" || C.Twitter.ConsumerKey != "ConsumeMe" || C.Twitter.ConsumerSecret != "EatASecret" {
if C.Twitter.AccessKey != "§OneNiceKey" ||
C.Twitter.AccessSecret != "SuperNiceSecret" ||
C.Twitter.ConsumerKey != "ConsumeMe" ||
C.Twitter.ConsumerSecret != "EatASecret" ||
C.Twitter.MagicHashtag != "#notsomagic" ||
C.Database.Dialect != "somedia" ||
C.Database.Connection != "conn" {
t.Errorf("Could not read config, entries wrong")
}
t.Cleanup(CleanupConfigTest)

View file

@ -1,6 +1,8 @@
package twitter
import (
"net/http"
"git.1750studios.com/ToddShepard/DB640/internal/config"
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
@ -12,6 +14,9 @@ var Client *twitter.Client
// Tweet as in twitter.Tweet
type Tweet = twitter.Tweet
// Stream as in twitter.Stream
type Stream = twitter.Stream
// Init initzializes the twitter client
func Init() {
conf := oauth1.NewConfig(config.C.Twitter.ConsumerKey, config.C.Twitter.ConsumerSecret)
@ -36,3 +41,24 @@ func StreamDemux(stream *twitter.Stream, cb func(*Tweet)) {
demux.Tweet = cb
demux.HandleChan(stream.Messages)
}
// SendTweet allows to send a string as tweet (optionally as reply to a specified tweet)
func SendTweet(msg string, replytweet *twitter.Tweet) (*twitter.Tweet, *http.Response, error) {
if replytweet == nil {
// not a reply
return Client.Statuses.Update(msg, nil)
}
// replying
p := twitter.StatusUpdateParams{
InReplyToStatusID: replytweet.ID,
}
return Client.Statuses.Update("@"+replytweet.User.ScreenName+" "+msg, &p)
}
// GetTextAndHashtags returns #tweet text and hashtags for short and extended tweets
func GetTextAndHashtags(tweet *twitter.Tweet) (string, []twitter.HashtagEntity) {
if tweet.ExtendedTweet == nil {
return tweet.Text, tweet.Entities.Hashtags
}
return tweet.ExtendedTweet.FullText, tweet.ExtendedTweet.Entities.Hashtags
}