flowers/main.go

1380 lines
40 KiB
Go
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bufio"
"bytes"
"database/sql"
"errors"
"fmt"
"io/ioutil"
"math"
"math/rand"
"os"
"os/exec"
"os/signal"
"regexp"
"strings"
"syscall"
"time"
"github.com/bwmarrin/discordgo"
_ "github.com/mattn/go-sqlite3"
)
// Variables used for command line parameters
var (
Token string
flowerVer string
)
var url_regexp, _ = regexp.Compile(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)`)
var event = false
// The list of games is currently a hardcoded slice of slices. The first element of
// a game slice should be the default ("display") name of the game, second one is a short name, the other ones are aliases.
// Since the second value is used as a filename, a game should have at least 2 values.
func getGames() [][]string {
return [][]string{
{"Garry's Mod", "gmod", "garrys mod", "ttt", "Trouble in Terrorist Town"},
{"Hunt: Showdown", "hunt", "hunt showdown"},
{"Risk of Rain", "risk", "risky", "ror", "ror2", "risk of rain 2"},
{"Fistful of Frags", "fof", "fistful"},
{"Counter-Strike", "csgo", "Counter-Strike: Global Offensive", "cs", "counter strike", "counter strike global offensive", "counter strike: global offensive", "cs:go", "css", "cs16", "cs 1.6", "cs1.6", "counter strike 1.6", "counter-strike 1.6"},
{"Tekken 7", "tekken"},
{"Squad", "squad"},
{"Jordycore", "jordy", "artoria", "fartoria", "fartoriacore", "league", "league of legends", "lol", "valorant", "garfield cart", "crab game", "crap game", "squid game", "carp game", "fall guys", "fall goys", "cringe guys"},
// {"Apex Legends", "apex"},
{"Barotrauma", "baro"},
// {"Worms", "worms"},
{"Left 4 Dead 2", "l4d2", "l4d", "left4dead2", "left4dead", "left 4 dead", "lfd", "lfd2"},
{"Dota 2", "dota", "dota2"},
{"Deep Rock Galactic", "drg", "deep rock", "dwarfs", "dwarf fortress"},
{"Gunfire Reborn", "gunfire"},
{"Lethal League Blaze", "llb", "lethal league", "bouncy ball"},
// {"ROUNDS", "rounds"},
{"Sid Meier's Civilization", "civ", "civ4", "civ5", "civilisation", "civilization 5", "civilization 4", "civilization v", "civilization iv", "civ 5", "civ 4", "civ v", "civ iv", "civilization"},
{"Endless Space 2", "es2", "es", "endless space"},
// {"Neotokyo", "neotokyo", "neo tokyo"},
{"100% Orange Juice!", "100oj", "100%oj", "orange juice", "100% orange juice", "100 orange juice", "100% oj", "100 oj", "oj"},
{"Minecraft", "mc", "terraria", "hypixel", "major", "majorcore", "starbound", "valheim", "stardew valley"},
{"BattleBit", "battlebit", "battlebit remastered"},
{"Among Us", "sus", "amogus", "amongus", "along the's"},
{"Titanfall 2", "tf2", "tf", "titanfall", "tittyfall"},
{"Escape from Tarkov", "tarkov", "scavs"},
{"Multiversus", "multiversus", "super smash bros ultimate", "melee", "multiverzus"},
{"Intruder", "intruder", "impostor", "amonger", "intruders", "rainbow six siege"},
{"Halo: The Master Chief Collection", "halo", "halo: combat evolved", "halo ce", "halo 2", "halo 3", "halo reach", "gaylo", "majorcore", "halo mcc"},
{"Warcraft III: The Frozen Throne", "wc3", "warcraft 3", "warcraft", "dota 1", "warcraft 3 the frozen throne", "warcraft 3 reign of chaos"},
{"GUNDAM EVOLUTION", "gundam"},
}
}
func getFortunes() []string {
fortunes := []string{
"Your fortune: Reply hazy, try again", //0
"Your fortune: Excellent Luck", //1
"Your fortune: Good Luck", //2
"Your fortune: Average Luck", //3
"Your fortune: Bad Luck", //4
"Your fortune: Good news will come to you by mail", //5
"Your fortune:  ´_ゝ`)フーン", //6
"Your fortune: キタ━━━━━━(゚∀゚)━━━━━━ !!!!", //7
"Your fortune: You will meet a dark handsome stranger", //8
"Your fortune: Better not tell you now", //9
"Your fortune: Outlook good", //10
"Your fortune: Very Bad Luck", //11
"Your fortune: Godly Luck", //12
"Your fortune: le ebin dubs xDDDDDDDDDDDD", //13
"Your fortune: you gon' get some dick", //14
"Your fortune: ayy lmao", //15
"Your fortune: (YOU ARE BANNED)", //16
"Your fortune: Get Shrekt", //17
"Your fortune: YOU JUST LOST THE GAME", //18
"Your fortune: NOT SO SENPAI BAKA~KUN", //19
}
return fortunes
}
// func getFortune() string {
// rand.Seed(time.Now().Unix())
// return getFortunes()[rand.Intn(len(getFortunes()))]
// }
func getCandyPic() string {
pics := []string{
"https://cdn.discordapp.com/attachments/956628829735125042/1023232603379212339/candyroland.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023238894742937650/candyphos.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023239554481799328/candynooo.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023240219287367750/candyhappy.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023242557670572052/candyclueless.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023242846490329138/candybased.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023243877429284874/candylol.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023243877676761108/candyjust.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245477484953610/candykneel.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245477875040336/candylfg.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245478214766712/candythicc.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245478504169552/candysaber.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245478869078026/candythis.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023245479187841075/candy15.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1023259345934352414/candysad.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1024353063076642866/candynemorgal.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1024353428027211826/candyschizo.jpg",
"https://cdn.discordapp.com/attachments/956628829735125042/1024728955963588608/candytroll.jpg",
}
return pics[rand.Intn(len(pics))]
}
func candy(s *discordgo.Session, channel string, droptype string) {
candy1 := &discordgo.MessageEmbed{
Title: "Candy",
Color: 0,
Footer: &discordgo.MessageEmbedFooter{
Text: "candy1",
},
Image: &discordgo.MessageEmbedImage{
URL: getCandyPic(),
},
}
candyRadmeal := &discordgo.MessageEmbed{
Title: "Candy",
Color: 0xff0000,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyRadmeal",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/946859404819587162/946897683908542494/P10213-191951-1.jpg",
},
}
candyCaptain := &discordgo.MessageEmbed{
Title: "Captain Candy",
Color: 0xffe600,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyCaptain",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1023225555820216440/unknown.png",
},
}
candyMilky := &discordgo.MessageEmbed{
Title: "Chocolate Inaba",
Color: 0x6df175,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyMilky",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1023229123725893632/7c5085c86d4f230dc253c62b6266279f.jpg",
},
}
candyMeta := &discordgo.MessageEmbed{
Title: "Macaroons",
Color: 0xa90000,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyMeta",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1023271248903544972/macaroon.jpg",
},
}
candyXorcon := &discordgo.MessageEmbed{
Title: "Xorconium Pills",
Color: 0x306AC0,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyXorcon",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1024326522389147718/Alpha_Xorcon.png",
},
}
candyKornflake := &discordgo.MessageEmbed{
Title: "Candy Korn",
Color: 0xff5500,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyKornflake",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1024436493495836762/kornflake.jpg",
},
}
candyKiko := &discordgo.MessageEmbed{
Title: "Kikola Cubes",
Color: 0x8f32a8,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyKiko",
},
Image: &discordgo.MessageEmbedImage{
URL: "https://cdn.discordapp.com/attachments/956628829735125042/1024731407001591919/unknown.png",
},
}
candyChaos := &discordgo.MessageEmbed{
Title: "Chaos Candy",
Description: getFortunes()[rand.Intn(len(getFortunes()))],
Color: 0x000000,
Footer: &discordgo.MessageEmbedFooter{
Text: "candyChaos",
IconURL: "",
ProxyIconURL: "",
},
}
drop := candy1
if droptype == "" {
switch rand.Intn(40) {
case 1:
drop = candyCaptain
case 3, 4:
drop = candyMilky
case 5, 6:
drop = candyRadmeal
case 7:
drop = candyMeta
case 8, 9:
drop = candyXorcon
case 10, 11:
drop = candyKornflake
case 12, 13:
drop = candyKiko
case 39:
drop = candyChaos
default:
drop = candy1
}
} else {
switch droptype {
case "candyCaptain":
drop = candyCaptain
case "candyMilky":
drop = candyMilky
case "candyRadmeal":
drop = candyRadmeal
case "candyMeta":
drop = candyMeta
case "candyXorcon":
drop = candyXorcon
case "candyKornflake":
drop = candyKornflake
case "candyKiko":
drop = candyKiko
case "candyChaos":
drop = candyChaos
default:
drop = candy1
}
}
ms := &discordgo.MessageSend{
Content: "🍬 ***Some candy has appeared! React to this message to claim it.*** 🍬",
Embed: drop,
}
s.ChannelMessageSendComplex(channel, ms)
}
func battle(user string, target string) string {
rand.Seed(time.Now().Unix())
userPower := int16(0)
targetPower := int16(0)
rollToPower := func(roll int) int16 {
switch roll {
case 0:
return int16(rand.Int31n(51) - 25)
case 1:
return 50
case 2:
return 1
case 3:
return 0
case 4:
return -1
case 5:
return 25
case 6:
return 7
case 7:
return 777
case 8:
return int16(rand.Int31n(999))
case 9:
return -5
case 10:
return 9
case 11:
return -50
case 12:
return 999
case 13:
vals := [9]int16{11, 22, 33, 44, 55, 66, 77, 88, 99}
return vals[rand.Intn(len(vals))]
case 14:
vals := [2]int16{-69, 69}
return vals[rand.Intn(len(vals))]
case 15:
vals := [2]int16{-420, 420}
return vals[rand.Intn(len(vals))]
case 16:
return -9999
case 17:
return -666
case 18:
return -777
case 19:
return 0 - int16(rand.Int31n(9999))
default:
return 0
}
}
fight := func(userPower, targetPower int16) string {
fightmsg := ""
if userPower > targetPower {
fightmsg += "**<@" + user + "> has slain <@" + target + ">!**\n"
}
if userPower == targetPower {
fightmsg += "**<@" + user + "> and <@" + target + "> have fought a bloody battle, and both have perished.**\n"
}
if userPower < targetPower {
fightmsg += "**<@" + target + "> has slain <@" + user + ">!**\n"
}
return fightmsg
}
msg := "**Battle between <@" + user + "> and <@" + target + ">**\n" +
"*<@" + user + "> rolls!*\n"
userRoll := rand.Intn(len(getFortunes()))
msg += getFortunes()[userRoll] + "\n"
userPower = rollToPower(userRoll)
// msg += fmt.Sprint(userPower) + "\n"
msg += "*<@" + target + "> rolls!*\n"
targetRoll := rand.Intn(len(getFortunes()))
msg += getFortunes()[targetRoll] + "\n"
targetPower = rollToPower(targetRoll)
// msg += fmt.Sprint(targetPower) + "\n"
if userPower > targetPower && target == "228911057316347905" {
msg += "*<@" + target + ">'s Lucky Charm activated!*\n"
targetRoll = rand.Intn(len(getFortunes()))
msg += getFortunes()[targetRoll] + "\n"
targetPower = rollToPower(targetRoll)
}
if userPower == targetPower {
if user == "228911057316347905" {
msg += "*<@" + user + ">'s Lucky Charm activated!*\n"
userRoll = rand.Intn(len(getFortunes()))
msg += getFortunes()[userRoll] + "\n"
userPower = rollToPower(userRoll)
}
if target == "228911057316347905" {
msg += "*<@" + target + ">'s Lucky Charm activated!*\n"
targetRoll = rand.Intn(len(getFortunes()))
msg += getFortunes()[targetRoll] + "\n"
targetPower = rollToPower(targetRoll)
}
}
if userPower < targetPower && user == "228911057316347905" {
msg += "*<@" + user + ">'s Lucky Charm activated!*\n"
userRoll = rand.Intn(len(getFortunes()))
msg += getFortunes()[userRoll] + "\n"
userPower = rollToPower(userRoll)
}
msg += fight(userPower, targetPower)
return msg
}
func getFiles() {
fmt.Println("Checking files for Europe region.")
for _, i := range getGames() {
_, err := os.Stat("games/eu/" + i[1])
if errors.Is(err, os.ErrNotExist) {
fmt.Println("games/eu/" + i[1] + " does not exist, attempting creation")
file, err := os.Create("games/eu/" + i[1])
if err != nil {
fmt.Println(err)
}
defer file.Close()
} else {
fmt.Println("games/eu/" + i[1] + " exists")
}
}
fmt.Println("Checking files for America region.")
for _, i := range getGames() {
_, err := os.Stat("games/us/" + i[1])
if errors.Is(err, os.ErrNotExist) {
fmt.Println("games/us/" + i[1] + " does not exist, attempting creation")
file, err := os.Create("games/us/" + i[1])
if err != nil {
fmt.Println(err)
}
defer file.Close()
} else {
fmt.Println("games/us/" + i[1] + " exists")
}
}
}
func initdb() {
file, err := os.Create("guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
file.Close()
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
users_table := `CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userID" TEXT,
"candy" INT,
"buff" INT);`
query, err := db.Prepare(users_table)
if err != nil {
fmt.Println(err.Error())
return
}
query.Exec()
}
func addUser(userID string, candy int, buff int) {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
records := `INSERT INTO users(userID, candy, buff) VALUES (?, ?, ?)`
query, err := db.Prepare(records)
if err != nil {
fmt.Println(err.Error())
return
}
_, err = query.Exec(userID, candy, buff)
if err != nil {
fmt.Println(err.Error())
return
}
}
func delUser(userID string) {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
query, err := db.Prepare(`DELETE FROM users WHERE userID = ?`)
if err != nil {
fmt.Println(err.Error())
return
}
query.Exec()
}
func checkUser(userID string) bool {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return false
}
err = db.QueryRow(`SELECT userID FROM users WHERE userID = ?`, userID).Scan(&userID)
if err != nil {
if err != sql.ErrNoRows {
fmt.Println(err.Error())
}
return false
}
return true
}
func checkUserCandy(userID string) int {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return 0
}
var candy int
err = db.QueryRow(`SELECT candy FROM users WHERE userID = ?`, userID).Scan(&candy)
if err != nil {
fmt.Println(err.Error())
return 0
}
return candy
}
func addCandy(userID string, amount int) {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
query, err := db.Prepare(`UPDATE users SET candy = candy + ? WHERE userID = ?`)
if err != nil {
fmt.Println(err.Error())
}
_, err = query.Exec(amount, userID)
if err != nil {
fmt.Println(err.Error())
}
}
func addBuff(userID string, amount int) {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
query, err := db.Prepare(`UPDATE users SET buff = buff + ? WHERE userID = ?`)
if err != nil {
fmt.Println(err.Error())
}
_, err = query.Exec(amount, userID)
if err != nil {
fmt.Println(err.Error())
}
}
func candyRank() (string, error) {
ms := ""
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return ms, err
}
query, err := db.Query(`SELECT userID, candy FROM users ORDER BY candy DESC LIMIT 10`)
if err != nil {
fmt.Println(err.Error())
return ms, err
}
defer query.Close()
n := 1
for query.Next() {
var userID string
var candy int
query.Scan(&userID, &candy)
ms += fmt.Sprint(n) + `. <@` + userID + "> " + fmt.Sprint(candy) + "\n"
n++
}
return ms, err
}
func topUserCandy() (int, string) {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return 0, ""
}
var candy int
var user string
err = db.QueryRow(`SELECT candy, userID FROM users WHERE candy = (SELECT MAX(candy) FROM users)`).Scan(&candy, &user)
if err != nil {
fmt.Println(err.Error())
return 0, ""
}
return candy, user
}
func main() {
commitID, err := exec.Command("git", "log", "--oneline", "-1").Output()
if err != nil {
fmt.Println("Error getting git commit ID: ", err)
}
flowerVer = `"Ghost Quartz"
Last commit:
` + string(commitID)
fmt.Println(flowerVer)
if len(os.Args) < 2 {
fmt.Println("No token provided.")
os.Exit(1)
}
fmt.Println("Checking files.")
getFiles()
_, err = os.Stat("guilds.db")
if errors.Is(err, os.ErrNotExist) {
fmt.Println("Guilds database not found!")
fmt.Println("Initialising database...")
initdb()
fmt.Println("Testing database:")
addUser("0000000", 100, 0)
delUser("0000000")
fmt.Println("Test complete.")
}
// create a new discord session using the provided bot token.
dg, err := discordgo.New("Bot " + os.Args[1])
if err != nil {
fmt.Println("error creating Discord session,", err)
return
}
// Register the messageCreate func as a callback for MessageCreate events.
dg.AddHandler(messageCreate)
// In this example, we only care about receiving message events.
dg.Identify.Intents = discordgo.IntentsGuildMessages
// Open a websocket connection to Discord and begin listening.
err = dg.Open()
if err != nil {
fmt.Println("error opening connection,", err)
return
}
// Wait here until CTRL-C or other term signal is received.
fmt.Println("Bot is now running. Press CTRL-C to exit.")
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-sc
// Cleanly close down the Discord session.
dg.Close()
}
func parseArgs(s string) string {
args := strings.Split(s, " ")
args = args[1:]
return strings.ToLower(strings.Join(args, " "))
}
func parseArgsRegion(s string) (string, string) {
args := strings.Split(s, " ")
args = args[1:]
region := ""
if len(args) == 0 {
return "", region
} else if strings.ToUpper(args[0]) == "EU" || strings.ToUpper(args[0]) == "US" || strings.ToUpper(args[0]) == "ALL" {
region = args[0]
}
return strings.ToLower(strings.Join(args[1:], " ")), strings.ToLower(region)
}
func checkGame(s string) (bool, string, string) {
found := false
game := ""
gameShort := ""
for _, i := range getGames() {
for _, x := range i {
if strings.ToLower(x) == s {
found = true
game = i[0]
gameShort = i[1]
break
}
}
}
return found, game, gameShort
}
// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the authenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
if time.Now().Month().String() == "October" {
event = true
} else if event == true {
haul, winner := topUserCandy()
s.ChannelMessageSend("947540183077748820", "<@" + winner + "> has won the candy hunt! Candy claimed: " + fmt.Sprint(haul))
event = false
}
var claimed bool
var tickrate time.Duration
const maxtickrate = 5000 * time.Millisecond
var claimer string
if m.Author.ID == s.State.User.ID {
if m.Content == "🍬 ***Some candy has appeared! React to this message to claim it.*** 🍬" {
s.MessageReactionAdd(m.ChannelID, m.Reference().MessageID, "🍬")
}
tickrate = 200 * time.Millisecond
claimed = false
for i := 0; i < 720; i++ {
reactions, err := s.MessageReactions(m.ChannelID, m.Reference().MessageID, "🍬", 2, "", "")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
i -= 1
continue
}
if len(reactions) <= 1 {
time.Sleep(tickrate)
if tickrate < maxtickrate && i%5 == 0 {
tickrate += 20 * time.Millisecond
}
continue
}
for n, i := range reactions {
if i.ID == s.State.User.ID {
reactions[n] = reactions[len(reactions)-1]
}
}
if len(reactions) == 0 {
time.Sleep(tickrate)
if tickrate < maxtickrate && i%5 == 0 {
tickrate += 20 * time.Millisecond
}
continue
}
claimer = reactions[0].ID
var candyvalue int
bufftype := "none"
buffvalue := 0
var candystr string
maxcandy, _ := topUserCandy()
switch m.Embeds[0].Footer.Text {
case "candyMilky":
candyvalue = 500
bufftype = "tewi"
case "candyMeta":
candyvalue = 1000
case "candyCaptain":
candyvalue = 250
case "candyRadmeal":
candyvalue = -200
case "candyXorcon":
candyvalue = 50
bufftype = "alpha"
buffvalue = 1
case "candyKornflake":
candyvalue = 200
case "candyKiko":
candyvalue = 500
case "candyChaos":
candyvalue = rand.Intn(maxcandy*2) - maxcandy
default:
candyvalue = 100
}
multiplier := 1
usercandy := checkUserCandy(reactions[0].ID)
if !math.Signbit(float64(candyvalue)) && m.Embeds[0].Footer.Text != "candyChaos" {
if checkUserCandy(claimer) < maxcandy {
if usercandy == 0 {
multiplier = maxcandy / 10000
} else if usercandy < 0 {
multiplier = maxcandy / 100
} else {
multiplier = (maxcandy / usercandy) * 2
}
}
candyvalue *= multiplier
candystr = "+" + fmt.Sprint(candyvalue)
} else if m.Embeds[0].Footer.Text != "candyChaos" {
if usercandy < 0 {
candyvalue = int(math.Abs(float64(candyvalue)))
}
candystr = fmt.Sprint(candyvalue)
} else {
multiplier = rand.Intn(21) - 10
candyvalue *= multiplier
if !math.Signbit(float64(candyvalue)) {
candystr = "+" + fmt.Sprint(candyvalue)
} else {
candystr = fmt.Sprint(candyvalue)
}
}
msg := reactions[0].Username + " has claimed the candy! (" + candystr + " 🍬) [" + fmt.Sprint(multiplier) + "x]"
switch bufftype {
case "tewi":
msg += "\n*Good luck!* Global candy droprate temporarily increased!"
case "alpha":
msg += "\n*Bash!* Crit chance permanently increased!"
}
if !checkUser(claimer) {
addUser(claimer, candyvalue, buffvalue)
} else {
addCandy(claimer, candyvalue)
addBuff(claimer, buffvalue)
}
s.ChannelMessageSend(m.ChannelID, msg)
claimed = true
if claimed {
break
}
}
return
}
if m.ChannelID == "946459086554275883" && event {
rand.Seed(time.Now().Unix())
if rand.Intn(100) < 3 {
time.Sleep(1 * time.Second)
rand.Seed(time.Now().Unix() - rand.Int63n(time.Now().Unix()))
candy(s, m.ChannelID, "")
}
}
if strings.HasPrefix(m.Content, "pp!") {
blockfile, err := ioutil.ReadFile("blocklist.txt")
if err != nil {
fmt.Println(err.Error())
}
blocklist := strings.Split(string(blockfile), "\n")
for _, i := range blocklist {
if i == m.Author.ID && m.Author.ID != "228911057316347905" {
s.ChannelMessageSend(m.ChannelID, "1 blocked message")
return
}
}
}
if strings.HasPrefix(m.Content, "pp!help") {
s.ChannelMessageSend(m.ChannelID, "Command help:\n"+
"`pp!register [ALL|EU|US] [game]` - register for a game\n"+
"`pp!unregister [game]` - unregister from a game\n"+
"`pp!summon [EU|US] [game]` - summon people for a game\n"+
"`pp!games` - show available games\n"+
"`pp!gamers [game]` - show gamers registered for a game\n"+
"`pp!alias [game]` - show aliases for a game\n")
}
if strings.HasPrefix(m.Content, "pp!summon") {
args, region := parseArgsRegion(m.Content)
found, game, gameShort := checkGame(args)
if region == "" {
s.ChannelMessageSend(m.ChannelID, "You have to provide a region (EU or US)\n"+
"*command usage:*\n"+
"`pp!summon [EU|US] [game]` - summon people for a game\n")
return
}
if found && region != "all" {
content, err := ioutil.ReadFile("games/" + region + "/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers := strings.Split(string(content), "\n")
for n, i := range gamers {
gamers[n] = "<@" + i + ">"
}
if len(gamers) > 0 {
gamers = gamers[:len(gamers)-1]
}
if len(gamers) == 0 {
gamers = append(gamers, "nobody")
}
s.ChannelMessageSend(m.ChannelID, "Summoning "+strings.Join(gamers, " ")+" for "+game+"! ("+strings.ToUpper(region)+")")
} else if found && region == "all" {
content, err := ioutil.ReadFile("games/eu/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers := strings.Split(string(content), "\n")
for n, i := range gamers {
gamers[n] = "<@" + i + ">"
}
if len(gamers) > 0 {
gamers = gamers[:len(gamers)-1]
}
if len(gamers) == 0 {
gamers = append(gamers, "nobody")
}
content2, err := ioutil.ReadFile("games/us/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers2 := strings.Split(string(content2), "\n")
for n, i := range gamers2 {
gamers2[n] = "<@" + i + ">"
}
if len(gamers2) > 0 {
gamers2 = gamers2[:len(gamers2)-1]
}
if len(gamers2) == 0 {
gamers2 = append(gamers2, "nobody")
}
s.ChannelMessageSend(m.ChannelID, "Summoning ALL gamers for "+game+"!\n"+strings.Join(gamers, " ")+"\n"+strings.Join(gamers2, " "))
} else {
s.ChannelMessageSend(m.ChannelID, "Game not found!\n"+
"*command usage:*\n"+
"`pp!summon [EU|US] [game]` - summon people for a game\n")
}
}
if strings.HasPrefix(m.Content, "pp!register") {
args, region := parseArgsRegion(m.Content)
found, game, gameShort := checkGame(args)
bunnyEU := false
bunnyUS := false
if region == "" {
s.ChannelMessageSend(m.ChannelID, "You have to provide a region (EU, US or ALL)\n"+
"*command usage:*\n"+
"`pp!register [ALL|EU|US] [game]` - register for a game\n")
return
}
if found && region != "all" {
content, err := ioutil.ReadFile("games/" + region + "/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers := strings.Split(string(content), "\n")
for _, i := range gamers {
if i == m.Author.ID {
s.ChannelMessageSend(m.ChannelID, "You are already registered for "+game+" in "+strings.ToUpper(region)+".")
return
}
}
f, err := os.OpenFile("games/"+region+"/"+gameShort, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f.Close()
if _, err := f.WriteString(m.Author.ID + "\n"); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Registered for "+game+"! (region: "+strings.ToUpper(region)+")")
} else if found && region == "all" {
content, err := ioutil.ReadFile("games/eu/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers := strings.Split(string(content), "\n")
for _, i := range gamers {
if i == m.Author.ID {
s.ChannelMessageSend(m.ChannelID, "You are already registered for "+game+" in Europe.")
bunnyEU = true
}
}
if !bunnyEU {
f, err := os.OpenFile("games/eu/"+gameShort, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f.Close()
if _, err := f.WriteString(m.Author.ID + "\n"); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Registered for "+game+"! (region: Europe)")
}
content2, err := ioutil.ReadFile("games/us/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
gamers2 := strings.Split(string(content2), "\n")
for _, i := range gamers2 {
if i == m.Author.ID {
s.ChannelMessageSend(m.ChannelID, "You are already registered for "+game+" in America.")
bunnyUS = true
}
}
if !bunnyUS {
f2, err := os.OpenFile("games/us/"+gameShort, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f2.Close()
if _, err := f2.WriteString(m.Author.ID + "\n"); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Registered for "+game+"! (region: America)")
}
} else if !found {
s.ChannelMessageSend(m.ChannelID, "Game not found!\n"+
"*command usage:*\n"+
"`pp!register [ALL|EU|US] [game]` - register for a game\n")
} else {
s.ChannelMessageSend(m.ChannelID, "Usage:\npp!register `EU|US|ALL` `game`")
}
}
if strings.HasPrefix(m.Content, "pp!gamers") {
found, game, gameShort := checkGame(parseArgs(m.Content))
if found {
lc1 := 0
var gamersEU strings.Builder
file, err := os.Open("games/eu/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
gamersEU.WriteString("<@" + strings.TrimRight(scanner.Text(), "\n") + ">\n")
lc1++
}
lc2 := 0
var gamersUS strings.Builder
file2, err := os.Open("games/us/" + gameShort)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
}
defer file2.Close()
scanner2 := bufio.NewScanner(file2)
for scanner2.Scan() {
gamersUS.WriteString("<@" + strings.TrimRight(scanner2.Text(), "\n") + ">\n")
lc2++
}
ms := &discordgo.MessageSend{
Content: "Gamers for " + game + " in Europe: " + fmt.Sprint(lc1) + "\n" + gamersEU.String() + "\n" +
"Gamers for " + game + " in America: " + fmt.Sprint(lc2) + "\n" + gamersUS.String(),
AllowedMentions: &discordgo.MessageAllowedMentions{},
}
s.ChannelMessageSendComplex(m.ChannelID, ms)
} else {
s.ChannelMessageSend(m.ChannelID, "Game not found!")
}
}
if strings.HasPrefix(m.Content, "pp!games") {
var games strings.Builder
for _, i := range getGames() {
games.WriteString(i[0] + "\n")
}
s.ChannelMessageSend(m.ChannelID, "Available games: \n"+games.String())
}
if strings.HasPrefix(m.Content, "pp!alias") {
found, game, _ := checkGame(parseArgs(m.Content))
var aliases strings.Builder
if found {
for _, i := range getGames() {
if i[0] == game {
for _, j := range i {
aliases.WriteString(j + "\n")
}
}
}
s.ChannelMessageSend(m.ChannelID, "Aliases for "+game+":\n"+aliases.String())
} else {
s.ChannelMessageSend(m.ChannelID, "Game not found!")
}
}
if strings.HasPrefix(m.Content, "pp!unregister") {
found, game, gameShort := checkGame(parseArgs(m.Content))
if found {
// https://gist.github.com/Integralist/c29ff647e5fb2f5c5001aa50a9288d8f
fpath := "games/eu/" + gameShort
f, err := os.Open(fpath)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f.Close()
var bs []byte
buf := bytes.NewBuffer(bs)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if scanner.Text() != m.Author.ID {
_, err := buf.Write(scanner.Bytes())
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
_, err = buf.WriteString("\n")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
}
}
if err := scanner.Err(); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
err = os.WriteFile(fpath, buf.Bytes(), 0666)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Unregistered from "+game+" in EU!")
fpath2 := "games/us/" + gameShort
f2, err := os.Open(fpath2)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f2.Close()
var bs2 []byte
buf2 := bytes.NewBuffer(bs2)
scanner2 := bufio.NewScanner(f2)
for scanner2.Scan() {
if scanner2.Text() != m.Author.ID {
_, err := buf2.Write(scanner2.Bytes())
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
_, err = buf2.WriteString("\n")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
}
}
if err := scanner2.Err(); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
err = os.WriteFile(fpath2, buf2.Bytes(), 0666)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Unregistered from "+game+" in US!")
} else {
s.ChannelMessageSend(m.ChannelID, "Game not found!")
}
}
if strings.HasPrefix(m.Content, "pp!members") {
mem, err := s.GuildMember(m.GuildID, m.Author.ID)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
}
g, err := s.Guild(m.GuildID)
var mems strings.Builder
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
}
for _, i := range g.Members {
mems.WriteString("<@" + i.Nick + ">\n")
}
s.ChannelMessageSend(m.ChannelID, fmt.Sprint(len(g.Members)))
s.ChannelMessageSend(m.ChannelID, mems.String())
s.ChannelMessageSend(m.ChannelID, mem.Nick)
}
if strings.HasPrefix(m.Content, "pp!roll") {
rand.Seed(time.Now().Unix())
s.ChannelMessageSend(m.ChannelID, fmt.Sprint(rand.Intn(100)))
}
if strings.HasPrefix(m.Content, "pp!milk") {
rand.Seed(time.Now().Unix())
milks := []string{}
for i := 0; i < rand.Intn(100); i++ {
if rand.Float32() > 0.5 {
milks = append(milks, "🥛")
} else {
milks = append(milks, "🐄")
}
}
s.ChannelMessageSend(m.ChannelID, strings.Join(milks, ""))
}
if strings.HasPrefix(m.Content, "pp!radma") {
radmeons := []string{
"https://cdn.discordapp.com/attachments/946859404819587162/946897683908542494/P10213-191951-1.jpg",
"https://cdn.discordapp.com/attachments/946459086554275883/1025901158335774800/radmaAmberTurd.jpg",
"https://cdn.discordapp.com/attachments/946459086554275883/1025901158658748519/radmaSpecialOPs.jpg",
"https://cdn.discordapp.com/attachments/946459086554275883/1025901159053021225/radmaWonka.jpg",
"https://cdn.discordapp.com/attachments/946459086554275883/1025901159313047552/Radma_rectal.png",
"https://cdn.discordapp.com/attachments/946459086554275883/1026849353584877568/radmeal_eater.png",
"https://media.discordapp.net/attachments/579378525400858640/996922899204157480/IMG_8998.gif",
}
s.ChannelMessageSend(m.ChannelID, radmeons[rand.Intn(len(radmeons))])
}
if strings.HasPrefix(m.Content, "pp!fortune") {
out, err := exec.Command("/usr/local/plan9front/bin/fortune").Output()
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
}
s.ChannelMessageSend(m.ChannelID, string(out))
}
if strings.HasPrefix(m.Content, "pp!atk") || strings.HasPrefix(m.Content, "pp!attack") {
args := parseArgs(m.Content)
target := strings.Split(args, " ")[0]
user := m.Author.ID
if strings.HasPrefix(target, "<@") && strings.HasSuffix(target, ">") {
ms := &discordgo.MessageSend{
Content: battle(user, strings.Trim(target, "<@>")),
AllowedMentions: &discordgo.MessageAllowedMentions{},
}
s.ChannelMessageSendComplex(m.ChannelID, ms)
} else {
s.ChannelMessageSend(m.ChannelID, "Target not found!")
}
}
if strings.HasPrefix(m.Content, "pp!moo") {
s.ChannelMessageSend(m.ChannelID, "```\n"+
" (__)\n"+
" (oo)\n"+
" /------\\/\n"+
" / | ||\n"+
" * /\\---/\\\n"+
" ~~ ~~\n"+
"...\"Have you mooed today?\"...\n"+
"```")
}
if strings.HasPrefix(m.Content, "pp!version") {
s.ChannelMessageSend(m.ChannelID, flowerVer)
}
if !strings.HasPrefix(m.Content, "pp!") && !url_regexp.MatchString(m.Content) {
f, err := os.OpenFile("markov.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
print("DEBUG: error opening markov.txt: " + err.Error() + "\n")
return
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
print("DEBUG: error accessing f.Stat: " + err.Error() + "\n")
return
}
if fi.Size() > 1000000 {
if err := os.Truncate("markov.txt", 0); err != nil {
fmt.Println("Failed to truncate: " + err.Error())
}
}
_, err = f.WriteString(m.Content + "\n")
if err != nil {
print(err.Error())
}
}
if strings.HasPrefix(m.Content, "pp!dissociate") {
diss, err := exec.Command("./dissociate.sh").Output()
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
ms := &discordgo.MessageSend{
Content: string(diss),
AllowedMentions: &discordgo.MessageAllowedMentions{},
}
s.ChannelMessageSendComplex(m.ChannelID, ms)
}
if strings.HasPrefix(m.Content, "pp!block") {
if m.Author.ID != "228911057316347905" {
s.ChannelMessageSend(m.ChannelID, "Insufficient permissions")
return
}
felon := parseArgs(m.Content)
f, err := os.OpenFile("blocklist.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
_, err = f.WriteString(felon + "\n")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Blocked "+felon)
}
if strings.HasPrefix(m.Content, "pp!unblock") {
if m.Author.ID != "228911057316347905" {
s.ChannelMessageSend(m.ChannelID, "Insufficient permissions")
return
}
felon := parseArgs(m.Content)
f, err := os.Open("blocklist.txt")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
defer f.Close()
var bs []byte
buf := bytes.NewBuffer(bs)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if scanner.Text() != felon {
_, err := buf.Write(scanner.Bytes())
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
_, err = buf.WriteString("\n")
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
}
}
if err := scanner.Err(); err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
err = os.WriteFile("blocklist.txt", buf.Bytes(), 0666)
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
s.ChannelMessageSend(m.ChannelID, "Unblocked "+felon)
}
if strings.HasPrefix(m.Content, "pp!spawncandy") && m.Author.ID == "228911057316347905" {
arg := strings.Split(m.Content, " ")
if len(arg) < 2 {
candy(s, m.ChannelID, "")
} else {
candy(s, m.ChannelID, arg[1])
}
}
if strings.HasPrefix(m.Content, "pp!db") && m.Author.ID == "228911057316347905" {
db, err := sql.Open("sqlite3", "guilds.db")
if err != nil {
fmt.Println(err.Error())
return
}
query, err := db.Prepare(parseArgs(m.Content))
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
query.Exec()
s.ChannelMessageSend(m.ChannelID, "OK")
}
if strings.HasPrefix(m.Content, "pp!candy") {
s.ChannelMessageSend(m.ChannelID, "Collected candy: "+fmt.Sprint(checkUserCandy(m.Author.ID)))
}
if strings.HasPrefix(m.Content, "pp!checkuser") {
s.ChannelMessageSend(m.ChannelID, fmt.Sprint(checkUser(m.Author.ID)))
}
if strings.HasPrefix(m.Content, "pp!rank") {
rank, err := candyRank()
if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error())
return
}
ms := &discordgo.MessageSend{
Embed: &discordgo.MessageEmbed{
Title: "Candy ranking",
Description: rank,
},
AllowedMentions: &discordgo.MessageAllowedMentions{},
}
s.ChannelMessageSendComplex(m.ChannelID, ms)
}
if strings.HasPrefix(m.Content, "pp!top") {
candy, user := topUserCandy()
s.ChannelMessageSendComplex(m.ChannelID, &discordgo.MessageSend{
Content: "Most candy earned: <@" + user + "> " + fmt.Sprint(candy),
AllowedMentions: &discordgo.MessageAllowedMentions{},
})
}
if strings.HasPrefix(m.Content, "pp!event") {
s.ChannelMessageSend(m.ChannelID, fmt.Sprint(event))
}
}