package bm import ( "net/http" "git.golem15.com/golem15/summercms/modules/pact" ) // MCPMaterialPrivacy is the sentence every material tool description // carries (D-17, D-21). const MCPMaterialPrivacy = "Returns metadata and links only, never file contents; a material's body (possible transcript text) is left out unless include_body is true." // The sentences every student tool description ends with (D-15). const ( needsScopeRead = " Needs scope read." needsScopeWrite = " Needs scope write." ) // noInput is the input of a tool that takes no arguments. type noInput struct{} // idInput names one record by its id. type idInput struct { ID uint `json:"id" path:"id" jsonschema:"the record id, as listed by the matching list tool"` } // readingIDInput names one reading by its id. type readingIDInput struct { ID uint `json:"id" path:"id" jsonschema:"the reading id, as listed by bm_readings or bm_course"` } // coursesInput is the input of bm_courses. type coursesInput struct { Semester int `json:"semester,omitempty" query:"semester" jsonschema:"only courses of this semester, 1 to 4"` } // rangeInput is the input of bm_schedule and bm_deadlines. type rangeInput struct { From string `json:"from,omitempty" query:"from" jsonschema:"first day, YYYY-MM-DD (default: today)"` To string `json:"to,omitempty" query:"to" jsonschema:"last day (inclusive), YYYY-MM-DD, not before from (default: no end)"` } // readingsInput is the input of bm_readings. type readingsInput struct { Course uint `json:"course,omitempty" query:"course" jsonschema:"only readings of this course id"` } // materialsInput is the input of bm_materials. type materialsInput struct { Course uint `json:"course,omitempty" query:"course" jsonschema:"only materials of this course id"` Meeting uint `json:"meeting,omitempty" query:"meeting" jsonschema:"only materials of this zjazd (meeting) id"` Tag string `json:"tag,omitempty" query:"tag" jsonschema:"only materials with this tag slug, at most 100 characters"` Type string `json:"type,omitempty" query:"type" jsonschema:"only materials of this type, one of: pdf, notatka, link, inne"` Page int `json:"page,omitempty" query:"page" jsonschema:"page number, 1 or more (default 1)"` PerPage int `json:"per_page,omitempty" query:"per_page" jsonschema:"materials per page, 1 to 100"` } // materialInput is the input of bm_material. type materialInput struct { ID uint `json:"id" path:"id" jsonschema:"the material id, as listed by bm_materials"` IncludeBody bool `json:"include_body,omitempty" query:"include_body" jsonschema:"true to include the material's body (it may hold transcript text)"` } // boolPtr returns a pointer to b, for the tool annotations. func boolPtr(b bool) *bool { return &b } // studentTools are the tools over the token twins of the student API. Each // call runs as the session's user, who reaches only their own progress and // published data, as on the HTTP API (D-09). func studentTools() []pact.MCPTool { return []pact.MCPTool{ { Name: "dashboard", Title: "BM dashboard", Description: "Returns the student's dashboard: the next class sessions, the deadlines not yet due, the zjazd (meeting) under way today and the next one, and the student's reading progress counts." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/dashboard", Input: noInput{}, }, { Name: "courses", Title: "BM courses", Description: "Lists the programme's courses with code, form, lecturer, semester, ECTS, assessment, syllabus link and counters." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/courses", Input: coursesInput{}, }, { Name: "course", Title: "BM course", Description: "Returns one course with its description, syllabus link, counters, class sessions, readings (with the student's read and owned marks) and published materials." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/courses/{id}", Input: idInput{}, }, { Name: "schedule", Title: "BM schedule", Description: "Lists the class sessions starting in a date range (default: from today, no end) with course, zjazd, start and end time, room, kind, lecturer, notes and whether the class is online." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/schedule", Input: rangeInput{}, }, { Name: "meetings", Title: "BM meetings", Description: "Lists the zjazdy (weekend meetings) with number, first and last day, notes and the number of class sessions in each." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/meetings", Input: noInput{}, }, { Name: "deadlines", Title: "BM deadlines", Description: "Lists the deadlines due in a date range (default: from today, no end) with title, due time, kind, course and description." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/deadlines", Input: rangeInput{}, }, { Name: "readings", Title: "BM readings", Description: "Lists readings with author, source, link, course, zjazd, whether required, and the student's read and owned marks." + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/readings", Input: readingsInput{}, }, { Name: "mark_reading_read", Title: "Mark a reading as read", Description: "Marks a reading as read by the signed-in student and returns the reading id with the read time. Marking again keeps the first time." + needsScopeWrite, Guard: "user", Method: http.MethodPut, Path: TokenPrefix + "/readings/{id}/progress", Input: readingIDInput{}, }, { Name: "unmark_reading_read", Title: "Unmark a reading as read", Description: "Removes the signed-in student's read mark from a reading (it can be marked again) and returns the reading id with an empty read time." + needsScopeWrite, Guard: "user", Method: http.MethodDelete, Path: TokenPrefix + "/readings/{id}/progress", Input: readingIDInput{}, Destructive: boolPtr(false), Idempotent: boolPtr(true), }, { Name: "mark_reading_owned", Title: "Mark a reading as owned", Description: "Marks that the signed-in student has a copy of a reading and returns the reading id with the owned time." + needsScopeWrite, Guard: "user", Method: http.MethodPut, Path: TokenPrefix + "/readings/{id}/owned", Input: readingIDInput{}, }, { Name: "unmark_reading_owned", Title: "Unmark a reading as owned", Description: "Removes the signed-in student's owned mark from a reading (it can be marked again) and returns the reading id with an empty owned time." + needsScopeWrite, Guard: "user", Method: http.MethodDelete, Path: TokenPrefix + "/readings/{id}/owned", Input: readingIDInput{}, Destructive: boolPtr(false), Idempotent: boolPtr(true), }, { Name: "materials", Title: "BM materials", Description: "Lists a page of published materials, newest first, with title, type, course, zjazd, source, link, tags and file count, plus the page meta. " + MCPMaterialPrivacy + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/materials", Input: materialsInput{}, }, { Name: "material", Title: "BM material", Description: "Returns one published material with its tags and its files (id, absolute link, name, size and type). " + MCPMaterialPrivacy + needsScopeRead, Guard: "user", Method: http.MethodGet, Path: TokenPrefix + "/materials/{id}", Input: materialInput{}, }, } }