Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lezioni per generici corsi di laurea #138

Merged
merged 21 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ func run(bot *tgbotapi.BotAPI) {

for update := range updates {
if update.Message == nil {
callback := tgbotapi.NewCallback(update.CallbackQuery.ID, update.CallbackQuery.Data)
if _, err := bot.Request(callback); err != nil {
log.Printf("Error [bot.Request() for the callback]: %s\n", err)
continue
}

callback_text := update.CallbackQuery.Data

if strings.HasPrefix(callback_text, "lectures_") {
handleCallback(bot, &update, "lezioni", callback_text)
}

continue
} else if filterMessage(bot, update.Message) {
continue
Expand Down Expand Up @@ -229,6 +241,15 @@ func executeCommand(bot *tgbotapi.BotAPI, update *tgbotapi.Update, commandIndex
if newCommand.HasNextCommand() {
handleAction(bot, update, newCommand.NextCommand)
}

if newCommand.HasRows() {
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
msg.ReplyMarkup = newCommand.Rows
if _, err := bot.Send(msg); err != nil {
msg = tgbotapi.NewMessage(update.Message.Chat.ID, "Error sending data")
bot.Send(msg)
}
}
}
}

Expand All @@ -247,6 +268,21 @@ func handleAction(bot *tgbotapi.BotAPI, update *tgbotapi.Update, commandName str
return false
}

// Handle a callback searching a the good action
func handleCallback(bot *tgbotapi.BotAPI, update *tgbotapi.Update, commandName string, callback_text string) bool {
idx := slices.IndexFunc(model.Actions, func(action model.Action) bool {
return action.Name == commandName
})

if idx != -1 {
model.Actions[idx].Data.HandleBotCallback(bot, update, callback_text)

return true
}

return false
}

func filterMessage(bot *tgbotapi.BotAPI, message *tgbotapi.Message) bool {
if message.Dice != nil {
// msg := tgbotapi.NewMessage(message.Chat.ID, "Found a dice")
Expand Down
4 changes: 2 additions & 2 deletions commands/uni.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ func (t *LezioniTime) UnmarshalJSON(data []byte) error {

// GetTimeTable returns an HTML string containing the timetable for the given
// course on the given date. Returns an empty string if there are no lessons.
func GetTimeTable(courseType, courseName string, year int, day time.Time) (string, error) {
func GetTimeTable(courseType, courseName string, curriculum string, year int, day time.Time) (string, error) {

interval := &timetable.Interval{Start: day, End: day}
events, err := timetable.FetchTimetable(courseType, courseName, "", year, interval)
events, err := timetable.FetchTimetable(courseType, courseName, curriculum, year, interval)
if err != nil {
log.Printf("Error getting timetable: %s\n", err)
return "", err
Expand Down
5 changes: 3 additions & 2 deletions commands/uni_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func TestGetTimeTable(t *testing.T) {
courseName string
year int
day time.Time
curriculum string
}
tests := []struct {
name string
Expand Down Expand Up @@ -145,7 +146,7 @@ func TestGetTimeTable(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetTimeTable(tt.args.courseType, tt.args.courseName, tt.args.year, tt.args.day)
got, err := GetTimeTable(tt.args.courseType, tt.args.courseName, tt.args.curriculum, tt.args.year, tt.args.day)
if err != nil && !tt.error {
t.Errorf("GetTimeTable() error = %v", err)
return
Expand All @@ -163,7 +164,7 @@ func TestGetTimeTable(t *testing.T) {
func TestWeekend(t *testing.T) {

date := time.Date(2023, 3, 11, 0, 0, 0, 0, time.UTC)
result, err := GetTimeTable("laurea", "informatica", 1, date)
result, err := GetTimeTable("laurea", "informatica", "", 1, date)
if err != nil {
t.Fatalf("Error while getting timetable: %s", err)
}
Expand Down
96 changes: 5 additions & 91 deletions json/actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,98 +91,12 @@
"text": "<b>Lauree Triennali</b>\n\nInformatica\n1\ufe0f\u20e3 1\u00b0 anno (<a href='https://t.me/uniboinfo23'>Telegram</a>, <a href='https://discord.gg/8TWKqfVF'>Discord</a>)\n2\ufe0f\u20e3 2\u00b0 anno (<a href='https://t.me/uniboinfo2223'>Telegram</a>, <a href='https://discord.gg/2cK8ENJ2Vg'>Discord</a>)\n3\ufe0f\u20e3 3\u00b0 anno (<a href='https://t.me/joinchat/jTyZ03cqDRliOTY0'>Telegram</a>, <a href='https://discord.gg/cYFbnGEYAA'>Discord</a>)\n3\ufe0f\u20e3 Ex-3\u00b0 anno (<a href='https://t.me/informaticaunibo2021'>Telegram</a>, <a href='https://discord.gg/N7NJms8d7v'>Discord</a>)\n<a href='https://www.reddit.com/r/unibo_informatica'><b>\ud83d\uddff Subreddit</b></a>\n\nIngegneria Informatica\n1\ufe0f\u20e32\ufe0f\u20e33\ufe0f\u20e3 Tutti gli anni(<a href='https://chat.whatsapp.com/HB1Gp5ZlMzR9xIhgUwEkrA'>Whatsapp</a>)\n4\ufe0f\u20e3 Ex-3\u00b0 anno(<a href='https://t.me/+R7CwyJOvG0AMPRHy'>Telegram</a>)\n\nIngegneria e Science informatiche (Cesena)\n1\ufe0f\u20e32\ufe0f\u20e33\ufe0f\u20e3 Tutti gli anni(<a href='https://chat.whatsapp.com/EA4ndjtOnIa6d8xPwSYA6Q'>Whatsapp</a>)\n\nInformatica per il Management\n1\ufe0f\u20e32\ufe0f\u20e33\ufe0f\u20e3 Tutti gli anni(<a href='https://t.me/unibo_info_manag'>Telegram</a>)\n\n<b>Lauree Magistrali</b>\n\nInformatica\n1\ufe0f\u20e32\ufe0f\u20e3 Tutti gli anni(<a href='https://t.me/mag_informatica_unibo'>Telegram</a>)\n\nArtificial Intelligence\n1\ufe0f\u20e3 1\u00b0 anno (<a href='https://t.me/officialai2324'>Telegram</a>)\n2\ufe0f\u20e3 2\u00b0 anno (<a href='https://t.me/unibo_ai_2022'>Telegram</a>)\n\nIngegneria e Science informatiche (Cesena)\n1\ufe0f\u20e32\ufe0f\u20e3 Tutti gli anni (<a href='https://chat.whatsapp.com/BgwpLOTuBN543W4bjsOxnl'>Whatsapp</a>, <a href='https://t.me/joinchat/BMT7WBYtBSdduMJdhjs3Ew'>Telegram</a>)\n\n<a href='https://t.me/joinchat/4_SVcmVsRAo3MTlk'>\ud83d\udd22 Tutti i gruppi Unibo</a>"
}
},
"lezionioggi": {
"type": "yearly",
"lezioni": {
"type": "buttonsLecture",
"data": {
"description": "Orari lezioni di oggi (tuo anno)",
"command": "lezionioggi",
"noYear": "Questo non sembra essere un gruppo generale per nessun anno di corso. Per usare questo comando da qui, devi specificare /lezionioggi1, /lezionioggi2 o /lezionioggi3."
}
},
"lezionioggi1": {
"type": "todayLectures",
"data": {
"description": "Orari lezioni di oggi (1\u00b0 anno)",
"course": {
"year": 1,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di oggi (1\u00b0 anno):</b>\n",
"fallbackText": "Non ci sono lezioni oggi. SMETTILA DI PRESSARMI"
}
},
"lezionioggi2": {
"type": "todayLectures",
"data": {
"description": "Orari lezioni di oggi (2\u00b0 anno)",
"course": {
"year": 2,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di oggi (2\u00b0 anno):</b>\n",
"fallbackText": "Non ci sono lezioni oggi. SMETTILA DI PRESSARMI"
}
},
"lezionioggi3": {
"type": "todayLectures",
"data": {
"description": "Orari lezioni di oggi (3\u00b0 anno)",
"course": {
"year": 3,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di oggi:</b>\n",
"fallbackText": "Non ci sono lezioni oggi. SMETTILA DI PRESSARMI"
}
},
"lezionidomani": {
"type": "yearly",
"data": {
"description": "Orari lezioni di domani (tuo anno)",
"command": "lezionidomani",
"noYear": "Questo non sembra essere un gruppo generale per nessun anno di corso. Per usare questo comando da qui, devi specificare /lezionidomani1, /lezionidomani2 o /lezionidomani3."
}
},
"lezionidomani1": {
"type": "tomorrowLectures",
"data": {
"description": "Orari lezioni di domani (1\u00b0 anno)",
"course": {
"year": 1,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di domani (1\u00b0 anno):</b>\n",
"fallbackText": "Non ci sono lezioni domani. SMETTILA DI PRESSARMI"
}
},
"lezionidomani2": {
"type": "tomorrowLectures",
"data": {
"description": "Orari lezioni di domani (2\u00b0 anno)",
"course": {
"year": 2,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di domani (2\u00b0 anno):</b>\n",
"fallbackText": "Non ci sono lezioni domani. SMETTILA DI PRESSARMI"
}
},
"lezionidomani3": {
"type": "tomorrowLectures",
"data": {
"description": "Orari lezioni di domani (3\u00b0 anno)",
"course": {
"year": 3,
"type": "laurea",
"name": "informatica"
},
"title": "<b>Lezioni di domani (3\u00b0 anno):</b>\n",
"fallbackText": "Non ci sono lezioni domani. SMETTILA DI PRESSARMI"
"description": "Orari lezioni",
"title": " <b>Lezioni di %s di (%d\u00b0 anno) di giorno %s</b>",
"fallbackText": "Non ci sono lezioni in questo giorno. SMETTILA DI PRESSARMI"
}
},
"materiali": {
Expand Down
123 changes: 123 additions & 0 deletions model/callback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package model

import (
"fmt"
"log"
"regexp"
"strconv"
"strings"
"time"

tgbotapi "github.com/musianisamuele/telegram-bot-api"

"github.com/csunibo/informabot/commands"
)

func (_ MessageData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `MessageData`")
}

func (_ HelpData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `HelpData`")
}

func (_ IssueData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `IssueData`")
}

func (_ LookingForData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `LookingForData`")
}

func (_ NotLookingForData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `NotLookingForData`")
}

// Handle the callback for the lectures command (`/lezioni`)
// Parse the `callback_text` to check which operation it must to do:
// - If the string ends with "_today" or "_tomorrow" it returns the timetable
// - If the string just contains a "_y_<number>" it asks for today or tomorrow
// - Otherwise prints the course year of what timetable the user wants to see
func (data Lectures) HandleBotCallback(bot *tgbotapi.BotAPI, update *tgbotapi.Update, callback_text string) {
var chatId = int64(update.CallbackQuery.Message.Chat.ID)
var messageId = update.CallbackQuery.Message.MessageID

if strings.Contains(callback_text, "_day_") {
dayRegex, err := regexp.Compile(`_day_(\d+)`)
if err != nil {
log.Printf("Error [dayRegex]: %s\n", err)
return
}

unixTime, err := strconv.ParseInt(dayRegex.FindString(callback_text)[5:], 10, 64)
if err != nil {
log.Printf("Error [unixTime]: %s\n", err)
return
}

timeForLectures := time.Unix(unixTime, 0)

yearRegex, err := regexp.Compile(`_y_(\d)_`)
if err != nil {
log.Printf("Error [yearRegex]: %s\n", err)
return
}

year, err := strconv.Atoi(yearRegex.FindString(callback_text)[3:4])
if err != nil {
log.Printf("Error [convert to integer the year regex]: %s\n", err)
return
}

timetableKey := callback_text[len("lectures_"):strings.Index(callback_text, "_y_")]

timetable := Timetables[timetableKey]
response, err := commands.GetTimeTable(timetable.Type, timetable.Name, timetable.Curriculum, year, timeForLectures)
if err != nil {
log.Printf("Error [GetTimeTable]: %s\n", err)
}

if response == "" {
response = data.FallbackText
} else {
response = fmt.Sprintf(data.Title, timetable.Course, year, timeForLectures.Format("2006-01-02")) + "\n\n" + response
}

editConfig := tgbotapi.NewEditMessageText(chatId, messageId, response)
editConfig.ParseMode = tgbotapi.ModeHTML

_, err = bot.Send(editConfig)
if err != nil {
log.Printf("Error [bot.Send() for the NewEditMessageText]: %s\n", err)
}
} else if strings.Contains(callback_text, "_y_") {
rows := ChooseTimetableDay(callback_text)
keyboard := tgbotapi.NewInlineKeyboardMarkup(rows...)
editConfig := tgbotapi.NewEditMessageReplyMarkup(chatId, messageId, keyboard)
_, err := bot.Send(editConfig)
if err != nil {
log.Printf("Error [bot.Send() for the NewEditMessageReplyMarkup]: %s\n", err)
}
} else {
timetableName := strings.TrimPrefix(callback_text, "lectures_")
rows := GetLectureYears(callback_text, Timetables[timetableName].Course)
keyboard := tgbotapi.NewInlineKeyboardMarkup(rows...)
editConfig := tgbotapi.NewEditMessageReplyMarkup(chatId, messageId, keyboard)
_, err := bot.Send(editConfig)
if err != nil {
log.Printf("Error [bot.Send() for the NewEditMessageReplyMarkup]: %s\n", err)
}
}
}

func (_ ListData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `ListData`")
}

func (_ LuckData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `LuckData`")
}

func (_ InvalidData) HandleBotCallback(_bot *tgbotapi.BotAPI, _udpate *tgbotapi.Update, _callback_text string) {
log.Printf("`HandleBotCallback` not defined for `InvalidData`")
}
58 changes: 4 additions & 54 deletions model/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
tgbotapi "github.com/musianisamuele/telegram-bot-api"
"golang.org/x/exp/slices"

"github.com/csunibo/informabot/commands"
"github.com/csunibo/informabot/utils"
)

Expand Down Expand Up @@ -144,59 +143,10 @@ func (data NotLookingForData) HandleBotCommand(_ *tgbotapi.BotAPI, message *tgbo
return makeResponseWithText(msg)
}

func (data YearlyData) HandleBotCommand(_ *tgbotapi.BotAPI, message *tgbotapi.Message) CommandResponse {
chatTitle := strings.ToLower(message.Chat.Title)

// check if string contains the year number
if strings.Contains(chatTitle, "primo") ||
strings.Contains(chatTitle, "first") {
return makeResponseWithNextCommand(data.Command + "1")
} else if strings.Contains(chatTitle, "secondo") ||
strings.Contains(chatTitle, "second") {
return makeResponseWithNextCommand(data.Command + "2")
} else if strings.Contains(chatTitle, "terzo") ||
strings.Contains(chatTitle, "third") {
return makeResponseWithNextCommand(data.Command + "3")
} else {
return makeResponseWithText(data.NoYear)
}
}

func (data TodayLecturesData) HandleBotCommand(*tgbotapi.BotAPI, *tgbotapi.Message) CommandResponse {

response, err := commands.GetTimeTable(data.Course.Type, data.Course.Name, data.Course.Year, time.Now())
if err != nil {
log.Printf("Error [TodayLecturesData]: %s\n", err)
return makeResponseWithText("Bot internal Error, contact developers")
}

var msg string
if response != "" {
msg = data.Title + response
} else {
msg = data.FallbackText
}

return makeResponseWithText(msg)
}

func (data TomorrowLecturesData) HandleBotCommand(*tgbotapi.BotAPI, *tgbotapi.Message) CommandResponse {
tomorrowTime := time.Now().AddDate(0, 0, 1)

response, err := commands.GetTimeTable(data.Course.Type, data.Course.Name, data.Course.Year, tomorrowTime)
if err != nil {
log.Printf("Error [TomorrowLecturesData]: %s\n", err)
return makeResponseWithText("Bot internal Error, contact developers")
}

var msg string
if response != "" {
msg = data.Title + response
} else {
msg = data.FallbackText
}

return makeResponseWithText(msg)
func (data Lectures) HandleBotCommand(_ *tgbotapi.BotAPI, message *tgbotapi.Message) CommandResponse {
rows := GetTimetableCoursesRows(&Timetables)
keyboard := tgbotapi.NewInlineKeyboardMarkup(rows...)
return makeResponseWithInlineKeyboard(keyboard)
}

func (data ListData) HandleBotCommand(*tgbotapi.BotAPI, *tgbotapi.Message) CommandResponse {
Expand Down
Loading