Пример #1
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
}
Пример #2
0
func New(userId, password string) (ada *Adapter, status int, errMsg error) {
	ada = new(Adapter)

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		ada.Adapter, *status, *err = cic.New(userId, password)
	})
	sg.Go(func(status *int, err *error) {
		ada.Old, *status, *err = old.New(userId, password)
	})
	status, errMsg = sg.Wait()

	return
}
Пример #3
0
func (ada *Adapter) AllAttended(english bool) (courses []*model.Course, status int, errMsg error) {
	var pastCourses, thisCourses, nextCourses []*model.Course

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		thisCourses, nextCourses, *status, *err = ada.NowAttended(english)
	})
	sg.Go(func(status *int, err *error) {
		pastCourses, *status, *err = ada.PastAttended(english)
	})

	status, errMsg = sg.Wait()
	courses = append(nextCourses, thisCourses...)
	courses = append(courses, pastCourses...)
	return
}
Пример #4
0
func (ada *Adapter) AllAttendedList() (courses []*model.Course, status int, errMsg error) {
	var thisCourses, pastCourses []*model.Course

	sg := util.NewStatusGroup()

	sg.Go(func(status *int, err *error) {
		thisCourses, *status, *err = ada.AttendedList(1)
	})
	sg.Go(func(status *int, err *error) {
		pastCourses, *status, *err = ada.AttendedList(2)
	})

	status, errMsg = sg.Wait()
	courses = append(thisCourses, pastCourses...)
	return
}
Пример #5
0
func (ada *Adapter) Attended(semesterId string, english bool) (courses []*model.Course, status int, errMsg error) {
	var m map[fatName]string

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		m, *status, *err = ada.nameIdMap()
	})
	sg.Go(func(status *int, err *error) {
		courses, *status, *err = ada.Adapter.Attended(semesterId, english)
	})
	if status, errMsg = sg.Wait(); errMsg == nil {
		replaceCourseIds(courses, m)
	}

	return
}
Пример #6
0
func (ada *Adapter) Announcements(courseId string) (announcements []*model.Announcement, status int, errMsg error) {
	if announcements, status, errMsg = ada.AnnouncementList(courseId); errMsg != nil {
		return
	}

	sg := util.NewStatusGroup()

	for _, annc := range announcements {
		annc := annc
		sg.Go(func(status *int, err *error) {
			_, annc.Body, annc.Owner.Email, *status, *err = ada.Announcement(courseId, annc.Id)
		})
	}

	status, errMsg = sg.Wait()
	return
}
Пример #7
0
func (ada *Adapter) NowAttended(english bool) (thisCourses []*model.Course, nextCourses []*model.Course, status int, errMsg error) {
	var m map[fatName]string

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		m, *status, *err = ada.nameIdMap()
	})
	sg.Go(func(status *int, err *error) {
		thisCourses, nextCourses, *status, *err = ada.Adapter.NowAttended(english)
	})
	if status, errMsg = sg.Wait(); errMsg == nil {
		replaceCourseIds(thisCourses, m)
		replaceCourseIds(nextCourses, m)
	}

	return
}
Пример #8
0
func (ada *Adapter) NowAttended(english bool) (thisCourses []*model.Course, nextCourses []*model.Course, status int, errMsg error) {
	var thisSem, nextSem *model.Semester
	thisSem, nextSem, status, errMsg = ada.Semesters()
	if errMsg != nil {
		return
	}

	sg := util.NewStatusGroup()
	sg.Go(func(status *int, err *error) {
		thisCourses, *status, *err = ada.Attended(thisSem.Id, english)
	})
	sg.Go(func(status *int, err *error) {
		nextCourses, *status, *err = ada.Attended(nextSem.Id, english)
	})

	status, errMsg = sg.Wait()
	return
}
Пример #9
0
func BatchResourceFunc(argsStr string, f func(string) (interface{}, int, error)) (v interface{}, status int, err error) {
	args := strings.Split(argsStr, ",")

	if len(args) == 1 {
		v, status, err = f(args[0])
	} else {
		list := make([]interface{}, len(args))
		sg := util.NewStatusGroup()

		for i := range args {
			i := i
			sg.Go(func(status *int, err *error) {
				list[i], *status, *err = f(args[i])
			})
		}

		status, err = sg.Wait()
		v = list
	}

	return
}
Пример #10
0
func (ada *Adapter) Assignments(courseId string) (assignments []*model.Assignment, status int, errMsg error) {
	if assignments, status, errMsg = ada.AssignmentList(courseId); errMsg != nil {
		return
	}

	sg := util.NewStatusGroup()

	for _, assign := range assignments {
		assign := assign

		sg.Go(func(status *int, err *error) {
			_, assign.Body, assign.Attachment, *status, *err = ada.AssignmentDetail(courseId, assign.Id)
		})

		if assign.Submission != nil {
			sg.Go(func(status *int, err *error) {
				assign.Submission, *status, *err = ada.Submission(courseId, assign.Id)
			})
		}
	}

	status, errMsg = sg.Wait()
	return
}
Пример #11
0
func (ada *Adapter) Attended(semesterId string, english bool) (courses []*model.Course, status int, errMsg error) {
	courses = make([]*model.Course, 0)

	url := AttendedURL(semesterId)
	var v struct {
		ResultList []struct {
			CourseId      string
			Course_no     string
			Course_seq    string
			Course_name   string
			E_course_name string
			TeacherInfo   struct {
				Id     string
				Name   string
				Email  string
				Phone  string
				Gender string
				Title  string
			}
			CodeDepartmentInfo struct {
				Dwmc   string
				Dwywmc string
			}
			SemesterInfo struct {
				Id string
			}
			Detail_c    string
			Detail_e    string
			Credit      int
			Course_time int
		}
	}

	if err := ada.GetJSON(url, &v); err != nil {
		return nil, http.StatusBadGateway, err
	}

	sg := util.NewStatusGroup()

	for _, result := range v.ResultList {
		var name, description, department string
		if english {
			name = result.E_course_name
			description = result.Detail_e
			department = result.CodeDepartmentInfo.Dwywmc
		}
		// Fallback to Chinese version.
		if name == "" {
			name = result.Course_name
		}
		if description == "" {
			description = result.Detail_c
		}
		if department == "" {
			department = result.CodeDepartmentInfo.Dwmc
		}

		course := &model.Course{
			Id:          result.CourseId,
			SemesterId:  result.SemesterInfo.Id,
			Number:      result.Course_no,
			Sequence:    result.Course_seq,
			Name:        name,
			Credit:      result.Credit,
			Hour:        result.Course_time,
			Description: description,

			Teachers: []*model.User{
				&model.User{
					Id:         result.TeacherInfo.Id,
					Name:       result.TeacherInfo.Name,
					Type:       result.TeacherInfo.Title,
					Department: department,
					Gender:     result.TeacherInfo.Gender,
					Email:      result.TeacherInfo.Email,
					Phone:      result.TeacherInfo.Phone,
				},
			},
		}

		sg.Go(func(status *int, err *error) {
			course.Schedules, *status, *err = ada.Schedules(course.Id)
		})
		sg.Go(func(status *int, err *error) {
			course.Assistants, *status, *err = ada.Assistants(course.Id)
		})
		courses = append(courses, course)
	}

	status, errMsg = sg.Wait()
	return
}
Пример #12
0
	"github.com/tsinghua-io/api-server/adapter/tsinghua.edu.cn/x/learn"
	"github.com/tsinghua-io/api-server/model"
	"github.com/tsinghua-io/api-server/util"
	"net/http"
)

var CourseMaterials = Resource{
	"GET": util.AuthNeededHandler(GetCourseMaterials),
}

var GetCourseMaterials = learn.HandlerFunc(func(rw http.ResponseWriter, req *http.Request, ada *learn.Adapter) {
	v, status, err := BatchResourceFunc(
		mux.Vars(req)["id"],
		func(id string) (interface{}, int, error) {
			materials := new(model.Materials)
			sg := util.NewStatusGroup()

			sg.Go(func(status *int, err *error) {
				materials.Announcements, *status, *err = ada.Announcements(id)
			})
			sg.Go(func(status *int, err *error) {
				materials.Files, *status, *err = ada.Files(id)
			})
			sg.Go(func(status *int, err *error) {
				materials.Assignments, *status, *err = ada.Assignments(id)
			})

			status, err := sg.Wait()
			return materials, status, err
		})
	util.JSON(rw, v, status, err)
Пример #13
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
}