From a664b6bfbc9f1ae5704421549106efc502fa49b6 Mon Sep 17 00:00:00 2001 From: beebeeoii Date: Sun, 2 Jan 2022 12:44:15 +0800 Subject: [PATCH 1/3] documentations added for internal packages --- internal/app/app.go | 7 +++++++ internal/app/auth/auth.go | 3 +++ internal/app/dir/dir.go | 8 ++++++++ internal/app/integrations/telegram/telegram.go | 2 ++ internal/app/lock/lock.go | 2 ++ internal/app/pref/pref.go | 3 +++ main.go | 2 ++ 7 files changed, 27 insertions(+) diff --git a/internal/app/app.go b/internal/app/app.go index b261286..e375a29 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -1,3 +1,4 @@ +// Package app provides primitives to initialise crucial files for Lominus. package app import ( @@ -13,6 +14,9 @@ import ( "github.com/beebeeoii/lominus/pkg/pref" ) +// Init initialises and ensures log and preference files that Lominus requires are available. +// Directory in Preferences defaults to empty string (""). +// Frequency in Preferences defaults to -1. func Init() error { baseDir := appDir.GetBaseDir() @@ -39,6 +43,9 @@ func Init() error { return nil } +// GetOs returns user's running program's operating system target: +// one of darwin, freebsd, linux, and so on. +// To view possible combinations of GOOS and GOARCH, run "go tool dist list". func GetOs() string { return runtime.GOOS } diff --git a/internal/app/auth/auth.go b/internal/app/auth/auth.go index 1ccd7dc..c063b92 100644 --- a/internal/app/auth/auth.go +++ b/internal/app/auth/auth.go @@ -1,3 +1,4 @@ +// Package appAuth provides path retrievers for Lominus auth files. package appAuth import ( @@ -7,10 +8,12 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// GetJwtPath returns the file path to user's JWT data. func GetJwtPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.JWT_DATA_FILE_NAME) } +// GetJwtPath returns the file path to user's credentials. func GetCredentialsPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.CREDENTIALS_FILE_NAME) } diff --git a/internal/app/dir/dir.go b/internal/app/dir/dir.go index 500da05..7ba808a 100644 --- a/internal/app/dir/dir.go +++ b/internal/app/dir/dir.go @@ -1,3 +1,4 @@ +// Package appDir provides directory generators for Lominus config files. package appDir import ( @@ -8,6 +9,13 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// GetBaseDir returns the directory where config files for Lominus will be stored in. +// It uses os.UserConfigDir() under the hood and appends lominus.APP_NAME to it. +// On Unix systems, os.UserConfigDir() returns $XDG_CONFIG_HOME as specified by https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html +// if non-empty, else $HOME/.config. +// On Darwin, it returns $HOME/Library/Application Support. +// On Windows, it returns %AppData%. On Plan 9, it returns $home/lib. +// If the location cannot be determined (for example, $HOME is not defined), then it will return an error. func GetBaseDir() string { userConfigDir, err := os.UserConfigDir() if err != nil { diff --git a/internal/app/integrations/telegram/telegram.go b/internal/app/integrations/telegram/telegram.go index ed456c7..8e4b162 100644 --- a/internal/app/integrations/telegram/telegram.go +++ b/internal/app/integrations/telegram/telegram.go @@ -1,3 +1,4 @@ +// Package intTelegram provides path retrievers for Lominus Telegram integration files. package intTelegram import ( @@ -7,6 +8,7 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// GetTelegramInfoPath returns the file path to user's telegram config file. func GetTelegramInfoPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.TELEGRAM_FILE_NAME) } diff --git a/internal/app/lock/lock.go b/internal/app/lock/lock.go index 9dad1cb..0ac0a92 100644 --- a/internal/app/lock/lock.go +++ b/internal/app/lock/lock.go @@ -1,3 +1,4 @@ +// Package appLock provides path retrievers for Lominus lock file. package appLock import ( @@ -7,6 +8,7 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// GetLockPath returns the file path to Lominus lock file. func GetLockPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.LOCK_FILE_NAME) } diff --git a/internal/app/pref/pref.go b/internal/app/pref/pref.go index f559c1a..6b04cd4 100644 --- a/internal/app/pref/pref.go +++ b/internal/app/pref/pref.go @@ -1,3 +1,4 @@ +// Package appPref provides path retrievers for Lominus preferences files. package appPref import ( @@ -7,11 +8,13 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// Preferences struct describes the data being stored in the user's preferences file. type Preferences struct { Directory string Frequency int } +// GetJwtPath returns the file path to user's preferences. func GetPreferencesPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.PREFERENCES_FILE_NAME) } diff --git a/main.go b/main.go index 438eb79..3f271cf 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +// Package main is where Lominus starts from. package main import ( @@ -10,6 +11,7 @@ import ( "github.com/juju/fslock" ) +// Main is the starting point of where magic begins. func main() { appInitErr := app.Init() if appInitErr != nil { From 7e8bff0b635746dab29d1b7867ab99a77126347b Mon Sep 17 00:00:00 2001 From: beebeeoii Date: Wed, 5 Jan 2022 10:47:42 +0800 Subject: [PATCH 2/3] documentations added for internal packages --- internal/cron/cron.go | 13 +++++++++++++ internal/file/file.go | 10 ++++++++++ internal/indexing/indexing.go | 11 +++++++++++ internal/log/logs.go | 3 +++ internal/lominus/lominus.go | 1 + internal/notifications/notifications.go | 4 ++++ internal/ui/systray.go | 3 +++ internal/ui/ui.go | 8 ++++++++ 8 files changed, 53 insertions(+) diff --git a/internal/cron/cron.go b/internal/cron/cron.go index 0aacc18..a42f053 100644 --- a/internal/cron/cron.go +++ b/internal/cron/cron.go @@ -1,3 +1,4 @@ +// Package cron provides primitives to initialise and control the main cron scheduler. package cron import ( @@ -23,6 +24,8 @@ var mainScheduler *gocron.Scheduler var mainJob *gocron.Job var LastRanChannel chan string +// Init initialises the cronjob with the desired frequency set by the user. +// If frequency is unset, cronjob is not initialised. func Init() error { mainScheduler = gocron.NewScheduler(time.Local) LastRanChannel = make(chan string) @@ -47,6 +50,7 @@ func Init() error { return nil } +// Rerun clears the job from the scheduler and reschedules the same job with the new frequency. func Rerun(frequency int) error { mainScheduler.Clear() @@ -65,14 +69,19 @@ func Rerun(frequency int) error { return nil } +// GetNextRun returns the next time the cronjob would run. func GetNextRun() time.Time { return mainJob.NextRun() } +// GetLastRan returns the last time the cronjob ran. func GetLastRan() time.Time { return mainJob.LastRun() } +// createJob creates the cronjob that would run at the given frequency. +// It returns a Job which can be used in the main scheduler. +// This is where the bulk of the syncing logic lives. func createJob(frequency int) (*gocron.Job, error) { return mainScheduler.Every(frequency).Hours().Do(func() { notifications.NotificationChannel <- notifications.Notification{Title: "Sync", Content: "Syncing in progress"} @@ -208,6 +217,8 @@ func createJob(frequency int) (*gocron.Job, error) { }) } +// downloadFile is a helper function to download the respective files into their corresponding +// directory based on the File's Ancestors. func downloadFile(baseDir string, file api.File) error { fileDirSlice := append([]string{baseDir}, file.Ancestors...) ensureDir(filepath.Join(append(fileDirSlice, file.Name)...)) @@ -220,6 +231,8 @@ func downloadFile(baseDir string, file api.File) error { return downloadReq.Download(filepath.Join(fileDirSlice...)) } +// ensureDir is a helper function that ensures that the directory exists by creating them +// if they do not already exist. func ensureDir(dir string) { dirName := filepath.Dir(dir) if _, serr := os.Stat(dirName); serr != nil { diff --git a/internal/file/file.go b/internal/file/file.go index 2553603..f2b75d7 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -1,3 +1,4 @@ +// Package file provides util primitives to file operations. package file import ( @@ -6,6 +7,10 @@ import ( "os" ) +// EncodeStructToFile takes in any struct and encodes it into a file specified by fileName. +// If the file already exists, it is truncated. +// If the file does not exist, it is created with mode 0666 (before umask). +// Provide absolute path else file will be written to the current working directory. func EncodeStructToFile(fileName string, data interface{}) error { file, err := os.Create(fileName) if err != nil { @@ -20,6 +25,8 @@ func EncodeStructToFile(fileName string, data interface{}) error { return nil } +// DecodeStructFromFile takes a file that has been encoded by a struct and decodes it back to the struct. +// Provide absolute path else file may not be found. func DecodeStructFromFile(fileName string, data interface{}) error { file, err := os.Open(fileName) if err != nil { @@ -32,16 +39,19 @@ func DecodeStructFromFile(fileName string, data interface{}) error { return err } +// Exists checks if the given file exists. func Exists(name string) bool { _, err := os.Stat(name) return err == nil } +// FileNotFoundError struct is an error struct that contains the custom error that will be thrown when file is not found. type FileNotFoundError struct { FileName string } +// FileNotFoundError is an error that will be thrown when file is not found. func (e *FileNotFoundError) Error() string { return fmt.Sprintf("FileNotFoundError: %s cannot be found.", e.FileName) } diff --git a/internal/indexing/indexing.go b/internal/indexing/indexing.go index 54171fc..d765882 100644 --- a/internal/indexing/indexing.go +++ b/internal/indexing/indexing.go @@ -1,3 +1,4 @@ +// Package file provides primitives to file indexing for sync operations. package indexing import ( @@ -13,10 +14,14 @@ import ( "github.com/beebeeoii/lominus/pkg/api" ) +// IndexMap struct contains an array of IndexMapEntry. +// It is used to create a .csv IndexMap file for file comparison during syncs. type IndexMap struct { Entries []IndexMapEntry } +// IndexMapEntry struct contains the file Id, name and last updated (unix). +// These are the data used for file comparison during syncs. type IndexMapEntry struct { Id string FileName string @@ -25,6 +30,9 @@ type IndexMapEntry struct { const INDEX_MAP_FILE_NAME = "index_map.csv" +// Build is used to create a map of the current files on the local desktop. +// The built map will be used to compare with the IndexMap to determine whether a file +// needs to be downloaded or updated. func Build(dir string) (map[string]api.File, error) { filesMap := make(map[string]api.File) err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { @@ -49,6 +57,7 @@ func Build(dir string) (map[string]api.File, error) { return filesMap, err } +// CreateIndexMap writes the IndexMap to a csv file for which can be loaded for the next sync. func CreateIndexMap(indexMap IndexMap) error { logs.InfoLogger.Printf("Creating index map: %s\n", INDEX_MAP_FILE_NAME) indexMapFile, _ := os.Create(getIndexMapPath()) @@ -66,6 +75,7 @@ func CreateIndexMap(indexMap IndexMap) error { return nil } +// LoadIndexMap loads the IndexMap csv file back to a map of IndexMapEntry, with the key being the file Id. func LoadIndexMap(file io.Reader) (map[string]IndexMapEntry, error) { logs.InfoLogger.Printf("Loading index map: %s\n", INDEX_MAP_FILE_NAME) r := csv.NewReader(file) @@ -88,6 +98,7 @@ func LoadIndexMap(file io.Reader) (map[string]IndexMapEntry, error) { return indexMap, nil } +// getIndexMapPath returns the file path to the IndexMap csv file. func getIndexMapPath() string { return filepath.Join(appDir.GetBaseDir(), INDEX_MAP_FILE_NAME) } diff --git a/internal/log/logs.go b/internal/log/logs.go index 98f69d5..08a293d 100644 --- a/internal/log/logs.go +++ b/internal/log/logs.go @@ -1,3 +1,4 @@ +// Package logs provides primitives to initialise and access the logger. package logs import ( @@ -15,6 +16,7 @@ var ( ErrorLogger *log.Logger ) +// Init initialises the log file and the different loggers: WarningLogger, InfoLogger and ErrorLogger. func Init() error { file, err := os.OpenFile(getLogPath(), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) if err != nil { @@ -30,6 +32,7 @@ func Init() error { return nil } +// getLogPath returns the file path to the log file. func getLogPath() string { return filepath.Join(appDir.GetBaseDir(), lominus.LOG_FILE_NAME) } diff --git a/internal/lominus/lominus.go b/internal/lominus/lominus.go index 325bddc..c335a7e 100644 --- a/internal/lominus/lominus.go +++ b/internal/lominus/lominus.go @@ -1,3 +1,4 @@ +// Package lominus provides app config constants. package lominus const APP_NAME = "Lominus" diff --git a/internal/notifications/notifications.go b/internal/notifications/notifications.go index b1a2ff0..99c1912 100644 --- a/internal/notifications/notifications.go +++ b/internal/notifications/notifications.go @@ -1,5 +1,7 @@ +// Package notifications provides primitives to initialise the notification channel. package notifications +// Notification struct type Notification struct { Title string Content string @@ -7,6 +9,8 @@ type Notification struct { var NotificationChannel chan Notification +// Init initialises the notification channel which can be used to push notifications +// to the user. func Init() { NotificationChannel = make(chan Notification) } diff --git a/internal/ui/systray.go b/internal/ui/systray.go index 8815016..03a95df 100644 --- a/internal/ui/systray.go +++ b/internal/ui/systray.go @@ -1,3 +1,4 @@ +// Package ui provides primitives that initialises the UI. package ui import ( @@ -12,6 +13,7 @@ import ( var lastRanItem *systray.MenuItem +// onReady builds and initialises the system tray UI. func onReady() { systray.SetIcon(resourceAppIconIco.Content()) systray.SetTitle(lominus.APP_NAME) @@ -41,6 +43,7 @@ func onReady() { }() } +// onExit describes the actions taken when user quits the system tray. func onExit() { logs.InfoLogger.Println("lominus quit") mainApp.Quit() diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 91b4a30..5c4bfb1 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -1,3 +1,4 @@ +// Package ui provides primitives that initialises the UI. package ui import ( @@ -49,6 +50,7 @@ var frequencyMap = map[int]string{ var mainApp fyne.App var w fyne.Window +// Init builds and initialises the UI. func Init() error { if runtime.GOOS == "windows" { systray.Register(onReady, onExit) @@ -103,6 +105,7 @@ func Init() error { return nil } +// getCredentialsTab builds the credentials tab in the main UI. func getCredentialsTab(parentWindow fyne.Window) (*container.TabItem, error) { tab := container.NewTabItem("Login Info", container.NewVBox()) @@ -164,6 +167,7 @@ func getCredentialsTab(parentWindow fyne.Window) (*container.TabItem, error) { return tab, nil } +// getPreferencesTab builds the preferences tab in the main UI. func getPreferencesTab(parentWindow fyne.Window) (*container.TabItem, error) { tab := container.NewTabItem("Preferences", container.NewVBox()) @@ -247,6 +251,7 @@ func getPreferencesTab(parentWindow fyne.Window) (*container.TabItem, error) { return tab, nil } +// getIntegrationsTab builds the integrations tab in the main UI. func getIntegrationsTab(parentWindow fyne.Window) (*container.TabItem, error) { tab := container.NewTabItem("Integrations", container.NewVBox()) @@ -310,6 +315,7 @@ func getIntegrationsTab(parentWindow fyne.Window) (*container.TabItem, error) { return tab, nil } +// getPreferences is a util function that retrieves the user's preferences. func getPreferences() appPref.Preferences { preference, err := pref.LoadPreferences(appPref.GetPreferencesPath()) if err != nil { @@ -319,6 +325,7 @@ func getPreferences() appPref.Preferences { return preference } +// getSyncButton builds the sync button in the main UI. func getSyncButton(parentWindow fyne.Window) *widget.Button { return widget.NewButton("Sync Now", func() { preferences := getPreferences() @@ -334,6 +341,7 @@ func getSyncButton(parentWindow fyne.Window) *widget.Button { }) } +// getQuitButton builds the quit button in the main UI. func getQuitButton() *widget.Button { return widget.NewButton("Quit Lominus", func() { if appApp.GetOs() == "windows" { From 880ab1f8091de1fad31a52138fe3ff3b2efe7ff5 Mon Sep 17 00:00:00 2001 From: beebeeoii Date: Wed, 5 Jan 2022 11:50:03 +0800 Subject: [PATCH 3/3] documentations added for api packages --- pkg/api/files.go | 21 ++++++++++++++++++++- pkg/api/grades.go | 6 ++++-- pkg/api/modules.go | 3 +++ pkg/api/request.go | 15 ++++++++++++++- pkg/api/response.go | 6 +++++- pkg/auth/auth.go | 12 ++++++++++++ pkg/integrations/telegram/telegram.go | 9 +++++++++ pkg/pref/pref.go | 3 +++ pkg/sync/sync.go | 1 + 9 files changed, 71 insertions(+), 5 deletions(-) diff --git a/pkg/api/files.go b/pkg/api/files.go index cfcd38e..c3a58fc 100644 --- a/pkg/api/files.go +++ b/pkg/api/files.go @@ -1,3 +1,4 @@ +// Package api provides functions that link up and communicate with Luminus servers. package api import ( @@ -11,6 +12,9 @@ import ( "time" ) +// Folder struct is the datapack for containing details about a Folder +// Ancestors the relative folders that precedes the current folder, including itself. +// Eg. Ancestors for a folder with the path: /folder1/folder2/folder3 is ['folder1', 'folder2', 'folder3'] type Folder struct { Id string Name string @@ -19,6 +23,9 @@ type Folder struct { Ancestors []string } +// File struct is the datapack for containing details about a File +// Ancestors the relative folders that precedes the current folder, including itself. +// Eg. Ancestors for a file with the path: /folder1/folder2/file.pdf is ['folder1', 'folder2', 'file.pdf'] type File struct { Id string Name string @@ -30,6 +37,9 @@ const FOLDER_URL_ENDPOINT = "https://luminus.nus.edu.sg/v2/api/files/?populate=t const FILE_URL_ENDPOINT = "https://luminus.nus.edu.sg/v2/api/files/%s/file?populate=Creator,lastUpdatedUser,comment" const DOWNLOAD_URL_ENDPOINT = "https://luminus.nus.edu.sg/v2/api/files/file/%s/downloadurl" +// GetAllFolders returns a slice of Folder objects from a DocumentRequest. +// Ensure DocumentRequest mode is GET_FOLDERS (0). +// Find out more about DocumentRequests under request.go. func (req DocumentRequest) GetAllFolders() ([]Folder, error) { folder := []Folder{} if req.Mode != GET_FOLDERS { @@ -57,7 +67,10 @@ func (req DocumentRequest) GetAllFolders() ([]Folder, error) { return folder, nil } -// Deprecated - build DocumentRequest with a Folder instead of a module instead, and call getRootFiles() directly +// Deprecated - build DocumentRequest with a Folder instead of a module instead, and call getRootFiles() directly. +// GetAllFiles returns a slice of File objects that are in a Folder using a DocumentRequest. +// Ensure DocumentRequest mode is GET_ALL_FILES (1). +// Find out more about DocumentRequests under request.go. func (req DocumentRequest) GetAllFiles() ([]File, error) { files := []File{} if req.Mode != GET_ALL_FILES { @@ -85,6 +98,9 @@ func (req DocumentRequest) GetAllFiles() ([]File, error) { return files, nil } +// getRootFiles returns a slice of File objects and nested File objects that are in a Folder or nested Folder from a DocumentRequest. +// Ensure DocumentRequest mode is GET_FILES (3). +// Find out more about DocumentRequests under request.go. func (req DocumentRequest) getRootFiles() ([]File, error) { files := []File{} if req.Mode != GET_FILES { @@ -147,6 +163,9 @@ func (req DocumentRequest) getRootFiles() ([]File, error) { return files, nil } +// Download downloads the specified file in a DocumentRequest into local storage. +// Ensure DocumentRequest mode is DOWNLOAD_FILE (2). +// Find out more about DocumentRequests under request.go. func (req DocumentRequest) Download(filePath string) error { if req.Mode != DOWNLOAD_FILE { return errors.New("mode mismatched: ensure DocumentRequest mode is DOWNLOAD_FILE (2)") diff --git a/pkg/api/grades.go b/pkg/api/grades.go index 6211f56..b4cc9a6 100644 --- a/pkg/api/grades.go +++ b/pkg/api/grades.go @@ -1,10 +1,11 @@ +// Package api provides functions that link up and communicate with Luminus servers. package api import ( "time" ) -// Grade struct is the datapack for containing details about every Grade in a module +// Grade struct is the datapack for containing details about every Grade in a module. type Grade struct { Name string Marks float64 @@ -15,7 +16,8 @@ type Grade struct { const GRADE_URL_ENDPOINT = "https://luminus.nus.edu.sg/v2/api/gradebook/?populate=scores&ParentID=%s" -// Retrieves all grades for a particular module represented by moduleCode. +// GetGrades retrieves all grades for a particular module represented by moduleCode specified in GradeRequest. +// Find out more about GradeRequests under request.go. func (req GradeRequest) GetGrades() ([]Grade, error) { var grades []Grade diff --git a/pkg/api/modules.go b/pkg/api/modules.go index 33bb92b..3f2f3dc 100644 --- a/pkg/api/modules.go +++ b/pkg/api/modules.go @@ -1,3 +1,4 @@ +// Package api provides functions that link up and communicate with Luminus servers. package api // Module struct is the datapack for containing details about every module @@ -12,6 +13,8 @@ type Module struct { const MODULE_URL_ENDPOINT = "https://luminus.nus.edu.sg/v2/api/module/?populate=Creator,termDetail,isMandatory" +// GetModules retrieves all modules that are taken by the user using a ModuleRequest. +// Find out more about ModuleRequests under request.go. func (req ModuleRequest) GetModules() ([]Module, error) { var modules []Module diff --git a/pkg/api/request.go b/pkg/api/request.go index 7f7d64b..522d100 100644 --- a/pkg/api/request.go +++ b/pkg/api/request.go @@ -1,3 +1,4 @@ +// Package api provides functions that link up and communicate with Luminus servers. package api import ( @@ -8,12 +9,14 @@ import ( "github.com/beebeeoii/lominus/pkg/auth" ) +// Request struct is the datapack for containing details about a HTTP request. type Request struct { Url string JwtToken string UserAgent string } +// DocumentRequest struct is the datapack for containing details about a specific HTTP request used for documents (Luminus Files). type DocumentRequest struct { File File Folder Folder @@ -22,11 +25,13 @@ type DocumentRequest struct { Mode int } +// GradeRequest struct is the datapack for containing details about a specific HTTP request used for grades (Luminus Gradebook). type GradeRequest struct { Module Module Request Request } +// ModuleRequest struct is the datapack for containing details about a specific HTTP request used for modules being taken. type ModuleRequest struct { Request Request } @@ -40,6 +45,8 @@ const ( const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0" +// BuildModuleRequest builds and returns a ModuleRequest that can be used for Module related operations +// such as retrieving all modules. func BuildModuleRequest() (ModuleRequest, error) { jwtToken, jwtTokenErr := retrieveJwtToken() if jwtTokenErr != nil { @@ -55,6 +62,9 @@ func BuildModuleRequest() (ModuleRequest, error) { }, nil } +// BuildGradeRequest builds and returns a GradeRequest that can be used for Grade related operations +// such as retrieving grades of a module. +// A Module is required to build a GradeRequest as it is module specific. func BuildGradeRequest(module Module) (GradeRequest, error) { jwtToken, jwtTokenErr := retrieveJwtToken() if jwtTokenErr != nil { @@ -71,7 +81,9 @@ func BuildGradeRequest(module Module) (GradeRequest, error) { }, nil } -// DocumentRequests must be built using Module or Folder only. +// BuildDocumentRequest builds and returns a DocumentRequest that can be used for File/Folder related operations +// such as retrieving files/folders of a module. +// DocumentRequests must be built using Module/Folder/File only. // Building it with Folder enables you to specify the specific folder you are interested in. // Building it with Module taks you to the root folder of the module files. // Building it with File enables you to download the file. @@ -141,6 +153,7 @@ func BuildDocumentRequest(builder interface{}, mode int) (DocumentRequest, error } } +// retrieveJwtToken is a util function that loads user's JWT data to be used to communicate with Luminus servers. func retrieveJwtToken() (string, error) { jwtData, jwtErr := auth.LoadJwtData(appAuth.GetJwtPath()) if jwtErr != nil { diff --git a/pkg/api/response.go b/pkg/api/response.go index 89ae0ce..7f592b4 100644 --- a/pkg/api/response.go +++ b/pkg/api/response.go @@ -1,3 +1,4 @@ +// Package api provides functions that link up and communicate with Luminus servers. package api import ( @@ -6,7 +7,7 @@ import ( "net/http" ) -// raw struct is the datapack for containing api raw data +// RawResponse struct is the datapack for containing API response raw data. type RawResponse struct { Status string `json:"status"` Code int `json:"code"` @@ -15,12 +16,15 @@ type RawResponse struct { Data []map[string]interface{} `json:"data"` } +// DownloadResponse struct is the datapack for containing API download response raw data. type DownloadResponse struct { Code int `json:"code"` Status string `json:"status"` DownloadUrl string `json:"data"` } +// GetRawResponse sends the HTTP request and marshals it into the pointer provided. +// Argument provided must be a pointer. func (req Request) GetRawResponse(res interface{}) error { request, err := http.NewRequest("GET", req.Url, nil) diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 617536a..046c273 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -1,3 +1,4 @@ +// Package auth provides functions that link up and communicate with Luminus authentication server. package auth import ( @@ -13,17 +14,20 @@ import ( "github.com/beebeeoii/lominus/internal/lominus" ) +// JsonResponse struct is the datapack for containing API authentication response raw data. type JsonResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` } +// JwtData struct is the datapack that describes the user's JWT data. type JwtData struct { JwtToken string Expiry int64 } +// Credentials struct is the datapack that describes the user's credentials. type Credentials struct { Username string Password string @@ -46,6 +50,7 @@ const AUTH_METHOD = "FormsAuthentication" const EXPIRY_HOURS = 1 +// RetrieveJwtToken takes in the user's Credentials and return a JWT token issued by Luminus authentication server. func RetrieveJwtToken(credentials Credentials, save bool) (string, error) { var jwtToken string client := &http.Client{ @@ -123,11 +128,13 @@ func RetrieveJwtToken(credentials Credentials, save bool) (string, error) { return jwtToken, nil } +// saveJwtData saves the user's JWT data to local storage for future use. func saveJwtData(jwtPath string, jwtToken string) error { jwtData := JwtData{jwtToken, time.Now().Add(time.Hour * 24).Unix()} return file.EncodeStructToFile(jwtPath, jwtData) } +// LoadJwtData loads the user's JWT data from local storage. func LoadJwtData(jwtPath string) (JwtData, error) { jwtData := JwtData{} if !file.Exists(jwtPath) { @@ -138,10 +145,12 @@ func LoadJwtData(jwtPath string) (JwtData, error) { return jwtData, err } +// SaveCredentials saves the user's Credentials for future authentications or renewals of JWT data. func SaveCredentials(credentialsPath string, credentials Credentials) error { return file.EncodeStructToFile(credentialsPath, credentials) } +// LoadCredentials loads the user's Credentials data from local storage. func LoadCredentials(credentialsPath string) (Credentials, error) { credentials := Credentials{} if !file.Exists(credentialsPath) { @@ -152,13 +161,16 @@ func LoadCredentials(credentialsPath string) (Credentials, error) { return credentials, err } +// IsExpired is a util function that checks if the user's JWT data has expired. func (jwtData JwtData) IsExpired() bool { expiry := time.Unix(jwtData.Expiry, 0) return time.Until(expiry).Hours() <= EXPIRY_HOURS } +// JwtExpiredError struct contains the JwtExpiredError which will be thrown when the JWT data has expired. type JwtExpiredError struct{} +// JwtExpiredError error to be thrown when the JWT data has expired. func (e *JwtExpiredError) Error() string { return "JwtExpiredError: JWT token has expired." } diff --git a/pkg/integrations/telegram/telegram.go b/pkg/integrations/telegram/telegram.go index 3eb7b98..760ca0c 100644 --- a/pkg/integrations/telegram/telegram.go +++ b/pkg/integrations/telegram/telegram.go @@ -1,3 +1,4 @@ +// Package telegram provides functions that facilitates the integration with Telegram. package telegram import ( @@ -10,11 +11,13 @@ import ( "github.com/beebeeoii/lominus/internal/file" ) +// TelegramInfo struct is the datapack that holds the data required for Telegram integration. type TelegramInfo struct { BotApi string UserId string } +// TelegramError struct contains the TelegramError which will be thrown when an error is returned by Telegram servers. type TelegramError struct { Description string } @@ -23,6 +26,7 @@ const SEND_MSG_URL = "https://api.telegram.org/bot%s/sendMessage" const CONTENT_TYPE = "application/x-www-form-urlencoded" const POST = "POST" +// SendMessage is a wrapper function that sends a message to the user using the Bot (specified by the botApi) created by the user. func SendMessage(botApi string, userId string, message string) error { client := &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { @@ -61,10 +65,12 @@ func SendMessage(botApi string, userId string, message string) error { return nil } +// GenerateGradeMessageFormat creates a message text for grade notifications. func GenerateGradeMessageFormat(moduleName string, testName string, comments string, marks float64, maxMarks float64) string { return fmt.Sprintf("🆕 Grades 🆕\n%s: %s\n\nComments: %s\n\nGrade: %f/%f", moduleName, testName, comments, marks, maxMarks) } +// cleanseMessage escapes restricted chracters in messages that would cause Telegram servers to return an error. func cleanseMessage(message string) string { message = strings.Replace(message, ".", "\\.", -1) message = strings.Replace(message, "-", "\\-", -1) @@ -88,10 +94,12 @@ func cleanseMessage(message string) string { return message } +// SaveTelegramData saves the user's Telegram data onto local storage. func SaveTelegramData(telegramDataPath string, telegramInfo TelegramInfo) error { return file.EncodeStructToFile(telegramDataPath, telegramInfo) } +// LoadTelegramData loads the user's Telegram data from local storage. func LoadTelegramData(telegramDataPath string) (TelegramInfo, error) { telegramInfo := TelegramInfo{} if !file.Exists(telegramDataPath) { @@ -102,6 +110,7 @@ func LoadTelegramData(telegramDataPath string) (TelegramInfo, error) { return telegramInfo, err } +// TelegramError error will be thrown when an error is returned by Telegram servers. func (e *TelegramError) Error() string { return fmt.Sprintf("TelegramError: %s", e.Description) } diff --git a/pkg/pref/pref.go b/pkg/pref/pref.go index b84944e..da188a3 100644 --- a/pkg/pref/pref.go +++ b/pkg/pref/pref.go @@ -1,3 +1,4 @@ +// Package pref provides primitives that interacts with Preference files. package pref import ( @@ -10,10 +11,12 @@ const PREFERENCES_FILE_NAME = lominus.PREFERENCES_FILE_NAME var Preferences = appPref.Preferences{} +// SavePreferences saves the user's preferences data onto local storage. func SavePreferences(filePath string, preferences appPref.Preferences) error { return file.EncodeStructToFile(filePath, preferences) } +// LoadPreferences loads the user's preferences data from local storage. func LoadPreferences(filePath string) (appPref.Preferences, error) { preferences := appPref.Preferences{} if !file.Exists(filePath) { diff --git a/pkg/sync/sync.go b/pkg/sync/sync.go index 65f6d53..999ab9d 100644 --- a/pkg/sync/sync.go +++ b/pkg/sync/sync.go @@ -1,3 +1,4 @@ +// Package sync is deprecated (please do not use) package sync import (