139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"rockhu-bot/local/model"
|
|
"rockhu-bot/local/repository"
|
|
"rockhu-bot/local/utl/common"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gocolly/colly"
|
|
"gorm.io/datatypes"
|
|
)
|
|
|
|
type ConcertService struct {
|
|
repository *repository.ConcertRepository
|
|
}
|
|
|
|
func NewConcertService(repository *repository.ConcertRepository) *ConcertService {
|
|
return &ConcertService{
|
|
repository: repository,
|
|
}
|
|
}
|
|
|
|
// GetFirst
|
|
// Gets first row from Concert table.
|
|
//
|
|
// Args:
|
|
// context.Context: Application context
|
|
// Returns:
|
|
// string: Application version
|
|
func (as ConcertService) GetAll(ctx context.Context) *[]model.ConcertModel {
|
|
return as.repository.GetAll(ctx)
|
|
}
|
|
|
|
func (as ConcertService) CheckAndUpdateConcerts(ctx context.Context) []model.ConcertModel {
|
|
cm := as.GetAll(ctx)
|
|
fmt.Printf("Currently there are %d concerts\n", len(*cm))
|
|
NewConcerts := scrapeData(ctx)
|
|
fmt.Printf("There are %d new concerts\n", len(*NewConcerts))
|
|
forInsert, forDelete, _ := partitionConcerts(*cm, *NewConcerts)
|
|
|
|
tx := as.repository.CreateTransaction()
|
|
defer tx.Rollback()
|
|
|
|
if len(forDelete) > 0 {
|
|
tx.Delete(forDelete)
|
|
}
|
|
if len(forInsert) > 0 {
|
|
tx.Create(forInsert)
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
return forInsert
|
|
}
|
|
|
|
func scrapeData(ctx context.Context) *[]model.ConcertModel {
|
|
c := colly.NewCollector()
|
|
concerts := new([]model.ConcertModel)
|
|
|
|
// Find and visit all links
|
|
c.OnHTML(".event_box", func(e *colly.HTMLElement) {
|
|
currentDate := time.Now()
|
|
currentMonth := currentDate.Month()
|
|
month, err := common.GetMonthFromLocalized(e.ChildText(".event_date>.month"))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
dayText := e.ChildText(".event_date>.day")
|
|
day, err := strconv.Atoi(dayText)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
year := currentDate.Year()
|
|
if month < int(currentMonth) {
|
|
year = year + 1
|
|
}
|
|
|
|
eventDate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
|
|
concert := new(model.ConcertModel)
|
|
concert.Name = e.ChildText(".event_title")
|
|
concert.StartDate = datatypes.Date(eventDate)
|
|
*concerts = append(*concerts, *concert)
|
|
})
|
|
|
|
c.OnRequest(func(r *colly.Request) {
|
|
fmt.Println("Visiting", r.URL)
|
|
})
|
|
|
|
c.Visit("https://jegy.rock1.hu/")
|
|
|
|
return concerts
|
|
}
|
|
|
|
func concertKey(concert model.ConcertModel) string {
|
|
cc := concert.Name + (time.Time)(concert.StartDate).Format("2006-01-02")
|
|
fmt.Println(cc)
|
|
return cc
|
|
}
|
|
|
|
func partitionConcerts(previous, current []model.ConcertModel) (newConcerts, deletedConcerts, unchangedConcerts []model.ConcertModel) {
|
|
// Create a map of previous concerts for quick lookup
|
|
fmt.Println("Previous concerts\n")
|
|
previousMap := make(map[string]model.ConcertModel)
|
|
for _, concert := range previous {
|
|
previousMap[concertKey(concert)] = concert
|
|
}
|
|
|
|
fmt.Println("New concerts\n")
|
|
// Create a map of current concerts for quick lookup
|
|
currentMap := make(map[string]model.ConcertModel)
|
|
for _, concert := range current {
|
|
currentMap[concertKey(concert)] = concert
|
|
}
|
|
|
|
// Identify new and unchanged concerts
|
|
for _, concert := range current {
|
|
if _, exists := previousMap[concertKey(concert)]; exists {
|
|
unchangedConcerts = append(unchangedConcerts, concert)
|
|
} else {
|
|
newConcerts = append(newConcerts, concert)
|
|
fmt.Printf("New concert %s\n", concert.Name)
|
|
}
|
|
}
|
|
|
|
// Identify deleted concerts
|
|
for _, concert := range previous {
|
|
if _, exists := currentMap[concertKey(concert)]; !exists {
|
|
deletedConcerts = append(deletedConcerts, concert)
|
|
fmt.Printf("Deleted concert %s\n", concert.Name)
|
|
}
|
|
}
|
|
|
|
return newConcerts, deletedConcerts, unchangedConcerts
|
|
}
|