|
@@ -1,326 +0,0 @@
|
|
|
-package main
|
|
|
-
|
|
|
-import (
|
|
|
- "net/http"
|
|
|
- "log"
|
|
|
- "strings"
|
|
|
- "path/filepath"
|
|
|
- "encoding/json"
|
|
|
- "os"
|
|
|
- "fmt"
|
|
|
- "strconv"
|
|
|
-)
|
|
|
-
|
|
|
-/*
|
|
|
- AirMUsic - Maybe the best music playback app on ArOZ Online
|
|
|
-
|
|
|
- CopyRight Toby Chui, 2020
|
|
|
-*/
|
|
|
-
|
|
|
-func module_Music_init(){
|
|
|
- http.HandleFunc("/Music/listSong", module_airMusic_listSong)
|
|
|
- http.HandleFunc("/Music/getMeta", module_airMusic_getMeta)
|
|
|
- http.HandleFunc("/Music/getFileInfo", module_airMusic_getFileInfo)
|
|
|
-
|
|
|
-
|
|
|
- //Register this module to system
|
|
|
- registerModule(moduleInfo{
|
|
|
- Name: "Music",
|
|
|
- Desc: "The basic music player for ArOZ Online",
|
|
|
- Group: "Media",
|
|
|
- IconPath: "Music/img/module_icon.png",
|
|
|
- Version: "0.0.4",
|
|
|
- StartDir: "Music/index.html",
|
|
|
- SupportFW: true,
|
|
|
- LaunchFWDir: "Music/index.html",
|
|
|
- SupportEmb: true,
|
|
|
- LaunchEmb: "Music/embedded.html",
|
|
|
- InitFWSize: []int{475, 700},
|
|
|
- InitEmbSize: []int{360, 240},
|
|
|
- SupportedExt: []string{".mp3",".flac",".wav",".ogg",".aac",".webm",".mp4"},
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-func module_airMusic_getMeta(w http.ResponseWriter, r *http.Request){
|
|
|
- username, err := authAgent.GetUserName(w,r);
|
|
|
- if (err != nil){
|
|
|
- sendErrorResponse(w,"User not logged in")
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- playingFile, _ := mv(r, "file", false)
|
|
|
- playingFile = system_fs_specialURIDecode(playingFile)
|
|
|
- rPlayingFilePath, _ := virtualPathToRealPath(playingFile, username)
|
|
|
- fileDir := filepath.ToSlash(filepath.Dir(rPlayingFilePath))
|
|
|
- supportedFileExt := []string{".mp3",".flac",".wav",".ogg",".aac",".webm",".mp4"}
|
|
|
- var fileInfos [][]string
|
|
|
- objs, _ := system_fs_specialGlob(fileDir + "/*")
|
|
|
- for _, obj := range objs{
|
|
|
- if (!IsDir(obj) && stringInSlice(filepath.Ext(obj), supportedFileExt)){
|
|
|
- //This is a file that we want to list
|
|
|
- var thisFileInfo []string
|
|
|
- fileExt := filepath.Ext(obj)[1:]
|
|
|
- fileName := filepath.Base(obj)
|
|
|
- filePath, _ := realpathToVirtualpath(obj, username)
|
|
|
- _, hsize, unit, _ := system_fs_getFileSize(obj)
|
|
|
- size := fmt.Sprintf("%.2f", hsize) + unit;
|
|
|
-
|
|
|
- thisFileInfo = append(thisFileInfo, fileName)
|
|
|
- thisFileInfo = append(thisFileInfo, filePath)
|
|
|
- thisFileInfo = append(thisFileInfo, fileExt)
|
|
|
- thisFileInfo = append(thisFileInfo, size)
|
|
|
-
|
|
|
- fileInfos = append(fileInfos, thisFileInfo)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- jsonString, _ := json.Marshal(fileInfos);
|
|
|
- sendJSONResponse(w, string(jsonString));
|
|
|
-}
|
|
|
-
|
|
|
-func module_airMusic_listSong(w http.ResponseWriter, r *http.Request){
|
|
|
- username, err := authAgent.GetUserName(w,r);
|
|
|
- if (err != nil){
|
|
|
- redirectToLoginPage(w,r)
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- var musicDirs []string
|
|
|
- var playLists []string
|
|
|
-
|
|
|
- //Initialize user folder structure if it is not yet init
|
|
|
- uploadDir, _ := virtualPathToRealPath("user:/Music/",username)
|
|
|
- playList, _ := virtualPathToRealPath("user:/Music/playlist",username)
|
|
|
- os.MkdirAll(uploadDir, 0755)
|
|
|
- os.MkdirAll(playList, 0755)
|
|
|
- musicDirs = append(musicDirs, uploadDir);
|
|
|
- playLists = append(playLists, playList);
|
|
|
-
|
|
|
- for _, extStorage := range storages{
|
|
|
- path := extStorage.Path;
|
|
|
- if (path[len(path) - 1:] != "/"){
|
|
|
- path = path + "/"
|
|
|
- }
|
|
|
- musicDirs = append(musicDirs, path)
|
|
|
- }
|
|
|
-
|
|
|
- //Get which folder the user want to list
|
|
|
- lsDir, _ := mv(r, "listdir", false)
|
|
|
- listSong, _ := mv(r, "listSong", false)
|
|
|
- listFolder, _ := mv(r, "listfolder", false)
|
|
|
- supportedFileExt := []string{".mp3",".flac",".wav",".ogg",".aac",".webm"}
|
|
|
-
|
|
|
- //Decode url component if needed
|
|
|
- if (lsDir != ""){
|
|
|
- lsDir = strings.ReplaceAll(lsDir, "%2B","+")
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (listSong != ""){
|
|
|
- //List song mode. List the song in the directories
|
|
|
- if (listSong == "all"){
|
|
|
- songData := [][]string{}
|
|
|
- for _, directory := range musicDirs{
|
|
|
-
|
|
|
- filepath.Walk(directory,
|
|
|
- func(path string, info os.FileInfo, err error) error {
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- path = filepath.ToSlash(path)
|
|
|
-
|
|
|
- if (stringInSlice(filepath.Ext(path),supportedFileExt)){
|
|
|
- //This is an audio file. Append to songData
|
|
|
- var audioFiles []string
|
|
|
- _, hsize, unit, _ := system_fs_getFileSize(path)
|
|
|
- size := fmt.Sprintf("%.2f", hsize) + unit;
|
|
|
- vpath, _ := realpathToVirtualpath(path, username);
|
|
|
- audioFiles = append(audioFiles, "/media?file=" + vpath);
|
|
|
- audioFiles = append(audioFiles, strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)));
|
|
|
- audioFiles = append(audioFiles, filepath.Ext(path)[1:]);
|
|
|
- audioFiles = append(audioFiles, size);
|
|
|
- songData = append(songData, audioFiles)
|
|
|
- }
|
|
|
- return nil
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- jsonString, _ := json.Marshal(songData);
|
|
|
- sendJSONResponse(w, string(jsonString));
|
|
|
-
|
|
|
- }else if (strings.Contains(listSong, "search:")){
|
|
|
- keyword := listSong[7:]
|
|
|
- songData := [][]string{}
|
|
|
- for _, directory := range musicDirs{
|
|
|
-
|
|
|
- filepath.Walk(directory,
|
|
|
- func(path string, info os.FileInfo, err error) error {
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- path = filepath.ToSlash(path)
|
|
|
-
|
|
|
- if (stringInSlice(filepath.Ext(path),supportedFileExt) && strings.Contains(filepath.Base(path),keyword)){
|
|
|
- //This is an audio file. Append to songData
|
|
|
- var audioFiles []string
|
|
|
- _, hsize, unit, _ := system_fs_getFileSize(path)
|
|
|
- size := fmt.Sprintf("%.2f", hsize) + unit;
|
|
|
- vpath, _ := realpathToVirtualpath(path, username);
|
|
|
- audioFiles = append(audioFiles, "/media?file=" + vpath);
|
|
|
- audioFiles = append(audioFiles, strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)));
|
|
|
- audioFiles = append(audioFiles, filepath.Ext(path)[1:]);
|
|
|
- audioFiles = append(audioFiles, size);
|
|
|
- songData = append(songData, audioFiles)
|
|
|
- }
|
|
|
- return nil
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- jsonString, _ := json.Marshal(songData);
|
|
|
- sendJSONResponse(w, string(jsonString));
|
|
|
- }else{
|
|
|
- log.Println("Work in progress")
|
|
|
- }
|
|
|
- }else if (lsDir != ""){
|
|
|
- //List diretory
|
|
|
- if (lsDir == "root"){
|
|
|
- var rootInfo [][]string
|
|
|
- for _, dir := range musicDirs{
|
|
|
- var thisRootInfo []string
|
|
|
- //thisRootInfo = append(thisRootInfo, filepath.Base(dir))
|
|
|
- virtualStorageRootName, err := system_storage_getRootNameByPath(dir, username)
|
|
|
- if (err != nil){
|
|
|
- thisRootInfo = append(thisRootInfo, filepath.Base(dir))
|
|
|
- }else{
|
|
|
- thisRootInfo = append(thisRootInfo, virtualStorageRootName)
|
|
|
- }
|
|
|
-
|
|
|
- vpath, _ := realpathToVirtualpath(dir,username);
|
|
|
- thisRootInfo = append(thisRootInfo, vpath + "/")
|
|
|
- objects, _ := filepath.Glob(dir + "/*")
|
|
|
- var files []string
|
|
|
- var folders []string
|
|
|
- for _, f := range objects{
|
|
|
- if (IsDir(f)){
|
|
|
- folders = append(folders, f)
|
|
|
- }else if (stringInSlice(filepath.Ext(f),supportedFileExt)) {
|
|
|
- files = append(files, f)
|
|
|
- }
|
|
|
- }
|
|
|
- thisRootInfo = append(thisRootInfo, strconv.Itoa(len(files)))
|
|
|
- thisRootInfo = append(thisRootInfo, strconv.Itoa(len(folders)))
|
|
|
- rootInfo = append(rootInfo, thisRootInfo)
|
|
|
- }
|
|
|
- jsonString, _ := json.Marshal(rootInfo)
|
|
|
- sendJSONResponse(w, string(jsonString))
|
|
|
- }else{
|
|
|
- listingTarget, _ := virtualPathToRealPath(lsDir, username);
|
|
|
- if (listingTarget == ""){
|
|
|
- //User try to leave the accessable area. Reject access.
|
|
|
- sendErrorResponse(w, "Permission denied")
|
|
|
- return;
|
|
|
- }
|
|
|
- var results [][][]string
|
|
|
- //List all objects in the current directory and catergorize them
|
|
|
- folders := []string{}
|
|
|
- files := []string{}
|
|
|
- //Special glob for handling path with [ or ]
|
|
|
- objects, _ := system_fs_specialGlob(filepath.Clean(listingTarget) + "/*")
|
|
|
- for _, obj := range objects{
|
|
|
- if (IsDir(obj)){
|
|
|
- folders = append(folders, obj)
|
|
|
- }else if (stringInSlice(filepath.Ext(obj),supportedFileExt)){
|
|
|
- files = append(files, obj)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- folderInfos := [][]string{}
|
|
|
- for _, folder := range folders{
|
|
|
- var thisFolderInfo []string
|
|
|
- folderName := filepath.Base(folder)
|
|
|
- folderPath, _ := realpathToVirtualpath(folder, username)
|
|
|
- filesInDir := 0;
|
|
|
- DirInDir := 0;
|
|
|
- objInDir, _ := system_fs_specialGlob(filepath.ToSlash(folder) + "/*")
|
|
|
- for _, obj := range objInDir{
|
|
|
- if (IsDir(obj)){
|
|
|
- DirInDir++;
|
|
|
- }else if (stringInSlice(filepath.Ext(obj),supportedFileExt)){
|
|
|
- filesInDir++;
|
|
|
- }
|
|
|
- }
|
|
|
- thisFolderInfo = append(thisFolderInfo, folderName)
|
|
|
- thisFolderInfo = append(thisFolderInfo, folderPath + "/")
|
|
|
- thisFolderInfo = append(thisFolderInfo, strconv.Itoa(filesInDir))
|
|
|
- thisFolderInfo = append(thisFolderInfo, strconv.Itoa(DirInDir))
|
|
|
- folderInfos = append(folderInfos, thisFolderInfo)
|
|
|
- }
|
|
|
-
|
|
|
- fileInfos := [][]string{}
|
|
|
- for _, file := range files{
|
|
|
- var thisFileInfo []string
|
|
|
- vfilepath, _ := realpathToVirtualpath(file, username)
|
|
|
- filename := filepath.Base(file)
|
|
|
- ext := filepath.Ext(file)[1:]
|
|
|
- _, hsize, unit, _ := system_fs_getFileSize(file)
|
|
|
- size := fmt.Sprintf("%.2f", hsize) + unit;
|
|
|
-
|
|
|
- thisFileInfo = append(thisFileInfo, "/media?file=" + vfilepath)
|
|
|
- thisFileInfo = append(thisFileInfo, filename)
|
|
|
- thisFileInfo = append(thisFileInfo, ext)
|
|
|
- thisFileInfo = append(thisFileInfo, size)
|
|
|
- fileInfos = append(fileInfos, thisFileInfo)
|
|
|
- }
|
|
|
-
|
|
|
- results = append(results, folderInfos)
|
|
|
- results = append(results, fileInfos)
|
|
|
- jsonString, _ := json.Marshal(results)
|
|
|
- sendJSONResponse(w, string(jsonString))
|
|
|
-
|
|
|
- }
|
|
|
- }else if (listFolder != ""){
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func module_airMusic_getFileInfo(w http.ResponseWriter, r *http.Request){
|
|
|
- username, err := authAgent.GetUserName(w,r);
|
|
|
- if (err != nil){
|
|
|
- sendErrorResponse(w, "User not logged in")
|
|
|
- return;
|
|
|
- }
|
|
|
- vpath, _ := mv(r, "filepath", false)
|
|
|
-
|
|
|
- //Strip away the access path
|
|
|
- if (vpath[:12] == "/media?file="){
|
|
|
- vpath = vpath[12:];
|
|
|
- }
|
|
|
-
|
|
|
- //Convert the virtual path to realpath
|
|
|
- realpath, err := virtualPathToRealPath(vpath, username)
|
|
|
- if (err != nil){
|
|
|
- sendErrorResponse(w, "Invalid filepath")
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (!fileExists(realpath)){
|
|
|
- sendErrorResponse(w, "File not exists")
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- //Buiild the information for sendout
|
|
|
- results := []string{}
|
|
|
- results = append(results, filepath.Base(realpath))
|
|
|
- vdir, _ := realpathToVirtualpath(filepath.Dir(realpath), username)
|
|
|
- results = append(results, vdir)
|
|
|
- rawsize, hsize, unit, _ := system_fs_getFileSize(realpath)
|
|
|
- size := fmt.Sprintf("%.2f", hsize) + unit;
|
|
|
- results = append(results, size)
|
|
|
- results = append(results, fmt.Sprintf("%.2f", rawsize))
|
|
|
- info, err := os.Stat(realpath)
|
|
|
- results = append(results, info.ModTime().Format("2006-01-02 15:04:05"))
|
|
|
-
|
|
|
- jsonString, _ := json.Marshal(results)
|
|
|
- sendJSONResponse(w, string(jsonString))
|
|
|
-}
|
|
|
-
|