Something went wrong. Try again.
A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428// SiYuan - Refactor your thinking// Copyright (c) 2020-present, b3log.org//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program. If not, see <https://www.gnu.org/licenses/>.
package api
import ( "net/http" "strings" "time"
"github.com/88250/gulu" "github.com/gin-gonic/gin" "github.com/siyuan-note/siyuan/kernel/model" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util")
func getNotebookInfo(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
boxID := arg["notebook"].(string) if util.InvalidIDPattern(boxID, ret) { return }
box := model.Conf.Box(boxID) if nil == box { ret.Code = -1 ret.Msg = "notebook [" + boxID + "] not found" return }
boxInfo := box.GetInfo() ret.Data = map[string]interface{}{ "boxInfo": boxInfo, }}
func setNotebookIcon(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
boxID := arg["notebook"].(string) icon := arg["icon"].(string) model.SetBoxIcon(boxID, icon)}
func changeSortNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
idsArg := arg["notebooks"].([]interface{}) var ids []string for _, p := range idsArg { ids = append(ids, p.(string)) } model.ChangeBoxSort(ids)}
func renameNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return }
name := arg["name"].(string) err := model.RenameBox(notebook, name) if err != nil { ret.Code = -1 ret.Msg = err.Error() ret.Data = map[string]interface{}{"closeTimeout": 5000} return }
evt := util.NewCmdResult("renamenotebook", 0, util.PushModeBroadcast) evt.Data = map[string]interface{}{ "box": notebook, "name": name, } util.PushEvent(evt)}
func removeNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return }
if util.ReadOnly && !model.IsUserGuide(notebook) { ret.Code = -1 ret.Msg = model.Conf.Language(34) ret.Data = map[string]interface{}{"closeTimeout": 5000} return }
err := model.RemoveBox(notebook) if err != nil { ret.Code = -1 ret.Msg = err.Error() return }
evt := util.NewCmdResult("unmount", 0, util.PushModeBroadcast) evt.Data = map[string]interface{}{ "box": notebook, } evt.Callback = arg["callback"] util.PushEvent(evt)}
func createNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
name := arg["name"].(string) id, err := model.CreateBox(name) if err != nil { ret.Code = -1 ret.Msg = err.Error() return }
existed, err := model.Mount(id) if err != nil { ret.Code = -1 ret.Msg = err.Error() return }
box := model.Conf.Box(id) if nil == box { ret.Code = -1 ret.Msg = "opened notebook [" + id + "] not found" return }
ret.Data = map[string]interface{}{ "notebook": box, }
evt := util.NewCmdResult("createnotebook", 0, util.PushModeBroadcast) evt.Data = map[string]interface{}{ "box": box, "existed": existed, } util.PushEvent(evt)}
func openNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return }
isUserGuide := model.IsUserGuide(notebook) if util.ReadOnly && !isUserGuide { ret.Code = -1 ret.Msg = model.Conf.Language(34) ret.Data = map[string]interface{}{"closeTimeout": 5000} return }
if isUserGuide && util.ContainerIOS == util.Container { // iOS 端不再支持打开用户指南,请参考桌面端用户指南 // 用户指南中包含了付费相关内容,无法通过商店上架审核 // Opening the user guide is no longer supported on iOS https://github.com/siyuan-note/siyuan/issues/11492 ret.Code = -1 ret.Msg = model.Conf.Language(215) ret.Data = map[string]interface{}{"closeTimeout": 7000} return }
msgId := util.PushMsg(model.Conf.Language(45), 1000*60*15) defer util.PushClearMsg(msgId) existed, err := model.Mount(notebook) if err != nil { ret.Code = -1 ret.Msg = err.Error() return }
box := model.Conf.Box(notebook) if nil == box { ret.Code = -1 ret.Msg = "opened notebook [" + notebook + "] not found" return }
evt := util.NewCmdResult("mount", 0, util.PushModeBroadcast) evt.Data = map[string]interface{}{ "box": box, "existed": existed, } evt.Callback = arg["callback"] util.PushEvent(evt)
if isUserGuide { appArg := arg["app"] app := "" if nil != appArg { app = appArg.(string) }
go func() { var startID string i := 0 for ; i < 70; i++ { time.Sleep(100 * time.Millisecond) guideStartID := map[string]string{ "20210808180117-czj9bvb": "20200812220555-lj3enxa", "20211226090932-5lcq56f": "20211226115423-d5z1joq", "20210808180117-6v0mkxr": "20200923234011-ieuun1p", "20240530133126-axarxgx": "20240530101000-4qitucx", } startID = guideStartID[notebook] if treenode.ExistBlockTree(startID) { util.BroadcastByTypeAndApp("main", app, "openFileById", 0, "", map[string]interface{}{ "id": startID, }) break } } }() }}
func closeNotebook(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return } model.Unmount(notebook)}
func getNotebookConf(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return }
box := model.Conf.GetBox(notebook) if nil == box { ret.Code = -1 ret.Msg = "notebook [" + notebook + "] not found" return }
ret.Data = map[string]interface{}{ "box": box.ID, "name": box.Name, "conf": box.GetConf(), }}
func setNotebookConf(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret) if !ok { return }
notebook := arg["notebook"].(string) if util.InvalidIDPattern(notebook, ret) { return }
box := model.Conf.GetBox(notebook) if nil == box { ret.Code = -1 ret.Msg = "notebook [" + notebook + "] not found" return }
param, err := gulu.JSON.MarshalJSON(arg["conf"]) if err != nil { ret.Code = -1 ret.Msg = err.Error() return }
boxConf := box.GetConf() if err = gulu.JSON.UnmarshalJSON(param, boxConf); err != nil { ret.Code = -1 ret.Msg = err.Error() return }
boxConf.RefCreateSavePath = util.TrimSpaceInPath(boxConf.RefCreateSavePath) if "" != boxConf.RefCreateSavePath { if !strings.HasSuffix(boxConf.RefCreateSavePath, "/") { boxConf.RefCreateSavePath += "/" } }
boxConf.DailyNoteSavePath = util.TrimSpaceInPath(boxConf.DailyNoteSavePath) if "" != boxConf.DailyNoteSavePath { if !strings.HasPrefix(boxConf.DailyNoteSavePath, "/") { boxConf.DailyNoteSavePath = "/" + boxConf.DailyNoteSavePath } } if "/" == boxConf.DailyNoteSavePath { ret.Code = -1 ret.Msg = model.Conf.Language(49) return }
boxConf.DailyNoteTemplatePath = util.TrimSpaceInPath(boxConf.DailyNoteTemplatePath) if "" != boxConf.DailyNoteTemplatePath { if !strings.HasSuffix(boxConf.DailyNoteTemplatePath, ".md") { boxConf.DailyNoteTemplatePath += ".md" } if !strings.HasPrefix(boxConf.DailyNoteTemplatePath, "/") { boxConf.DailyNoteTemplatePath = "/" + boxConf.DailyNoteTemplatePath } }
boxConf.DocCreateSavePath = util.TrimSpaceInPath(boxConf.DocCreateSavePath)
box.SaveConf(boxConf) ret.Data = boxConf}
func lsNotebooks(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)
flashcard := false
// 兼容旧版接口,不能直接使用 util.JsonArg() arg := map[string]interface{}{} if err := c.ShouldBindJSON(&arg); err == nil { if arg["flashcard"] != nil { flashcard = arg["flashcard"].(bool) } }
var notebooks []*model.Box if flashcard { notebooks = model.GetFlashcardNotebooks() } else { var err error notebooks, err = model.ListNotebooks() if err != nil { return } }
ret.Data = map[string]interface{}{ "notebooks": notebooks, }}