Esempio n. 1
0
func (ada *Adapter) AssignmentDetail(courseId, id string) (title, body string, attach *model.Attachment, status int, errMsg error) {
	status = http.StatusOK

	url := AssignmentDetailURL(courseId, id)
	doc, err := ada.GetDocument(url)
	if err != nil {
		status = http.StatusBadGateway
		errMsg = err
		return
	}

	var attachSel *goquery.Selection

	// Careful, I remembered assignments could contain HTML before.
	if content := doc.Find("#table_box>tbody>tr>td.title+td"); content.Size() != 5 {
		errMsg = fmt.Errorf("Expect 5 content blocks, got %d.", content.Size())
	} else {
		attachSel = content.Eq(2)
		texts := util.TrimmedTexts(content)
		title = texts[0]
		body = texts[1]
	}

	if errMsg != nil {
		status = http.StatusInternalServerError
		errMsg = fmt.Errorf("Failed to parse %s: %s", url, errMsg)
		return
	}

	attach, status, errMsg = ada.Attachment(attachSel)
	return
}
Esempio n. 2
0
func (ada *Adapter) Submission(courseId, id string) (submission *model.Submission, status int, errMsg error) {
	status = http.StatusOK

	url := SubmissionURL(courseId, id)
	doc, err := ada.GetDocument(url)
	if err != nil {
		status = http.StatusBadGateway
		errMsg = err
		return
	}

	var attachSel, commentAttachSel *goquery.Selection

	// Careful, I remembered assignments could contain HTML before.
	if content := doc.Find("#table_box>tbody>tr>td.title+td"); content.Size() != 8 {
		errMsg = fmt.Errorf("Expect 8 content blocks, got %d.", content.Size())
	} else {
		texts := util.TrimmedTexts(content)
		markStr := texts[5]
		if mark, err := ParseMark(markStr); err != nil {
			errMsg = fmt.Errorf("Failed to parse mark from %s: %s", markStr, err)
		} else {
			attachSel = content.Eq(2)
			commentAttachSel = content.Eq(7)

			submission = &model.Submission{
				AssignmentId: id,
				Late:         false, // Or we cannot view it now.
				Body:         texts[1],
			}
			if markedAt := texts[4]; markedAt != "null" {
				if name := texts[3]; name != "" {
					submission.MarkedBy = &model.User{Name: name}
				}
				submission.MarkedAt = markedAt
				submission.Mark = mark
				submission.Comment = texts[6]
			}
		}
	}

	if errMsg != nil {
		status = http.StatusInternalServerError
		errMsg = fmt.Errorf("Failed to parse %s: %s", url, errMsg)
		return
	}

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		submission.Attachment, *status, *err = ada.Attachment(attachSel)
	})
	sg.Go(func(status *int, err *error) {
		submission.CommentAttachment, *status, *err = ada.Attachment(commentAttachSel)
	})

	status, errMsg = sg.Wait()
	return
}
Esempio n. 3
0
func (ada *Adapter) AssignmentList(courseId string) (assignments []*model.Assignment, status int, errMsg error) {
	status = http.StatusOK

	url := AssignmentsURL(courseId)
	doc, err := ada.GetDocument(url)
	if err != nil {
		status = http.StatusBadGateway
		errMsg = err
		return
	}

	rows := doc.Find("tr.tr1, tr.tr2")
	assignments = make([]*model.Assignment, rows.Size())

	rows.EachWithBreak(func(i int, s *goquery.Selection) bool {
		if cols := s.Children(); cols.Size() != 6 {
			errMsg = fmt.Errorf("Expect 6 columns, got %d.", cols.Size())
		} else if link := cols.Eq(0).Find("a"); link.Size() == 0 {
			errMsg = fmt.Errorf("Failed to find link in column 0.")
		} else if _, id := ParseAssignmentDetailURL(link.AttrOr("href", "")); id == "" {
			errMsg = fmt.Errorf("Failed to find assignment id from href (%s).", link.AttrOr("href", ""))
		} else {
			texts := util.TrimmedTexts(cols)
			assign := &model.Assignment{
				Id:       id,
				CourseId: courseId,
				BeginAt:  texts[1],
				DueAt:    texts[2] + "T23:59:59+0800",
				Title:    texts[0],
			}
			switch subStatus := texts[3]; subStatus {
			case "尚未提交":
			case "已经提交":
				assign.Submission = new(model.Submission)
			default:
				errMsg = fmt.Errorf("Unknown submission status: %s", subStatus)
			}

			assignments[i] = assign
		}

		return errMsg == nil
	})

	if errMsg != nil {
		status = http.StatusInternalServerError
		errMsg = fmt.Errorf("Failed to parse %s: %s", url, errMsg)
		return
	}

	return
}
Esempio n. 4
0
func (ada *Adapter) AnnouncementList(courseId string) (announcements []*model.Announcement, status int, errMsg error) {
	status = http.StatusOK

	url := AnnouncementListURL(courseId)
	doc, err := ada.GetDocument(url)
	if err != nil {
		status = http.StatusBadGateway
		errMsg = err
		return
	}

	rows := doc.Find("#table_box tr~tr")
	announcements = make([]*model.Announcement, rows.Size())

	rows.EachWithBreak(func(i int, s *goquery.Selection) bool {
		if cols := s.Children(); cols.Size() != 5 {
			errMsg = fmt.Errorf("Expect 5 columns, got %d.", cols.Size())
		} else if link := cols.Eq(1).Find("a"); link.Size() == 0 {
			errMsg = fmt.Errorf("Failed to find link in column 1.")
		} else if _, id := ParseAnnouncementURL(link.AttrOr("href", "")); id == "" {
			errMsg = fmt.Errorf("Failed to find announcement id from href (%s).", link.AttrOr("href", ""))
		} else {
			texts := util.TrimmedTexts(cols)
			annc := &model.Announcement{
				Id:        id,
				CourseId:  courseId,
				Owner:     &model.User{Name: strings.TrimSuffix(texts[2], "老师")},
				CreatedAt: texts[3],
				Title:     texts[1],
			}
			if red := link.Find("font[color=red]"); red.Size() > 0 {
				annc.Priority = 1
			}

			announcements[i] = annc
		}

		return errMsg == nil
	})

	if errMsg != nil {
		status = http.StatusInternalServerError
		errMsg = fmt.Errorf("Failed to parse %s: %s", url, errMsg)
		return
	}

	return
}
Esempio n. 5
0
func (ada *Adapter) Files(courseId string) (files []*model.File, status int, errMsg error) {
	// TODO: Clean this function up.
	files = make([]*model.File, 0)

	url := FilesURL(courseId)
	doc, err := ada.GetDocument(url)
	if err != nil {
		status = http.StatusBadGateway
		errMsg = err
		return
	}

	// Find all categories.
	categories := util.TrimmedTexts(doc.Find("#table_box td.textTD"))

	doc.Find("div.layerbox").EachWithBreak(func(i int, div *goquery.Selection) bool {
		if i >= len(categories) {
			return false
		}
		category := []string{categories[i]}

		div.Find("#table_box tr~tr").EachWithBreak(func(_ int, s *goquery.Selection) bool {
			if cols := s.Children(); cols.Size() != 6 {
				errMsg = fmt.Errorf("Expect 6 columns, got %d.", cols.Size())
			} else if link := cols.Eq(1).Find("a"); link.Size() == 0 {
				errMsg = fmt.Errorf("Failed to find link in column 1.")
			} else if _, id := ParseDownloadURL(link.AttrOr("href", "")); id == "" {
				errMsg = fmt.Errorf("Failed to find file id from href (%s).", link.AttrOr("href", ""))
			} else {
				texts := util.TrimmedTexts(cols)
				file := &model.File{
					Id:          id,
					CourseId:    courseId,
					CreatedAt:   texts[4],
					Title:       texts[1],
					Description: texts[2],
					Category:    category,
					DownloadURL: BaseURL + link.AttrOr("href", ""),
				}

				files = append(files, file)
			}

			return errMsg == nil
		})

		return errMsg == nil
	})

	if errMsg != nil {
		status = http.StatusInternalServerError
		errMsg = fmt.Errorf("Failed to parse %s: %s", url, errMsg)
		return
	}

	// Fill file infos.
	sg := util.NewStatusGroup()

	for _, file := range files {
		file := file
		sg.Go(func(status *int, err *error) {
			file.Filename, file.Size, *status, *err = ada.FileInfo(file.DownloadURL, simplifiedchinese.GBK)
		})
	}

	status, errMsg = sg.Wait()
	return
}