package main import ( "encoding/json" "fmt" "html" "io" "net/http" "net/url" "regexp" "strings" "strconv" "time" ) func submit_code(course_code int, attendance_code string) bool { cur_body := launch_aplus(course_code) if cur_body == "" { fmt.Println("Unknown error") return false } else if cur_body == "Roles not supported" { fmt.Println("Cannot access course", course_code, "(canvas error \"Roles not supported\")") return false } if verbose { fmt.Printf("%s", cur_body) } if strings.Contains(cur_body, "Student not known") { fmt.Println("Student not known. This course must first be visited by an instructor for students to have access.") return false } current_url := fmt.Sprintf("%s/student/", base_aplus_link) // the links to submit the code for a class is under the dayPanel div daypanel_start := strings.Index(cur_body, "
") errormsg_start += len("Text\">") errormsg_end := errormsg_start errormsg_end += strings.Index(string(body)[errormsg_start:], "<") fmt.Println(string(body)[errormsg_start:errormsg_end]) } else if strings.Index(string(body), "ctl02_codeSuccessMessage") != -1 { fmt.Println("Code successfully recorded") } return true } func launch_aplus(course_code int) string { err := init_aplus_toolid(course_code) if err != nil { fmt.Println("Failed to get A+ base URL and tool ID. Try again with a different course code.") fmt.Printf("Error: %s\n", err) return "" } aplus_link := fmt.Sprintf("%s/courses/%d/external_tools/sessionless_launch?id=%d&access_token=%s", base_link, course_code, external_tools_code, token) aplus := get_aplus(token, aplus_link, client) resp, _ := client.Get(aplus) body, _ := io.ReadAll(resp.Body) form_str := get_form_from_request_body(body) form_values := parse_form(form_str) resp, _ = client.PostForm(base_aplus_link, form_values) body, _ = io.ReadAll(resp.Body) if strings.Index(string(body), "Roles not supported") != -1 { return "Roles not supported" } else { return string(body) } } func get_aplus(token string, link string, client http.Client) string { resp, _ := client.Get(link) body, _ := io.ReadAll(resp.Body) var aplus Aplus json.Unmarshal(body, &aplus) return aplus.URL } func get_form_from_request_body(req_body []byte) string { body_str := string(req_body) form_start := strings.Index(body_str, "") + 7 form_html := req_body[form_start:form_end] return string(form_html) } // parse_form extracts form fields and values from the given HTML form string. func parse_form(form_html string) url.Values { form_values := make(url.Values) inputs := strings.Split(form_html, "[^<]*") dates, statuses := re_date.FindAllString(tt_full, -1), re_status.FindAllString(tt_full, -1) for i := range dates { jsdate := strings.Split(dates[i][9:], ",") year, _ := strconv.Atoi(jsdate[0]) month, _ := strconv.Atoi(jsdate[1]) day, _ := strconv.Atoi(jsdate[2]) hour, _ := strconv.Atoi(jsdate[3]) min, _ := strconv.Atoi(jsdate[4]) sec, _ := strconv.Atoi(jsdate[5]) date := time.Date(year, time.Month(month + 1), day, hour, min, sec, 0, time.UTC).Local() fmt.Println(date.Format("Mon Jan 02 15:04:05 MST 2006") + ": " + strings.Replace(statuses[i], "title=\"\">", "", 1)) } }