2022-07-01 02:28:20 -04:00
package main
import (
2022-07-01 02:30:35 -04:00
"flag"
"fmt"
2022-07-01 03:48:26 -04:00
"log"
2022-07-01 02:30:35 -04:00
"os"
"os/signal"
"syscall"
2022-07-01 02:28:20 -04:00
"strings"
"regexp"
"context"
2022-07-01 06:06:03 -04:00
"time"
2022-07-01 02:28:20 -04:00
2022-07-01 02:30:35 -04:00
"github.com/bwmarrin/discordgo"
2022-07-01 02:28:20 -04:00
"github.com/wader/goutubedl"
2022-07-01 03:48:26 -04:00
"mvdan.cc/xurls/v2" // Peak lazy
2022-07-01 02:28:20 -04:00
)
2022-07-01 16:46:55 -04:00
func main ( ) {
// Variables used for command line parameters
var (
commands = [ ] * discordgo . ApplicationCommand {
{
Name : "ping" ,
Description : "Hopefully replies with pong or else I'll be sad." ,
} ,
{
Name : "sping" ,
Description : "Hopefully replies with pong silently or else I'll be sad." ,
} ,
{
Name : "slowping" ,
Description : "Hopefully replies with pong 10 seconds later or else I'll be sad." ,
} ,
}
commandHandlers = map [ string ] func ( s * discordgo . Session , i * discordgo . InteractionCreate ) {
"ping" : func ( s * discordgo . Session , i * discordgo . InteractionCreate ) {
if i . Interaction . Member != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . Member . User . Username , i . Interaction . Member . User . Discriminator )
} else if i . Interaction . User != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . User . Username , i . Interaction . User . Discriminator )
}
s . InteractionRespond ( i . Interaction , & discordgo . InteractionResponse {
Type : discordgo . InteractionResponseChannelMessageWithSource ,
Data : & discordgo . InteractionResponseData {
//Flags: 1 << 6, // Only lets issuer see initial response
Content : "Pong!" ,
} ,
} )
} ,
"sping" : func ( s * discordgo . Session , i * discordgo . InteractionCreate ) {
if i . Interaction . Member != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . Member . User . Username , i . Interaction . Member . User . Discriminator )
} else if i . Interaction . User != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . User . Username , i . Interaction . User . Discriminator )
}
s . InteractionRespond ( i . Interaction , & discordgo . InteractionResponse {
Type : discordgo . InteractionResponseChannelMessageWithSource ,
Data : & discordgo . InteractionResponseData {
Flags : 1 << 6 , // Only lets issuer see initial response
Content : "Pong!" ,
} ,
} )
} ,
"slowping" : func ( s * discordgo . Session , i * discordgo . InteractionCreate ) {
if i . Interaction . Member != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . Member . User . Username , i . Interaction . Member . User . Discriminator )
} else if i . Interaction . User != nil {
log . Printf ( "%s#%s invoked ping command" , i . Interaction . User . Username , i . Interaction . User . Discriminator )
}
s . InteractionRespond ( i . Interaction , & discordgo . InteractionResponse {
Type : discordgo . InteractionResponseChannelMessageWithSource ,
Data : & discordgo . InteractionResponseData {
//Flags: 1 << 6, // Only lets issuer see initial response
Content : "No problem." ,
} ,
} )
time . Sleep ( time . Second * 10 )
_ , err := s . FollowupMessageCreate ( i . Interaction , true , & discordgo . WebhookParams {
2022-07-01 06:06:03 -04:00
Content : "Pong!" ,
2022-07-01 16:46:55 -04:00
} )
if err != nil {
log . Println ( err )
}
} ,
}
)
2022-07-01 02:28:20 -04:00
2022-07-01 16:46:55 -04:00
// Lazyinator 9001
var (
s * discordgo . Session
err error
)
2022-07-01 02:28:20 -04:00
2022-07-01 16:46:55 -04:00
// Bot params
var (
GuildID = flag . String ( "guild" , "" , "Test guild ID. If not passed - bot registers commands globally" )
BotToken = flag . String ( "token" , "" , "Bot access token" )
)
2022-07-01 02:28:20 -04:00
2022-07-01 02:30:35 -04:00
flag . Parse ( )
2022-07-01 02:28:20 -04:00
s , err = discordgo . New ( "Bot " + * BotToken )
if err != nil {
2022-07-01 02:30:35 -04:00
fmt . Println ( "error creating Discord session," , err )
return
}
2022-07-01 02:28:20 -04:00
s . AddHandler ( func ( s * discordgo . Session , i * discordgo . InteractionCreate ) {
2022-07-01 02:30:35 -04:00
if h , ok := commandHandlers [ i . ApplicationCommandData ( ) . Name ] ; ok {
h ( s , i )
}
} )
2022-07-01 02:28:20 -04:00
2022-07-01 16:46:55 -04:00
// Message to print when bot is ready to go
2022-07-01 02:30:35 -04:00
s . AddHandler ( func ( s * discordgo . Session , r * discordgo . Ready ) {
2022-07-01 03:48:26 -04:00
log . Printf ( "Logged in as: %v#%v\n" , s . State . User . Username , s . State . User . Discriminator )
2022-07-01 02:30:35 -04:00
} )
2022-07-01 02:28:20 -04:00
2022-07-01 02:30:35 -04:00
// Register the messageCreate func as a callback for MessageCreate events.
s . AddHandler ( messageCreate )
2022-07-01 02:28:20 -04:00
2022-07-01 02:30:35 -04:00
// In this example, we only care about receiving message events.
2022-07-01 06:06:03 -04:00
//s.Identify.Intents = discordgo.IntentsGuildMessages
2022-07-01 02:28:20 -04:00
2022-07-01 02:30:35 -04:00
// Open a websocket connection to Discord and begin listening.
err = s . Open ( )
if err != nil {
fmt . Println ( "error opening connection," , err )
return
}
2022-07-01 02:28:20 -04:00
2022-07-01 06:06:03 -04:00
log . Println ( "Adding commands..." )
registeredCommands , err := s . ApplicationCommandBulkOverwrite ( s . State . User . ID , * GuildID , commands )
if err != nil {
log . Panic ( err )
}
2022-07-01 02:28:20 -04:00
// Just incase
defer s . Close ( )
2022-07-01 02:30:35 -04:00
// Wait here until CTRL-C or other term signal is received.
2022-07-01 16:46:55 -04:00
log . Println ( "Bot is running. Press CTRL-C to exit." )
2022-07-01 02:30:35 -04:00
sc := make ( chan os . Signal , 1 )
signal . Notify ( sc , syscall . SIGINT , syscall . SIGTERM , os . Interrupt , os . Kill )
<- sc
2022-07-01 02:28:20 -04:00
2022-07-01 16:46:55 -04:00
log . Printf ( "Signal received, closing bot..." )
2022-07-01 02:30:35 -04:00
// Cleanly close down the Discord session.
2022-07-01 06:06:03 -04:00
for _ , v := range registeredCommands {
err := s . ApplicationCommandDelete ( s . State . User . ID , * GuildID , v . ID )
if err != nil {
log . Panicf ( "Cannot delete '%v' command: %v" , v . Name , err )
}
}
2022-07-01 02:30:35 -04:00
s . Close ( )
2022-07-01 02:28:20 -04:00
}
// 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 ) {
2022-07-01 02:30:35 -04:00
// Ignore all messages created by the bot itself
// This isn't required in this specific example but it's a good practice.
if m . Author . ID == s . State . User . ID {
return
}
2022-07-01 02:28:20 -04:00
/ *
// If the message is "ping" reply with "Pong!"
2022-07-01 02:30:35 -04:00
if m . Content == "ping" {
s . ChannelMessageSend ( m . ChannelID , "Pong!" )
}
// If the message is "pong" reply with "Ping!"
if m . Content == "pong" {
s . ChannelMessageSend ( m . ChannelID , "Ping!" )
}
2022-07-01 02:28:20 -04:00
* /
2022-07-01 16:46:55 -04:00
//log.Printf("[%s] %s#%s: %s", m.ID, m.Author.Username, m.Author.Discriminator, m.Content)
2022-07-01 03:48:26 -04:00
rxStrict := xurls . Strict ( )
urls := rxStrict . FindAllString ( m . Content , - 1 )
if len ( urls ) > 0 {
2022-07-01 02:28:20 -04:00
message := discordgo . MessageSend {
Content : "Woah there partner! I detect some services that don't embed very well in Discord. Let me help you with that!\n" ,
Reference : m . Reference ( ) ,
2022-07-01 03:48:26 -04:00
Files : [ ] * discordgo . File { } ,
2022-07-01 02:28:20 -04:00
}
2022-07-01 03:48:26 -04:00
log . Println ( "URLs detected!" )
2022-07-01 02:28:20 -04:00
2022-07-01 04:12:20 -04:00
respond := false
2022-07-01 03:48:26 -04:00
for _ , url := range urls {
2022-07-01 04:16:08 -04:00
if output , _ := regexp . MatchString ( "http.*twitter.com/.*/status" , url ) ; output {
log . Println ( "Cringe twitter post detected." )
2022-07-01 02:28:20 -04:00
goutubedl . Path = "yt-dlp"
result , err := goutubedl . New ( context . Background ( ) , url , goutubedl . Options { } )
if err != nil {
2022-07-01 04:12:20 -04:00
// Probably no videos in it, don't care
log . Println ( err )
//s.ChannelMessageSend(m.ChannelID, err.Error())
2022-07-01 03:48:26 -04:00
continue
2022-07-01 02:28:20 -04:00
}
2022-07-01 04:12:20 -04:00
// Get rid of the stupid short URL that Shitter appends to everything
2022-07-01 04:16:53 -04:00
message . Content = message . Content + fmt . Sprintf ( "\"%s\"\n" , strings . Trim ( regexp . MustCompile ( "https://t.co/.*" ) . ReplaceAllString ( result . Info . Description , "" ) , " " ) ) // Still ugly
2022-07-01 02:28:20 -04:00
2022-07-01 03:48:26 -04:00
var choice goutubedl . Format
2022-07-01 02:28:20 -04:00
for i := len ( result . Formats ( ) ) - 1 ; i >= 0 ; i -- {
size := result . Formats ( ) [ i ] . FilesizeApprox
if size < 8 * 1024 * 1024 {
2022-07-01 03:48:26 -04:00
choice = result . Formats ( ) [ i ]
log . Printf ( "Choice: %s | Size: %fM\n" , choice . FormatID , size / 1024 / 1024 )
2022-07-01 02:28:20 -04:00
break
}
}
2022-07-01 03:48:26 -04:00
downloadResult , err := result . Download ( context . Background ( ) , choice . FormatID )
2022-07-01 02:28:20 -04:00
if err != nil {
2022-07-01 04:12:20 -04:00
log . Println ( err )
//s.ChannelMessageSend(m.ChannelID, err.Error())
2022-07-01 03:48:26 -04:00
continue
2022-07-01 02:28:20 -04:00
}
2022-07-01 03:48:26 -04:00
message . Files = append ( message . Files , & discordgo . File {
Name : fmt . Sprintf ( "%s.%s" , result . Info . ID , choice . Ext ) ,
ContentType : "text/plain" , // This is of course not true, but Discord doesn't give a shit
Reader : downloadResult ,
} )
2022-07-01 02:28:20 -04:00
2022-07-01 04:12:20 -04:00
respond = true
2022-07-01 03:48:26 -04:00
defer downloadResult . Close ( )
2022-07-01 02:28:20 -04:00
}
}
2022-07-01 04:12:20 -04:00
if respond {
if message , err := s . ChannelMessageSendComplex ( m . ChannelID , & message ) ; err != nil {
log . Println ( message )
log . Println ( err )
} else {
log . Printf ( "Successfully responded to %s" , m . ID )
}
2022-07-01 03:48:26 -04:00
}
2022-07-01 02:28:20 -04:00
}
}