Compare commits
No commits in common. "7f95c31498756636172a9fbf4ee9f4e8140642b0" and "50513cf3cd7fe6844b5c670aed687c32019f63b7" have entirely different histories.
7f95c31498
...
50513cf3cd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
config.json
|
|
4
config.json
Normal file
4
config.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"discord_bot_token": "MTIxNzA3NDM3ODE1MjM0NTcwMA.G5Evvi.AQ571YcyJK-Zt1RflylKU1K1Cnwuf80LOD43qw",
|
||||||
|
"discord_channel_id": "590581442392621067"
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"discord_bot_token": "YOUR_BOT_TOKEN",
|
|
||||||
"role_map": {
|
|
||||||
"Role 1": "ROLE_ID_NUMBER",
|
|
||||||
"Role 2": "ROLE_ID_NUMBER",
|
|
||||||
"Role 3": "ROLE_ID_NUMBER"
|
|
||||||
},
|
|
||||||
"channel_map": {
|
|
||||||
"Channel 1": "ROLE_ID_NUMBER",
|
|
||||||
"Channel 2": "ROLE_ID_NUMBER",
|
|
||||||
"Channel 3": "ROLE_ID_NUMBER"
|
|
||||||
},
|
|
||||||
"url": "https://fallout.bethesda.net/en/news"
|
|
||||||
}
|
|
198
main.go
198
main.go
@ -15,21 +15,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DiscordBotToken string `json:"discord_bot_token"`
|
DiscordBotToken string `json:"discord_bot_token"`
|
||||||
ChannelMap map[string]string `json:"channel_map"`
|
DiscordChannelID string `json:"discord_channel_id"` // Add more configuration fields here
|
||||||
RoleMap map[string]string `json:"role_map"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
//Initialize Time
|
|
||||||
//date := "April 16, 2024"
|
|
||||||
date := time.Now().Format("January 2, 2006")
|
|
||||||
|
|
||||||
// At the beginning of the main function
|
|
||||||
log.Println("Starting the bot...")
|
|
||||||
|
|
||||||
// Open and read the configuration file
|
// Open and read the configuration file
|
||||||
configFile, err := os.Open("config.json")
|
configFile, err := os.Open("config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,32 +37,17 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// After loading the configuration
|
// Access the Discord bot token from the configuration
|
||||||
log.Println("Loaded configuration from config.json")
|
|
||||||
|
|
||||||
// Access the Discord bot token and channel ID from the configuration
|
|
||||||
token := config.DiscordBotToken
|
token := config.DiscordBotToken
|
||||||
if token == "" {
|
if token == "" {
|
||||||
fmt.Println("Discord bot token is not set in config file")
|
fmt.Println("Discord bot token is not set in config file")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
channelMap := config.ChannelMap
|
//
|
||||||
if len(channelMap) == 0 {
|
channelID := config.DiscordChannelID
|
||||||
fmt.Println("Channel map is not set in config file")
|
if channelID == "" {
|
||||||
return
|
fmt.Println("Discord channel ID is not set in config file")
|
||||||
}
|
|
||||||
|
|
||||||
roleMap := config.RoleMap
|
|
||||||
if len(roleMap) == 0 {
|
|
||||||
fmt.Println("Role map is not set in config file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
url := config.URL
|
|
||||||
if url == "" {
|
|
||||||
fmt.Println("URL is not set in config file")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Discord session using the provided bot token
|
// Create a new Discord session using the provided bot token
|
||||||
@ -81,23 +57,20 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// After creating the Discord session
|
|
||||||
log.Println("Created Discord session")
|
|
||||||
|
|
||||||
// Register messageCreate as a callback for the messageCreate events
|
// Register messageCreate as a callback for the messageCreate events
|
||||||
dg.AddHandler(messageCreate)
|
dg.AddHandler(messageCreate)
|
||||||
|
|
||||||
|
dg.AddHandler(message2Create)
|
||||||
|
|
||||||
// Open a websocket connection to Discord and begin listening
|
// Open a websocket connection to Discord and begin listening
|
||||||
err = dg.Open()
|
err = dg.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error opening Discord connection:", err)
|
fmt.Println("Error opening Discord connection:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// After opening the Discord connection
|
|
||||||
log.Println("Opened Discord connection")
|
|
||||||
|
|
||||||
// Run the scraping and message sending function at start up
|
// Run the scraping and message sending function once at the specified time
|
||||||
sendNotifications(dg, fetchUrl(url), channelMap, roleMap, date)
|
sendNotifications(dg, channelID, scrapeNews())
|
||||||
|
|
||||||
// Schedule the scraping and message sending function to run once a day
|
// Schedule the scraping and message sending function to run once a day
|
||||||
ticker := time.NewTicker(24 * time.Hour)
|
ticker := time.NewTicker(24 * time.Hour)
|
||||||
@ -108,17 +81,19 @@ func main() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
sendNotifications(dg, fetchUrl(url), channelMap, roleMap, date)
|
sendNotifications(dg, channelID, scrapeNews())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
//test()
|
||||||
|
|
||||||
// Wait here until CTRL-C or other term signal is received
|
// Wait here until CTRL-C or other term signal is received
|
||||||
fmt.Println("Bot is now running. Press CTRL-C to exit.")
|
fmt.Println("Bot is now running. Press CTRL-C to exit.")
|
||||||
<-make(chan struct{})
|
<-make(chan struct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchUrl(url string) string {
|
func scrapeNews() string {
|
||||||
// Create a new context
|
// Create a new context
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx, cancel := chromedp.NewContext(
|
ctx, cancel := chromedp.NewContext(
|
||||||
@ -130,7 +105,7 @@ func fetchUrl(url string) string {
|
|||||||
// Navigate to the Fallout news page
|
// Navigate to the Fallout news page
|
||||||
var html string
|
var html string
|
||||||
err := chromedp.Run(ctx, chromedp.Tasks{
|
err := chromedp.Run(ctx, chromedp.Tasks{
|
||||||
chromedp.Navigate(url),
|
chromedp.Navigate("https://fallout.bethesda.net/en/news"),
|
||||||
chromedp.OuterHTML("html", &html),
|
chromedp.OuterHTML("html", &html),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -142,107 +117,59 @@ func fetchUrl(url string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a function to extract relevant tags from the HTML content
|
// Add a function to extract relevant tags from the HTML content
|
||||||
func extractNewsArticles(html string) []map[string]string {
|
func extractTags(html string) []string {
|
||||||
var articles []map[string]string
|
var tags []string
|
||||||
|
|
||||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error parsing HTML:", err)
|
fmt.Println("Error parsing HTML:", err)
|
||||||
return articles
|
return tags
|
||||||
}
|
}
|
||||||
|
// Find and extract tags with class name "news-module-feed-item-details-tag"
|
||||||
// Find and extract each article
|
doc.Find("span.news-module-feed-item-details-tag").Each(func(i int, s *goquery.Selection) {
|
||||||
doc.Find("article.news-module-feed-item").Each(func(i int, s *goquery.Selection) {
|
tag := strings.TrimSpace(s.Text())
|
||||||
article := make(map[string]string)
|
tags = append(tags, tag)
|
||||||
|
|
||||||
// Extract link
|
|
||||||
link, exists := s.Find("a.news-module-feed-item-image").Attr("href")
|
|
||||||
if exists {
|
|
||||||
article["link"] = "https://fallout.bethesda.net" + link
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract title
|
|
||||||
title := strings.TrimSpace(s.Find("h3.news-module-feed-item-title").Text())
|
|
||||||
article["title"] = title
|
|
||||||
|
|
||||||
// Extract tag
|
|
||||||
tag := strings.TrimSpace(s.Find("span.news-module-feed-item-details-tag").Text())
|
|
||||||
article["tag"] = tag
|
|
||||||
|
|
||||||
// Extract date
|
|
||||||
date := strings.TrimSpace(s.Find("span.news-module-feed-item-details-date").Text())
|
|
||||||
article["date"] = date
|
|
||||||
|
|
||||||
// Extract game
|
|
||||||
game := strings.TrimSpace(s.Find("span.news-module-feed-item-details-game").Text())
|
|
||||||
article["game"] = game
|
|
||||||
|
|
||||||
// Extract blurb
|
|
||||||
blurb := strings.TrimSpace(s.Find("p.news-module-feed-item-blurb").Text())
|
|
||||||
article["blurb"] = blurb
|
|
||||||
|
|
||||||
// Extract image URL
|
|
||||||
imageURL, exists := s.Find("img.news-module-feed-item-image-tag").Attr("src")
|
|
||||||
if exists {
|
|
||||||
article["imageURL"] = "https:" + imageURL
|
|
||||||
}
|
|
||||||
|
|
||||||
articles = append(articles, article)
|
|
||||||
})
|
})
|
||||||
|
return tags
|
||||||
return articles
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendNotifications(session *discordgo.Session, html string, channelMap, roleMap map[string]string, specifiedDate string) {
|
// Define a map to associate each desired tag with its corresponding Discord channel ID
|
||||||
// Extract articles from the HTML content
|
var tagChannelMap = map[string]string{
|
||||||
articles := extractNewsArticles(html)
|
"Patch Notes": "556093419341086749",
|
||||||
|
"Atomic Shop": "590581442392621067",
|
||||||
|
"News": "558335339018846228",
|
||||||
|
// Add more tags and corresponding channel IDs as needed
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate over extracted articles
|
func sendNotifications(session *discordgo.Session, channelID string, html string) {
|
||||||
for _, article := range articles {
|
// Extract tags from the HTML content
|
||||||
tag := article["tag"]
|
tags := extractTags(html)
|
||||||
date := article["date"]
|
|
||||||
link := article["link"]
|
|
||||||
blurb := article["blurb"]
|
|
||||||
title := article["title"]
|
|
||||||
imageURL := article["imageURL"]
|
|
||||||
|
|
||||||
|
// Define today's date string
|
||||||
|
today := time.Now().Format("January 2, 2006")
|
||||||
|
|
||||||
|
// Iterate over extracted tags
|
||||||
|
for _, tag := range tags {
|
||||||
// Check if the tag is in the desired tags list
|
// Check if the tag is in the desired tags list
|
||||||
if channelID, ok := channelMap[tag]; ok {
|
if tagChannelID, ok := tagChannelMap[tag]; ok {
|
||||||
// Check if the article's date matches the specified date
|
// Check if today's date matches the tag
|
||||||
if date == specifiedDate {
|
if tag == today {
|
||||||
// Create a rich embed
|
|
||||||
embed := &discordgo.MessageEmbed{
|
|
||||||
Title: title,
|
|
||||||
Description: blurb,
|
|
||||||
URL: link,
|
|
||||||
Image: &discordgo.MessageEmbedImage{
|
|
||||||
URL: imageURL,
|
|
||||||
},
|
|
||||||
Color: 0x00ff00, // Green color for the embed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a message to the corresponding Discord channel
|
// Send a message to the corresponding Discord channel
|
||||||
message := fmt.Sprintf("New <@&%s> have been released!", roleMap[tag])
|
message := fmt.Sprintf("Today's date matches the tag '%s' on the Fallout news page!", tag)
|
||||||
_, err := session.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{
|
_, err := session.ChannelMessageSend(tagChannelID, message)
|
||||||
Content: message,
|
|
||||||
Embed: embed,
|
|
||||||
AllowedMentions: &discordgo.MessageAllowedMentions{}, // Allow mentions
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error sending message to Discord channel %s: %s\n", channelID, err)
|
fmt.Printf("Error sending message to Discord channel %s: %s\n", tagChannelID, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Println("Message sent to Discord channel:", channelID)
|
fmt.Println("Message sent to Discord channel:", tagChannelID)
|
||||||
|
} else {
|
||||||
// Tag the corresponding role
|
// Send a different message indicating the tag was found
|
||||||
//if roleID, ok := roleMap[tag]; ok {
|
message := fmt.Sprintf("Tag '%s' found on the Fallout news page, but it's not today's date.", tag)
|
||||||
// _, err := session.ChannelMessageSend(channelID, fmt.Sprintf("<@&%s>", roleID))
|
_, err := session.ChannelMessageSend(tagChannelID, message)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// fmt.Printf("Error tagging role %s in Discord channel %s: %s\n", roleID, channelID, err)
|
fmt.Printf("Error sending message to Discord channel %s: %s\n", tagChannelID, err)
|
||||||
// } else {
|
continue
|
||||||
// fmt.Printf("Role %s tagged in Discord channel %s\n", roleID, channelID)
|
}
|
||||||
// }
|
fmt.Println("Message sent to Discord channel:", tagChannelID)
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +183,20 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the message content is "!hello", respond with "Hello!"
|
// If the message content is "!hello", respond with "Hello!"
|
||||||
if m.Content == "!hello" {
|
if m.Content == "!hello1" {
|
||||||
_, _ = s.ChannelMessageSend(m.ChannelID, "Hello!")
|
_, _ = s.ChannelMessageSend(m.ChannelID, "Hello!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function will be called whenever a new message is created
|
||||||
|
func message2Create(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
|
// Ignore messages created by the bot itself
|
||||||
|
if m.Author.ID == s.State.User.ID {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the message content is "!hello", respond with "Hello!"
|
||||||
|
if m.Content == "!hello" {
|
||||||
|
_, _ = s.ChannelMessageSend(m.ChannelID, "You are SUCH a NERD")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
21
readme.md
21
readme.md
@ -1,19 +1,4 @@
|
|||||||
# Fallout News Discord Bot
|
go mod download
|
||||||
|
go run main.go
|
||||||
|
|
||||||
## PreReqs
|
right now it scrapes bethesda news and spit back dates in console and prints if today is today
|
||||||
|
|
||||||
- Go
|
|
||||||
- Discord Developer Bot Credentials
|
|
||||||
- Discord Channels IDs
|
|
||||||
- Discord Role IDs
|
|
||||||
|
|
||||||
## Get Started
|
|
||||||
|
|
||||||
Go Get dependancies
|
|
||||||
`go mod download`
|
|
||||||
|
|
||||||
`cp example.config.json config.json`
|
|
||||||
fill out credentials in config with your information
|
|
||||||
|
|
||||||
Run the Bot:
|
|
||||||
`go run main.go`
|
|
||||||
|
Loading…
Reference in New Issue
Block a user