diff --git a/modules/database/database_struct.go b/modules/database/database_struct.go index 89584f9..7573818 100644 --- a/modules/database/database_struct.go +++ b/modules/database/database_struct.go @@ -21,17 +21,16 @@ type ShedulesInUser struct { } type Group struct { - GroupId int64 `xorm:"pk"` - GroupName string - SpecName string + GroupId int64 `xorm:"pk"` + GroupName string // Полный номер группы + SpecName string // Шифр и название специальности } type Teacher struct { - TeacherId int64 `xorm:"pk"` - LastName string - FirstName string - MidName string - SpecName string + TeacherId int64 `xorm:"pk"` + FirstName string // Фамилия + LastName string // Имя, отчество и прочие окончания + SpecName string // Место работы } type Lesson struct { diff --git a/modules/ssau_parser/database.go b/modules/ssau_parser/database.go index fcb4b41..87077a4 100644 --- a/modules/ssau_parser/database.go +++ b/modules/ssau_parser/database.go @@ -8,8 +8,22 @@ import ( "xorm.io/xorm" ) +func UpdateSchedule(db *xorm.Engine, sh WeekShedule) error { + err := checkGroupOrTeacher(db, sh) + if err != nil { + return err + } + + first_new := sh.Uncovered[0] + _, week := first_new.Begin.ISOWeek() + var old []database.Lesson + db.Where("WEEK(`Begin`) = ?", week).Asc("Begin").Find(&old) + Compare(sh.Uncovered, old) + return nil +} + func UploadShedule(db *xorm.Engine, sh WeekShedule) error { - err := addGroupOrTeacher(db, sh) + err := checkGroupOrTeacher(db, sh) if err != nil { return err } @@ -42,7 +56,7 @@ func UploadShedule(db *xorm.Engine, sh WeekShedule) error { gr.IsGroup = false gr.SheduleId = subLesson.TeacherId[0] GetSheduleInfo(doc.Doc, &gr) - addGroupOrTeacher(db, gr) + checkGroupOrTeacher(db, gr) } for _, groupId := range subLesson.GroupId { @@ -63,7 +77,7 @@ func UploadShedule(db *xorm.Engine, sh WeekShedule) error { gr.IsGroup = true gr.SheduleId = groupId GetSheduleInfo(doc.Doc, &gr) - addGroupOrTeacher(db, gr) + checkGroupOrTeacher(db, gr) } var existsLessons []database.Lesson @@ -109,7 +123,9 @@ func isTeacherExists(db *xorm.Engine, teacherId int64) (bool, error) { return len(exists) == 1, nil } -func addGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error { +// Проверка наличия группы или преподавателя в БД и добавление при необходимости +// TODO: Добавить проверку изменений в полях данных +func checkGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error { if sh.IsGroup { exists, err := isGroupExists(db, sh.SheduleId) if err != nil { @@ -135,8 +151,8 @@ func addGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error { log.Println(name) teacher := database.Teacher{ TeacherId: sh.SheduleId, - LastName: name[0], - FirstName: strings.Join(name[1:], " "), + FirstName: name[0], + LastName: strings.Join(name[1:], " "), SpecName: sh.SpecName, } db.InsertOne(teacher) diff --git a/modules/ssau_parser/diff.go b/modules/ssau_parser/diff.go index 75b072e..a0b0967 100644 --- a/modules/ssau_parser/diff.go +++ b/modules/ssau_parser/diff.go @@ -11,7 +11,7 @@ import ( ) // Раскрытие недельного расписания в список занятий для базы данных и сравнения -func UncoverShedule(sh WeekShedule) []database.Lesson { +func (sh *WeekShedule) UncoverShedule() { var lessons []database.Lesson for y, line := range sh.Lessons { for x, pair := range line { @@ -41,7 +41,7 @@ func UncoverShedule(sh WeekShedule) []database.Lesson { } } } - return lessons + sh.Uncovered = lessons } // Сравнивание списков занятий на предмет добавления и удаления diff --git a/modules/ssau_parser/parser.go b/modules/ssau_parser/parser.go index d135dac..158ec9d 100644 --- a/modules/ssau_parser/parser.go +++ b/modules/ssau_parser/parser.go @@ -1,14 +1,17 @@ package ssau_parser import ( + "errors" "strconv" "strings" "time" + "git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database" "github.com/PuerkitoBio/goquery" "golang.org/x/exp/slices" ) +// Пара, состоящая из занятий type Pair struct { Begin time.Time End time.Time @@ -16,6 +19,7 @@ type Pair struct { Lessons []Lesson } +// Отдельные занятия внутри пары type Lesson struct { Type string Name string @@ -27,14 +31,16 @@ type Lesson struct { Hash []byte } +// Недельное расписание type WeekShedule struct { IsGroup bool SheduleId int64 FullName string SpecName string - Week int - WeekBegin int - Lessons [][]Pair + Week int // Номер недели в семестре + WeekBegin int // Номер недели в году начала семестра + Lessons [][]Pair // Таблица пар в форме недельного расписания + Uncovered []database.Lesson // Раскрытый список всех занятий для дальнейшей обработки в БД } // Получить полный номер группы и название специальности (ФИО и место работы для преподавателей) @@ -58,10 +64,9 @@ func GetSheduleInfo(doc *goquery.Document, sh *WeekShedule) { var hourMap = map[int]int{8: 0, 9: 1, 11: 2, 13: 3, 15: 4, 17: 5, 18: 6, 20: 7} // Парсинг страницы с расписанием -func Parse(p Page) (*WeekShedule, error) { - var sh WeekShedule +func (sh *WeekShedule) Parse(p Page, uncover bool) error { doc := p.Doc - GetSheduleInfo(doc, &sh) + GetSheduleInfo(doc, sh) var raw_dates []string doc.Find(".schedule__head-date").Each(func(i int, s *goquery.Selection) { @@ -88,7 +93,7 @@ func Parse(p Page) (*WeekShedule, error) { if t == 0 { begin, err := time.Parse(" 15:04 -07", raw_times[t]) if err != nil { - return nil, err + return err } firstNum = hourMap[begin.Hour()] } @@ -98,12 +103,12 @@ func Parse(p Page) (*WeekShedule, error) { begin_raw := date + raw_times[t] begin, err := time.Parse(" 02.01.2006 15:04 -07", begin_raw) if err != nil { - return nil, err + return err } end_raw := date + raw_times[t+1] end, err := time.Parse(" 02.01.2006 15:04 -07", end_raw) if err != nil { - return nil, err + return err } idx := (len(raw_dates))*t/2 + d lesson := Pair{ @@ -120,7 +125,11 @@ func Parse(p Page) (*WeekShedule, error) { sh.SheduleId = p.ID sh.Week = p.Week sh.Lessons = shedule - return &sh, nil + + if uncover { + sh.UncoverShedule() + } + return nil } var types = [4]string{"lect", "lab", "pract", "other"} @@ -212,3 +221,37 @@ func ParseLesson(s *goquery.Selection, isGroup bool, sheduleId int64) []Lesson { return lessons } + +// Загрузка, парсинг и раскрытие расписания в одной функции +// Обязательно наличие IsGroup, SheduleId, Week в объекте +func (sh *WeekShedule) DownloadById(uncover bool) error { + if sh.SheduleId == 0 { + return errors.New("schedule id not included") + } + if sh.Week == 0 { + return errors.New("week not included") + } + + page, err := DownloadSheduleById(sh.SheduleId, sh.IsGroup, sh.Week) + if err != nil { + return err + } + err = sh.Parse(page, uncover) + if err != nil { + return err + } + return nil +} + +// Загрузка, парсинг и раскрытие расписания в одной функции по URI и номеру недели +func (sh *WeekShedule) Download(uri string, week int, uncover bool) error { + page, err := DownloadShedule(uri, week) + if err != nil { + return err + } + err = sh.Parse(page, uncover) + if err != nil { + return err + } + return nil +} diff --git a/modules/ssau_parser/ssau_parser_test.go b/modules/ssau_parser/ssau_parser_test.go index 2ed63b8..6dc61c1 100644 --- a/modules/ssau_parser/ssau_parser_test.go +++ b/modules/ssau_parser/ssau_parser_test.go @@ -3,6 +3,8 @@ package ssau_parser import ( "log" "testing" + + "git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database" ) var queries = []string{ @@ -21,6 +23,13 @@ var urls = []string{ "http://127.0.0.1:5000", } +// Вывод некритических ошибок тестирования в консоль +func handleError(err error) { + if err != nil { + log.Println(err) + } +} + // TODO: выдумать и прописать упоротые тесты для всего func TestSearchInRasp(t *testing.T) { // Проверка запросов @@ -75,68 +84,83 @@ func TestDownloadShedule(t *testing.T) { func TestParse(t *testing.T) { headURL = "http://127.0.0.1:5000" - page, err := DownloadSheduleById(802440189, true, 3) - if err != nil { - log.Println(err) - return - } - _, err = Parse(page) - if err != nil { - log.Println(err) + sh := WeekShedule{ + SheduleId: 802440189, + IsGroup: true, + Week: 3, } + err := sh.DownloadById(false) + handleError(err) // Ошибки в скелете расписания for i := 1; i < 6; i++ { - page, err := DownloadSheduleById(123, true, i) - if err != nil { - log.Println(err) - return - } - _, err = Parse(page) - if err != nil { - log.Println(err) + sh := WeekShedule{ + SheduleId: 123, + IsGroup: true, + Week: i, } + err = sh.DownloadById(false) + handleError(err) } // Ошибки внутри пар for i := 2; i < 3; i++ { - page, err := DownloadSheduleById(62806001, false, i) - if err != nil { - log.Println(err) - return - } - sh, err := Parse(page) - if err != nil { - log.Println(err) + sh := WeekShedule{ + SheduleId: 62806001, + IsGroup: false, + Week: i, } + err = sh.DownloadById(false) + handleError(err) log.Println(sh.FullName) } } func TestSheduleCompare(t *testing.T) { headURL = "http://127.0.0.1:5000" - page, err := DownloadSheduleById(802440189, true, 4) - if err != nil { - log.Println(err) - return + sh := WeekShedule{ + SheduleId: 802440189, + IsGroup: true, + Week: 4, } - sh, err := Parse(page) - if err != nil { - log.Println(err) - } - lessons := UncoverShedule(*sh) + err := sh.DownloadById(true) + handleError(err) - page, err = DownloadSheduleById(802440189, true, 8) - if err != nil { - log.Println(err) - return + new_sh := WeekShedule{ + SheduleId: 802440189, + IsGroup: true, + Week: 8, } - sh, err = Parse(page) - if err != nil { - log.Println(err) - } - new_lessons := UncoverShedule(*sh) + err = new_sh.DownloadById(true) + handleError(err) - add, del := Compare(new_lessons, lessons) + add, del := Compare(new_sh.Uncovered, sh.Uncovered) log.Println(add, del) } + +func TestCheckGroupOrTeacher(t *testing.T) { + db, err := database.Connect("test", "TESTpass1!", "testdb") + if err != nil { + log.Println(err) + return + } + // Очистка всех данных для теста + _, err = db.Where("groupid > 0").Delete(&database.Group{}) + handleError(err) + _, err = db.Where("teacherid > 0").Delete(&database.Teacher{}) + handleError(err) + + headURL = "http://127.0.0.1:5000" + sh := WeekShedule{ + SheduleId: 802440189, + IsGroup: true, + Week: 4, + } + err = sh.DownloadById(false) + handleError(err) + err = checkGroupOrTeacher(db, sh) + handleError(err) + // Повторяем на предмет наличия + err = checkGroupOrTeacher(db, sh) + handleError(err) +} diff --git a/modules/tg/handlers.go b/modules/tg/handlers.go index c21114e..3e78a00 100644 --- a/modules/tg/handlers.go +++ b/modules/tg/handlers.go @@ -102,7 +102,6 @@ func (bot *Bot) Find(query string) error { TeacherId: elem.Id, LastName: name[0], FirstName: name[1], - MidName: name[2], }) } } diff --git a/modules/tg/shedule.go b/modules/tg/shedule.go index d9abda4..2c15b68 100644 --- a/modules/tg/shedule.go +++ b/modules/tg/shedule.go @@ -323,8 +323,8 @@ func PairToStr(pair []database.Lesson, db *xorm.Engine) (string, error) { name := GenerateName(t) str += fmt.Sprintf("👤 %s\n", name) } - if sublesson.SubGroup != "" { - str += fmt.Sprintf("👥 %s\n", sublesson.SubGroup) + if sublesson.SubGroup != 0 { + str += fmt.Sprintf("👥 %d\n", sublesson.SubGroup) } if sublesson.Comment != "" { str += fmt.Sprintf("💬 %s\n", sublesson.Comment) diff --git a/modules/tg/week_shedule.go b/modules/tg/week_shedule.go index 551feb0..f2a252c 100644 --- a/modules/tg/week_shedule.go +++ b/modules/tg/week_shedule.go @@ -257,8 +257,8 @@ func (bot *Bot) CreateHTMLShedule(week int, shedule [][6][]database.Lesson, date if l[0].Place != "" { html += fmt.Sprintf("

%s

\n", l[0].Place) } - if l[0].SubGroup != "" { - html += fmt.Sprintf("

%s

\n", l[0].SubGroup) + if l[0].SubGroup != 0 { + html += fmt.Sprintf("

%d

\n", l[0].SubGroup) } if l[0].Comment != "" { html += fmt.Sprintf("

%s

\n", l[0].Comment) @@ -278,8 +278,8 @@ func (bot *Bot) CreateHTMLShedule(week int, shedule [][6][]database.Lesson, date if l[1].Place != "" { html += fmt.Sprintf("

%s

\n", l[1].Place) } - if l[1].SubGroup != "" { - html += fmt.Sprintf("

%s

\n", l[1].SubGroup) + if l[1].SubGroup != 0 { + html += fmt.Sprintf("

%d

\n", l[1].SubGroup) } if l[1].Comment != "" { html += fmt.Sprintf("

%s

\n", l[1].Comment)