All checks were successful
Deploy on Master Change / deploy (push) Successful in 1m12s
264 lines
7.3 KiB
Go
264 lines
7.3 KiB
Go
package qldt
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Client struct {
|
|
baseURL string
|
|
origin string
|
|
http *http.Client
|
|
}
|
|
|
|
func NewClient(baseURL, origin string) *Client {
|
|
baseURL = strings.TrimRight(baseURL, "/")
|
|
return &Client{
|
|
baseURL: baseURL,
|
|
origin: origin,
|
|
http: &http.Client{
|
|
Timeout: 45 * time.Second,
|
|
},
|
|
}
|
|
}
|
|
|
|
type StudentsResponse struct {
|
|
Message string `json:"message"`
|
|
StatusCode int `json:"statusCode"`
|
|
Data []StudentDTO `json:"data"`
|
|
Total int `json:"total"`
|
|
Page string `json:"page"`
|
|
PageSize string `json:"pageSize"`
|
|
}
|
|
|
|
type StudentDTO struct {
|
|
ID int64 `json:"id"`
|
|
StudentCode string `json:"studentCode"`
|
|
FullName string `json:"fullName"`
|
|
Phone *string `json:"phone"`
|
|
Email string `json:"email"`
|
|
DateOfBirth *string `json:"dateOfBirth"`
|
|
Gender *int `json:"gender"`
|
|
Status *string `json:"status"`
|
|
Location *string `json:"location"`
|
|
Avatar *string `json:"avatar"`
|
|
System *struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
} `json:"system"`
|
|
}
|
|
|
|
type ClassesResponse struct {
|
|
Data []ClassDTO `json:"data"`
|
|
StatusCode int `json:"statusCode"`
|
|
}
|
|
|
|
type ClassDTO struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
ClassCode string `json:"classCode"`
|
|
Type string `json:"type"`
|
|
StudentCount int `json:"studentCount"`
|
|
CreatedAt string `json:"createdAt"`
|
|
UpdatedAt *string `json:"updatedAt"`
|
|
Specializes *struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Systems *struct {
|
|
ID int64 `json:"id"`
|
|
SystemCode string `json:"systemCode"`
|
|
Name string `json:"name"`
|
|
} `json:"systems"`
|
|
} `json:"specializes"`
|
|
Courses []classCourseNestDTO `json:"courses"`
|
|
}
|
|
|
|
type classCourseNestDTO struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
func (c *Client) GetStudents(ctx context.Context, token string, page, pageSize int) (*StudentsResponse, error) {
|
|
u, err := url.Parse(c.baseURL + "/students")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
q := u.Query()
|
|
q.Set("page", strconv.Itoa(page))
|
|
q.Set("pageSize", strconv.Itoa(pageSize))
|
|
u.RawQuery = q.Encode()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
if c.origin != "" {
|
|
req.Header.Set("Origin", c.origin)
|
|
req.Header.Set("Referer", c.origin+"/")
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("qldt students http %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
var out StudentsResponse
|
|
if err := json.Unmarshal(body, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
if out.StatusCode != 0 && out.StatusCode != 200 {
|
|
return nil, fmt.Errorf("qldt statusCode %d: %s", out.StatusCode, out.Message)
|
|
}
|
|
|
|
return &out, nil
|
|
}
|
|
|
|
func (c *Client) GetClassesBySystem(ctx context.Context, token string, systemID int64) (*ClassesResponse, error) {
|
|
u := fmt.Sprintf("%s/classes/system/%d", c.baseURL, systemID)
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
if c.origin != "" {
|
|
req.Header.Set("Origin", c.origin)
|
|
req.Header.Set("Referer", c.origin+"/")
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("qldt classes/system/%d http %d: %s", systemID, resp.StatusCode, string(body))
|
|
}
|
|
|
|
var outClasses ClassesResponse
|
|
if err := json.Unmarshal(body, &outClasses); err != nil {
|
|
return nil, err
|
|
}
|
|
if outClasses.StatusCode != 0 && outClasses.StatusCode != 200 {
|
|
return nil, fmt.Errorf("qldt classes statusCode %d", outClasses.StatusCode)
|
|
}
|
|
return &outClasses, nil
|
|
}
|
|
|
|
func (c *Client) GetClassDashboard(ctx context.Context, token string, classID, courseID int64) ([]byte, error) {
|
|
u := fmt.Sprintf("%s/classes/dashboard/%d/%d", c.baseURL, classID, courseID)
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
if c.origin != "" {
|
|
req.Header.Set("Origin", c.origin)
|
|
req.Header.Set("Referer", c.origin+"/")
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("qldt classes/dashboard/%d/%d http %d: %s", classID, courseID, resp.StatusCode, string(body))
|
|
}
|
|
|
|
var probe struct {
|
|
StatusCode int `json:"statusCode"`
|
|
Message string `json:"message"`
|
|
}
|
|
if err := json.Unmarshal(body, &probe); err == nil {
|
|
if probe.StatusCode != 0 && probe.StatusCode != 200 {
|
|
return nil, fmt.Errorf("qldt classes/dashboard statusCode %d: %s", probe.StatusCode, probe.Message)
|
|
}
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
func (c *Client) GetLeaveRequests(ctx context.Context, token string, classID, courseID int64, date string) ([]byte, error) {
|
|
u := fmt.Sprintf("%s/request-leave?classId=%d&courseId=%d&date=%s", c.baseURL, classID, courseID, date)
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.setAuthHeaders(req, token)
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("qldt request-leave http %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
func (c *Client) UpdateLeaveStatus(ctx context.Context, token string, leaveID int64, status string) ([]byte, error) {
|
|
payload := map[string]string{"status": status}
|
|
jsonData, _ := json.Marshal(payload)
|
|
|
|
u := fmt.Sprintf("%s/request-leave/%d/status", c.baseURL, leaveID)
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, u, bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
c.setAuthHeaders(req, token)
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
// Fallback to POST method if PATCH is Method Not Allowed or Not Found
|
|
if resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotFound {
|
|
req2, err2 := http.NewRequestWithContext(ctx, http.MethodPost, u, bytes.NewBuffer(jsonData))
|
|
if err2 == nil {
|
|
req2.Header.Set("Content-Type", "application/json")
|
|
c.setAuthHeaders(req2, token)
|
|
resp2, errOr := c.http.Do(req2)
|
|
if errOr == nil {
|
|
defer resp2.Body.Close()
|
|
body2, _ := io.ReadAll(resp2.Body)
|
|
if resp2.StatusCode >= 200 && resp2.StatusCode < 300 {
|
|
return body2, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("qldt request-leave/%d/status http %d: %s", leaveID, resp.StatusCode, string(body))
|
|
}
|
|
return body, nil
|
|
}
|