分享一下150元找大神定制的Alist支持grep暴力搜索的方案

如果希望看到更漂亮的排版,可以移步我下面的博客: https://www.sharpgan.com/alist-modification-to-support-grep-brute-force-search/ # 前言 就我个人而言,不管多么吊的全文搜索,总是很不靠谱,关键时候总是掉链子,即使是买了昂贵的所谓的企业级的Elasticsearch,其提供的全文搜索功能也是很不靠谱,毕竟在维护基于es的日志搜索平台时,每天都有太多的人找我投诉搜不到想要的日志,而一去机器上用grep搜索的时候就有,具体细节我就不赘述了,所以我现在我只相信grep暴力搜索,好了不废话了,下面进入正题。 声明: 下面的代码全部基于Alist的一个老版本做的改动,这个版本是Version: v3.11.0-0-gfe416ba-dirty,如果你需要基于最新版本的Alist修改的话,应该可以举一反三。 修改完了之后参考下面的官方文档进行编译: [https://alist.nn.ci/zh/guide/install/source.html](https://alist.nn.ci/zh/guide/install/source.html) # 预览 文件变动一览: #### 后端 – 删除文件夹:internal/search/db_non_full_text 因为internal/bootstrap/data/setting.go中的key为conf.SearchIndex的options值中的database_non_full_text修改为了grep,所以这个文件夹就用不到了 – 新增文件夹:internal/search/grep 这是新的grep搜索类型,要新增一个文件夹来实现 新增文件: – internal/search/grep/search.go grep搜索的核心代码 – internal/search/grep/init.go grep搜索的init代码 修改文件: – internal/bootstrap/data/setting.go 用来把db_non_full_text逻辑替换成grep搜索逻辑 – internal/search/import.go 用来导入新的grep搜索逻辑 #### 前端 新增:无 修改文件: – src/pages/home/folder/Search.tsx 用来支持在新的标签页打开搜索结果中的html – src/pages/home/previews/index.ts 用来让html文件默认用html预览工具来打开 # 开干 玩的就是真实。 ### 后端 后端新增文件internal/search/grep/search.go文件内容如下: “`go package db import (         “bufio”         “context”         “github.com/alist-org/alist/v3/drivers/local”         “github.com/alist-org/alist/v3/internal/db”         “github.com/alist-org/alist/v3/internal/model”         “github.com/alist-org/alist/v3/internal/search/searcher”         “github.com/alist-org/alist/v3/pkg/utils”         “os/exec”         “path/filepath”         “strings” ) type Grep struct{} func (D Grep) Config() searcher.Config {         return config } func (D Grep) ListLocalStorage() []model.Storage {         storages, _, err := db.GetStorages(0, 500)         var localStorages []model.Storage         if err != nil {                 return localStorages         }         for i := range storages {                 storage := storages                 if storage.Driver == “Local” {                         localStorages = append(localStorages, storage)                 }         }         return localStorages } func (D Grep) FindRealRoot(parentFolder string) (string, string) {         if len(parentFolder) <= 0 {                 return "", ""         }         localStorages := D.ListLocalStorage()         if len(localStorages) <= 0 {                 return "", ""         }         for i := range localStorages {                 localStorage := localStorages                 // Unmarshal Addition                 addition := &local.Addition{}                 err := utils.Json.UnmarshalFromString(localStorage.Addition, addition)                 if err != nil {                         continue                 }                 if strings.Contains(parentFolder, localStorage.MountPath) {                         return localStorage.MountPath, addition.RootFolderPath                 }         }         return "", "" } func (D Grep) Search(ctx context.Context, req model.SearchReq) ([]model.SearchNode, int64, error) {         mountPath, rootFolderPath := D.FindRealRoot(req.Parent)         if len(mountPath) == 0 || len(rootFolderPath) == 0 {                 return []model.SearchNode{}, 0, nil         }         realRootFolder := strings.Replace(                 req.Parent,                 mountPath,                 rootFolderPath,                 1,         )     kw:=req.Keywords     isSpace:=strings.Contains(kw, " ")     if isSpace == true {         strSlice:=strings.Split(kw," ")         formerStr:=strSlice[0]         latterStr:=strSlice[1]         kw=formerStr+".*"+latterStr+"|"+latterStr+".*"+formerStr }         cmd := exec.Command("grep", "-R", "-l", "-i", "-E", kw, realRootFolder)         stderr, _ := cmd.StdoutPipe()         cmd.Start()         scanner := bufio.NewScanner(stderr)         scanner.Split(bufio.ScanLines)         var fileList []model.SearchNode         var limit int = 0         for scanner.Scan() {                 m := scanner.Text()                 fileName := strings.Split(m, ":")[0]                 cdir, cfile := filepath.Split(fileName)                 cfile = strings.TrimSuffix(cfile, "/")                 cdir = strings.Replace(cdir, rootFolderPath, mountPath, 1)                 if itemExists(fileList, cdir, cfile) {                         continue                 }                 fileList = append(fileList, model.SearchNode{                         Parent: cdir,                         Name:   cfile,                         IsDir:  false,                         Size:   0,                 })                 limit++                 if limit >= 100 {                         break                 }         }         cmd.Wait()         return fileList, 0, nil } func itemExists(fileList []model.SearchNode, cdir string, cfile string) bool {         for i := range fileList {                 file := fileList                 if file.Parent == cdir && file.Name == cfile {                         return true                 }         }         return false } func (D Grep) Index(ctx context.Context, node model.SearchNode) error {         return nil } func (D Grep) BatchIndex(ctx context.Context, nodes []model.SearchNode) error {         return nil } func (D Grep) Get(ctx context.Context, parent string) ([]model.SearchNode, error) {         return []model.SearchNode{}, nil } func (D Grep) Del(ctx context.Context, prefix string) error {         return nil } func (D Grep) Release(ctx context.Context) error {         return nil } func (D Grep) Clear(ctx context.Context) error {         return nil } var _ searcher.Searcher = (*Grep)(nil) “` 后端新增文件internal/search/grep/init.go文件内容如下: “`go package db import (         “github.com/alist-org/alist/v3/internal/search/searcher” ) var config = searcher.Config{         Name:       “grep”,         AutoUpdate: true, } func init() {         searcher.RegisterSearcher(config, func() (searcher.Searcher, error) {                 return &Grep{}, nil         }) } “` 后端修改文件internal/bootstrap/data/setting.go具体为: 把key为conf.SearchIndex的options值中的database_non_full_text修改为grep 后端修改文件internal/search/import.go具体为: 把db_non_full_text改为grep ### 前端 前端修改文件src/pages/home/folder/Search.tsx具体为: 在SearchResult这个函数下面的return属性中新增一个 `target=”_blank”`属性,用来支持在新的标签页打开搜索结果中的html,示例代码如下: “`typescript const SearchResult = (props: SearchNode) => {   return (     “` 前端修改文件src/pages/home/previews/index.ts具体为: 在函数getPreviews中将常量res改为变量: 从原来的 `const res: PreviewComponent[] = []`变为 `var res: PreviewComponent[] = []` 然后在// iframe previews注释上方新增如下代码,用来让html文件默认用html预览工具来打开: “`typescript var fileExt = ext(file.name).toLowerCase()   if (fileExt == “html”) {     res = res.filter(item => item.name === “HTML render”)   } “` 完整示例代码如下: “`typescript export const getPreviews = (   file: Obj & { provider: string } ): PreviewComponent[] => {   var res: PreviewComponent[] = []   // internal previews   previews.forEach((preview) => {     if (preview.provider && !preview.provider.test(file.provider)) {       return     }     if (       preview.type === file.type ||       preview.exts === “*” ||       preview.exts?.includes(ext(file.name).toLowerCase())     ) {       res.push({ name: preview.name, component: preview.component })     }   })   var fileExt = ext(file.name).toLowerCase()   if (fileExt == “html”) {     res = res.filter(item => item.name === “HTML render”)   }   // iframe previews   const iframePreviews = getIframePreviews(file.name)   iframePreviews.forEach((preview) => {     res.push({       name: preview.key,       component: generateIframePreview(preview.value),     })   })   // download page   res.push({     name: “Download”,     component: lazy(() => import(“./download”)),   })   return res } “` 下面是如何实现支持中文: 去[**https://crowdin.com/backend/download/project/alist/zh-CN.zip**](https://crowdin.com/backend/download/project/alist/zh-CN.zip)这里下载中文语言包,解压后放到前端文件夹src/lang下面,然后返回前端项目根目录执行 `node ./scripts/i18n.mjs,` 此时src/lang/zh-CN下面会生成一个叫entry.ts的文件然后重新编译前端项目即可。

请登录后发表评论

    • 头像半生书不完痴心梦0
    • 头像没再流泪0
    • 头像热心的网友0
    • 头像☆﹏浅蓝0
    • 头像你的笑,唯美了0
    • 头像趁爱不深0