a reddit/mastodon bot that takes new image posts from https://reddit.com/r/Overwatch_Porn and posts them to a mastodon instance!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
4.4 KiB

package main
import (
"strings"
"log"
"flag"
"os"
"io"
"io/ioutil"
"net/http"
"github.com/McKael/madon"
"github.com/turnage/graw"
"github.com/turnage/graw/reddit"
"github.com/pelletier/go-toml"
)
type Crossposter struct {
bot reddit.Bot
}
type MastoConfig struct {
Instance string
Secret string
Key string
AccessToken string
}
// our logic for the reddit bot that handles each post
func (p *Crossposter) Post(post *reddit.Post) error {
if !post.IsSelf {
log.Println("processing reddit post: ", post.Title)
// check if the link is a direct link
if strings.HasSuffix(post.URL, ".jpg") ||
strings.HasSuffix(post.URL, ".jpeg") ||
strings.HasSuffix(post.URL, ".png") ||
strings.HasSuffix(post.URL, ".gif"){
// download the image
if image, err := DownloadImage(post.URL); err != nil {
if DeleteAfterPost { // delete it once we're done, if thats set
defer os.Remove(image)
}
// try to upload the photo to mastodon and then make a post
if a, err := mClient.UploadMedia(image, "", ""); err == nil {
mClient.PostStatus(post.Title + "\n\nsrc: " + post.URL, 0, []int64{a.ID}, true, "porn, Overwatch", "unlisted")
}
}
} else {
// if the link isn't a direct image link we just link to it
mClient.PostStatus(post.Title + "\n\nsrc: " + post.URL, 0, nil, true, "porn, Overwatch", "unlisted")
}
} else {// if it's a self post then we do nothing
return nil
}
// no error, no problem
return nil
}
func DownloadImage(url string) (string, error) {
// something with imgur api?
// gfycat -> https://giant. {link} .mp4
parsedUrl := strings.Split(url, "/")
fileName := parsedUrl[len(parsedUrl) - 1]
if file, err := os.Create(ImageSaveDir + fileName); err != nil {
return "", err
} else {
if response, err := http.Get(url); err != nil {
return "", err
} else {
defer response.Body.Close()
if b, err := io.Copy(file, response.Body); err != nil {
return "", err
} else if b > MaxDataSize {
return "", err
}
}
file.Close()
}
return ImageSaveDir + fileName, nil
}
const (
AppName string = "OWP Crossposter"
ImageSaveDir string = "/tmp/OWP/"
DeleteAfterPost bool = true
MaxDataSize int64 = 8388608 //bytes -- 8mb
)
var (
mClient *madon.Client
RedditConfigFile string
mConfig MastoConfig = MastoConfig{}
)
func init() {
if _, err := os.Stat(ImageSaveDir); os.IsNotExist(err) {
os.Mkdir(ImageSaveDir, 0777)
}
var MastoConfigFile string
// first we check for mastodon and reddit config files
flag.StringVar(&MastoConfigFile, "mc", "", "relative file path to file containing mastodon client/user tokens")
flag.StringVar(&RedditConfigFile, "rc", "", "relative file path to file containing reddit client tokens")
flag.Parse()
// if we don't have a config file specified check the other flags
// but if we do then we read it and parse it
if MastoConfigFile == "" {
flag.StringVar(&mConfig.Secret, "ms", "",
"mastodon client secret, needs to be supplied if mastodon config file isn't specified")
flag.StringVar(&mConfig.Key, "mk", "",
"mastodon client key, needs to be supplied if mastodon config file isn't specified")
flag.StringVar(&mConfig.AccessToken, "ma", "",
"mastodon access token, needs to be supplied if mastodon config file isn't specified")
flag.Parse()
} else {
if dat, err := ioutil.ReadFile(MastoConfigFile); err != nil {
log.Fatal("error opening mastodon config file ", err)
} else {
toml.Unmarshal(dat, &mConfig)
}
}
// if we don't have the neccesary files we print the usage info
if RedditConfigFile == "" || mConfig.Secret == "" || mConfig.Key == "" || mConfig.AccessToken == "" {
flag.Usage()
return
}
}
func main() {
if redditBot, err := reddit.NewBotFromAgentFile(RedditConfigFile, 0); err != nil {
log.Fatal("failed to create the reddit bot ", err)
} else {
redditCfg := graw.Config{Subreddits: []string{"Overwatch_Porn"}}
handler := &Crossposter{bot: redditBot}
// generate the mastodon app from credentials
mClient, err = madon.RestoreApp(AppName,
mConfig.Instance,
mConfig.Key,
mConfig.Secret,
&madon.UserToken{ AccessToken: mConfig.AccessToken, Scope: "write" })
if err != nil {
log.Fatal("error restoring app from credentials ", err)
}
// start the reddit bot
log.Println("Starting reddit bot...")
if _, wait, err := graw.Run(handler, redditBot, redditCfg); err != nil {
log.Fatal("failed to start graw : ", err)
} else {
log.Println("graw run failed : ", wait())
}
}
}