[
  {
    "path": ".gitattributes",
    "content": "/public/*.html linguist-detectable=false\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: goreleaser\n\non:\n  push:\n\njobs:\n  goreleaser:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v1\n      - name: Set up Go\n        uses: actions/setup-go@v1\n        with:\n          go-version: \"1.13.x\"\n      - name: Run GoReleaser\n        uses: goreleaser/goreleaser-action@v1\n        with:\n          version: latest\n          args: release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.exe\n/go.sum\n/dark_dmzj\n/public/data.json\n/test\n"
  },
  {
    "path": ".goreleaser.yml",
    "content": "builds:\n  - env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - darwin\n      - windows\n    goarch:\n      - 386\n      - amd64\n      - arm\n      - arm64\nchecksum:\n  name_template: \"{{ .ProjectName }}_checksums.txt\"\narchives:\n  - name_template: \"{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}\"\n    format_overrides:\n      - goos: windows\n        format: zip\n    files:\n      - README.md\n      - public/**/*\n"
  },
  {
    "path": "README.md",
    "content": "# dark-dmzj\n\n方便得浏览动漫之家藏起来的漫画. [dark-dmzj.hloli.net](https://dark-dmzj.hloli.net)\n\n## usage\n1. 下载安装动漫之家手机APP.\n2. 手机浏览器打开 [https://dark-dmzj.hloli.net](https://dark-dmzj.hloli.net).\n\n![gif](https://i.imgur.com/NQdMDLo.gif)\n\n![cat](https://i.imgur.com/dtG3c3Q.jpg)\n"
  },
  {
    "path": "dark_dmzj.go",
    "content": "package main\n\nimport (\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/labstack/echo\"\n\t\"github.com/labstack/echo/middleware\"\n\t\"github.com/tidwall/gjson\"\n\t\"gopkg.in/cheggaaa/pb.v1\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"time\"\n)\n\nvar client *http.Client\nvar bar *pb.ProgressBar\nvar isDownloading bool\n\ntype dmzjBook struct {\n\tID                    uint64   `json:\"id\"`\n\tTitle                 string   `json:\"title\"`\n\tIsLong                int64    `json:\"islong\"`\n\tAuthors               []string `json:\"authors\"`\n\tTypes                 []string `json:\"types\"`\n\tStatus                []string `json:\"status\"`\n\tCover                 string   `json:\"cover\"`\n\tLastUpdateChapterName string   `json:\"last_update_chapter_name\"`\n\tLastUpdateChapterID   uint64   `json:\"last_update_chapter_id\"`\n\tLastUpdateTime        int64    `json:\"last_updatetime\"`\n}\n\nfunc init() {\n\tclient = &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tMaxIdleConnsPerHost:   256,\n\t\t\tMaxIdleConns:          256,\n\t\t\tResponseHeaderTimeout: 10 * time.Second,\n\t\t\tTLSHandshakeTimeout:   10 * time.Second,\n\t\t\tTLSNextProto:          make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),\n\t\t},\n\t\tTimeout: time.Second * 10,\n\t}\n\n\tex, err := os.Executable()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\texPath := filepath.Dir(ex)\n\tif _, err := os.Stat(filepath.Join(exPath, \"public\", \"index.html\")); !os.IsNotExist(err) {\n\t\tif err := os.Chdir(exPath); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n}\n\nfunc apiWithRetry(id int, try int) string {\n\tfor i := 0; i < try; i++ {\n\t\tdomains := []string{\"v3api.dmzj1.com/comic/comic_\"}\n\t\tres, err := client.Get(fmt.Sprintf(\"http://%s%d.json\", domains[rand.Intn(1)], id))\n\t\tresCk, errCk := client.Get(fmt.Sprintf(\"https://api.m.dmzj.com/info/%d.html\", id))\n\t\tif err == nil {\n\t\t\tdefer res.Body.Close()\n\t\t\tdefer io.Copy(ioutil.Discard, res.Body)\n\t\t}\n\t\tif errCk == nil {\n\t\t\tdefer resCk.Body.Close()\n\t\t\tdefer io.Copy(ioutil.Discard, resCk.Body)\n\t\t}\n\t\tif err == nil && res.StatusCode == 200 {\n\t\t\tbody, _ := ioutil.ReadAll(res.Body)\n\t\t\tif errCk == nil && resCk.StatusCode == 200 {\n\t\t\t\tbodyCk, _ := ioutil.ReadAll(resCk.Body)\n\t\t\t\tif len(bodyCk) > 1024 {\n\t\t\t\t\treturn \"\"\n\t\t\t\t}\n\t\t\t\treturn string(body)\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\nfunc getItem(id int, c chan<- string) {\n\tc <- apiWithRetry(id, 5)\n\tbar.Increment()\n}\n\nfunc arrayMap(vs []string, f func(string) []string) [][]string {\n\tvsm := make([][]string, len(vs))\n\tfor i, v := range vs {\n\t\tvsm[i] = f(v)\n\t}\n\treturn vsm\n}\n\nfunc downloadBooks() {\n\tif isDownloading {\n\t\treturn\n\t}\n\tisDownloading = true\n\tdefer func() { isDownloading = false }()\n\n\tMaxRoutines := 50\n\tMaxBooks := 70000\n\n\tbar = pb.New(MaxBooks - 1).Prefix(\"Updating \")\n\tbar.SetWidth(60)\n\tbar.ShowTimeLeft = true\n\tbar.ShowCounters = false\n\tbar.ShowSpeed = true\n\tbar.Start()\n\tdefer bar.FinishPrint(\"Finish!\")\n\n\tc := make(chan string, MaxBooks)\n\tjobs := make(chan int, MaxBooks)\n\tfor i := 0; i < MaxRoutines; i++ {\n\t\tgo func() {\n\t\t\tfor e := range jobs {\n\t\t\t\tgetItem(e, c)\n\t\t\t}\n\t\t}()\n\t}\n\tfor i := 1; i < MaxBooks; i++ {\n\t\tjobs <- i\n\t}\n\n\titems := []dmzjBook{}\n\tfor p := 1; p < MaxBooks; p++ {\n\t\tdat := gjson.Parse(<-c)\n\t\tif dat.Get(\"id\").Exists() {\n\t\t\ttags := arrayMap([]string{\"authors\", \"types\", \"status\"}, func(v string) []string {\n\t\t\t\ttag := []string{}\n\t\t\t\tfor _, e := range dat.Get(v).Array() {\n\t\t\t\t\ttag = append(tag, e.Get(\"tag_name\").String())\n\t\t\t\t}\n\t\t\t\treturn tag\n\t\t\t})\n\t\t\titems = append(items, dmzjBook{\n\t\t\t\tID:                    dat.Get(\"id\").Uint(),\n\t\t\t\tTitle:                 dat.Get(\"title\").String(),\n\t\t\t\tIsLong:                dat.Get(\"islong\").Int(),\n\t\t\t\tAuthors:               tags[0],\n\t\t\t\tTypes:                 tags[1],\n\t\t\t\tStatus:                tags[2],\n\t\t\t\tCover:                 dat.Get(\"cover\").String(),\n\t\t\t\tLastUpdateChapterName: dat.Get(\"chapters.0.data.0.chapter_title\").String(),\n\t\t\t\tLastUpdateChapterID:   dat.Get(\"chapters.0.data.0.chapter_id\").Uint(),\n\t\t\t\tLastUpdateTime:        dat.Get(\"last_updatetime\").Int(),\n\t\t\t})\n\t\t}\n\t}\n\n\tsort.Slice(items, func(a, b int) bool {\n\t\treturn items[a].LastUpdateTime > items[b].LastUpdateTime\n\t})\n\n\tjsonDat, _ := json.Marshal(items)\n\tioutil.WriteFile(\"public/data.json\", jsonDat, 0644)\n}\n\nfunc main() {\n\tgo func() {\n\t\ttime.Sleep(1 * time.Second)\n\t\tdownloadBooks()\n\t}()\n\n\te := echo.New()\n\te.HideBanner = true\n\te.Static(\"/\", \"public\")\n\te.Use(middleware.GzipWithConfig(middleware.GzipConfig{\n\t\tLevel: 5,\n\t}))\n\te.GET(\"/webpic/*\", func(c echo.Context) error {\n\t\treq, _ := http.NewRequest(\"GET\", fmt.Sprintf(\"http://images.dmzj.com%s\", c.Request().URL.Path), nil)\n\t\treq.Header.Set(\"Referer\", \"https://m.dmzj.com/\")\n\t\tres, err := client.Do(req)\n\t\tif err != nil {\n\t\t\treturn c.NoContent(http.StatusBadGateway)\n\t\t}\n\t\tdefer res.Body.Close()\n\t\tdata, _ := ioutil.ReadAll(res.Body)\n\t\treturn c.Blob(res.StatusCode, res.Header.Get(\"Content-Type\"), data)\n\t})\n\te.Logger.Fatal(e.Start(\":7777\"))\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/torta/dark-dmzj\n\nrequire (\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect\n\tgithub.com/fatih/color v1.7.0 // indirect\n\tgithub.com/labstack/echo v3.3.10+incompatible\n\tgithub.com/labstack/gommon v0.2.8 // indirect\n\tgithub.com/mattn/go-colorable v0.0.9 // indirect\n\tgithub.com/mattn/go-isatty v0.0.4 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.4 // indirect\n\tgithub.com/stretchr/testify v1.3.0 // indirect\n\tgithub.com/tidwall/gjson v1.1.5\n\tgithub.com/tidwall/match v1.0.1 // indirect\n\tgithub.com/valyala/bytebufferpool v1.0.0 // indirect\n\tgithub.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect\n\tgolang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 // indirect\n\tgolang.org/x/sys v0.0.0-20190130150945-aca44879d564 // indirect\n\tgopkg.in/cheggaaa/pb.v1 v1.0.27\n)\n"
  },
  {
    "path": "hotupdate.go",
    "content": "// +build !windows\n\npackage main\n\nimport (\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nfunc init() {\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, syscall.SIGUSR1)\n\tgo func() {\n\t\tfor {\n\t\t\t<-c\n\t\t\tdownloadBooks()\n\t\t}\n\t}()\n}\n"
  },
  {
    "path": "public/dmzj.css",
    "content": "body,button,dd,dl,dt,fieldset,h1,h2,h3,h4,h5,h6,hr,input,lengend,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0}body,html{height:100%}body{background:#f5f5f5;font-family:\"PingFang SC\",\"Microsoft YaHei\",\"微软雅黑\",SimSun,\"宋体\",Arial,STHeiti,\"华文黑体\",Helvetica,Tahoma,Arial sans-serif}body,button,input,select,textarea{font-size:12px}ol,ul{list-style:none}a{text-decoration:none;cursor:pointer;outline:0}a:hover{text-decoration:none}fieldset,img{border:none}button,input,select,textarea{font-size:100%}.header{height:46px;background-size:100% 2px;background-color:#fff}.header .serCh{display:none;width:100%;height:44px;background:#fff;position:absolute;left:0;top:0;z-index:5}.serChinputBox{margin-right:92px;height:10px}.searInput{-webkit-appearance:none;width:100%;float:left;height:30px;border:1px solid #cbcbcb;margin:8px 0 0 10px;border-radius:2px 0 0 2px;border-right:0;background:#f5f5f5;outline:0;font-size:15px;padding:0 5px}.searBtn{width:33px;height:28px;border:1px solid #cbcbcb;float:right;margin:8px 0 0 0;border-radius:0 2px 2px 0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAiCAMAAADmrkDzAAAAUVBMVEUAAAA1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTWDH6iCAAAAGnRSTlMA84gUz8rp4dzEPgxiWCcbBo1HRuCoSbGmIVJ8jhUAAADTSURBVDjLzZNZDsMgDEQNDVvIvrWZ+x+0UmkgTSz5t/Nlw5PMGJuyah2sUjbomlg1Hlm+ud/vBnB67ofYTdoDZr8AtYVrS9o62N9Ss8Izng/iC2o65Z3CSBeNUF3JDFa6aYUpLuDinYgO2ZFHS4xa+MMHFmK14OtHQ7NAuQiYeGJCSIFFzxM9bAoUBp4YoGRCrnK8dBZeKrgVOiZ2Xf45+fflCSrauCncUpiRyyRnoBQ6tmHo5882dBTMQ9gog+qCUD2mrRxTox5VQnj9I2JIQEx4A1Y8D2zeFlbPAAAAAElFTkSuQmCC) no-repeat center;background-size:17px 17px;background-color:#f5f5f5;border-left:0}.searClose{width:31px;height:28px;border:1px solid #cbcbcb;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATBAMAAACAfiv/AAAAIVBMVEUAAAA1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTXjvRxHAAAACnRSTlMAFNTO2BnFLii7fcpN5AAAAGdJREFUCNctzaENgDAQheGHINgGJqgiqYJgCCMgSQeoYh5mAEM6JeS/O3X5xP+0BHFH0Rb52r2ov+H8BDUpgrMEg4JBYxAeQbg6Sl195ZcrbZorbRuizRBtQ9qGgg2N04/wpNOTw/UBx1EX2JLOhUoAAAAASUVORK5CYII=) no-repeat center;background-size:10px 10px;border-radius:2px;float:right;margin:8px 10px 0 5px;background-color:#f5f5f5}.messagSjr{width:100%;position:absolute;top:46px;z-index:4;background:#fff;z-index:888}.messagSjr .keyTit li{margin:0 10px;padding:0 5px;height:40px;border-bottom:1px solid #cbcbcb;line-height:40px;font-size:14px}.UpdateList{margin-top:7px;background:#fff}.UpdateList .itemBox{height:114px;border-bottom:1px solid #cbcbcb;padding-top:10px;margin-left:10px;position:relative}.UpdateList .itemImg{width:78px;height:103px;float:left;display:block;position:relative}.UpdateList .itemImg img{border-radius:2px}.UpdateList .itemTxt{height:114px;margin-left:88px;padding-right:10px}.UpdateList .itemTxt .title{height:33px;display:block;padding-right:80px;color:#000;line-height:33px;font-size:15px;text-overflow:ellipsis;overflow:hidden}.UpdateList .itemTxt .txtItme{display:block;height:15px;line-height:15px;font-size:12px;color:#000;opacity:.9;margin:7px 0}.UpdateList .itemTxt .txtItme .pd{padding-right:5px}.UpdateList .itemTxt .txtItme .icon{float:left;display:block;width:15px;height:15px;float:left;display:block;margin-right:5px}.UpdateList .itemTxt .txtItme .icon.icon01{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAZlBMVEUAAABmvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP/m9P9twP/w+f+ByP9wwf9qvv/////L6f+x3f+/4//2+/+Y0v+V0f+JzP+84v/U7P/X7f/W7f+k1/+i1v/o0ERqAAAADXRSTlMA6pQE+VdMEMWArceByQzOeQAAAQZJREFUKM+Fk+mSgyAQhMULTTIcIqAx2eP9X3J1tUeSWOX3h5IG6bkypqjzRpSlaPK6yN6RrSBGtPJVrSDiQJWIRU4f5AWrFzrgAp3vTs9heE58f3sX379q7LpR/eC7+vcMV1Z1y9IpC3+L/xaH/X1d7x477eyLQzJ6XbXh8IqsJtBD7gnUs21g8HNDu/mGwAPWIoEmw9PLvhq1HtV8CoisJGYa+plhIqbcZRdNsE7bYKLbZQH128O5/4Iu2Fr0xPgIawjMrklBYiwCq7eoAiWEx5YWJBV1QHW2pKIkwaWyCygJCnqAkGiHQyo00yH5SSueNPL5GAB5E4l4k6mGEbwuI3hNR/AP2holij6C64EAAAAASUVORK5CYII=);background-size:100%}.UpdateList .itemTxt .txtItme .icon.icon02{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAeFBMVEUAAABmvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP/////w+P/6/f+LzP96xf+y3v/r9/+Rz/9pvv+AyP91w//m9P/a7/+94v+34P/y+v/R6//G5v+W0v/2+//f8f/K6P8CnX0IAAAAEXRSTlMA6QSS+VcQlUyA68Wtx8aBTV5wTfMAAAEBSURBVCjPhdNtc4MgDAfwABZF+7AUta5d1da2+/7fcDMFQll3/l+Id78DckcCIbJQW5FlYqsKCWm0ERhSGv2qK0KOWEUoc/yTXAZd45usvSt8m9zdi/+E7tdc1dd031Pqkeqb6zes58fpSH+3mhYDIAXrdUbKnr5CQpHop7U3z1iA8tp9017bNDawggopbTfNmnAFwulAa3K4gOypI8Y5Os6efO7xJe3dMx1+SXi6+sMrurA+xDpcTr40heypooICUx+sV/wAWSY+sgrJT9L8OmmLPsY9KPshUqG5Hcj7vmNF14558O4Rab7QiguNvDQGHL0rGcudZuER3MwjuIlH8AcPlDETmzg0tgAAAABJRU5ErkJggg==);background-size:100%}.UpdateList .itemTxt .txtItme .icon.icon03{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAY1BMVEUAAABmvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9mvP9wwf/p9v/a7/+Y0v/+///N6f+k1/+Mzf/4/P/s9/+54P+d1P+Ax//v+f/n9P/X7v+/4/98xv/qsHowAAAADnRSTlMA6ZT5V0wQgOvErcfGgcWY6r4AAAD0SURBVCjPhZNZFoMgDEXFuYNRBBVn97/KCqFGsae8D3P0SniQJCAl4ZtFEXuHSXBTmjE4lGfplcYGklh8piHcFBJ9wg893bW1VF03y/q6Praw4s1YlmPDK/tDbDyjq75qwaqtevSn/WdIeUnblhx5tmOGmTUlPpv8bL8r8z61cFE7mZCg7WEBK27jMqD5hw6y+WJhYyP184Fbq83Fm8LNIx06cDF+iiw+fE9CCK69I8bk8wiORkzuWgPHGh2MRAfzXUuQ/7lUT0mooOu5oCsV1NMO1EyDVEIoOVAzeVrR08j+MUClRU4wL1IiNIIvPYKv8wh+AJ7oKJ0DK8hKAAAAAElFTkSuQmCC);background-size:100%}.UpdateList .coll{width:50px;height:15px;color:#000;overflow:hidden;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAABOCAMAAABSQ2ssAAAA3lBMVEUAAAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/tAD/////+/D/6K3/wCf/uxf/uA7/tgX//vn/vyP//PX/+/L/6rX/2Hj/vR3/+OX/8dD/67r/02n/zlX/+er/9uH/wzL/wi7/uhH/3In/yUj/5qn/46D/0F3/4Zn/24P/x0D/xTkRj11eAAAAKHRSTlMAUhHv1+zcuLP7+fyPSh0CVcWEP1nz6LyTcWNhKAHTubWmo9+XbifPferQzAAAAptJREFUWMPtmNd22kAQhleo0Yxp7gVsJ86MBAjRe7Od8v4vFAOHE82gEEBzwUW+y9GZj7MsK2Z/FUrsvlC8yX95snOGpesJ+ORCv7S+5eLP1/mv2cJ9TO1DTEvblp6Ef5LULTut7ZKea/EEHEQirp2rcDQDjsDQwlwZG47EzijOmQlHY54x2W0KIpC6I7I7iEhQd5aCiKT+LDajQ2T0zVY8XIEAVw9rWxZEyK5PgAEiGKtToYEQ2tIWByHiy7dGAoRIxMhCBZaaBjHSStkghq2UxUq/3sZ1DDL6PlnWJ+8jUq6P3ytAsZQygTBdq2hjG6AdUm90gGAqlQTCHN/8Gqn48zouFlif095ZpY9tICSVAkoffwKnjf1lJ2eILqvEuK2LHeBU0XGwCpwp9ljlldh810H0YAv8BEI+BB3XhwCFoK3isLbdNm9ZdoIbmw3aXGxV0Nll4+VOi3x3N0Gbg9XqIbYG1qrYDBTyijTB7BCbgzUgD66ZrRbJ9ixqizObh41DdgGoLae2nkawPYraXkRtl6I2XdR2IWqD/7YT2AX9hH+9Lyd86mXfSGVR25Oo7VrUlt+2efv/19eZ7YbbHJzta5uhw2xFbuthu1Pbx1bzf2CP2QrcNkBKt/XhrW3eh9tFypDZXrkNhv1xkwmHq06mcsatBTBbTCWJjeP5g96mvzfwPeAgkknVZE+2GTRWI/MAOLzHJBP+ZhzlTEaIowmEQSYuSymbTIPhummjOYUw6DRoK5Xmk+r+8Ek1TW9tFbeJB9F0AzLQZG+Uordd2Zu4bEogmWAUZdMV0eRHOpXacAsRuRVN80STRsEUtJRRIWSPS2izculxWTvfnWyXDHOfZNs0StvJ9u7UvZwzLFNPblL3x3XqXvxr6v4bzaRYyhqP0ToAAAAASUVORK5CYII=) no-repeat 6px 0;background-size:39px;float:right;padding-top:45px;line-height:18px;font-size:12px;opacity:.9;text-align:center;position:absolute;top:37px;right:12px}.UpdateList .coll:hover{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAABOCAMAAAC5dNAvAAAA2FBMVEUAAAD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/ogD/////+vH/pw//4a3/sSf/pAX//vz/9eL/tDD/+/P/rR//5LX/rBn/+e//9+j/5rr/yWn/wVX/qxf/04b/zXf/ryT//Pf/3J3/vEj/79H/68n/4Kn/0Hz/xF3/uDz/79SHA+hiAAAAJ3RSTlMAUvy46u7Us/L43dliV0pAKB0SApUQj4Nx4cfDu6NVppGFblvepw6iItqwAAACr0lEQVRYw82Y6XKiUBBGm01Egxr3mMRk1m5AUNzX7Mm8/xuNZSo13JbJuPRUef7Rt/pYeIG6/UE6tVLxW/NL9YfRyucsS8c1WcvMZS7t69vGV7dY+gk7UdbqRt5y8J84Vt6oa2X4hIpm67gXuq1V4C9oGTyAjAZpnBt4IMY5bFEw8WDMAjDOdDwC/YzZ8EgUX0HHI9ELiV2w8GisP/txhQJcfdjaKEIbNlQyKEL+/f3QUAhto7NRCBvWlHUUQi+zexW421sUow4ABophAECO1d6euxElGd/3cE3vfqyU77r3HVTJAYCJCr2ItoiWiMuUetxHBRMAHFRY0PPKVyr9RUQPDxQt1Ga/M6ElKjgANVSZ0BtyXmgyoRfkzChglRqUWGVMQ+TMyfNSyj16ZJUSFDHBKvCIQtyC1mDKr5AXrDBBEdzEVWfE+j7XhbRmlNxeF5qJq4AGHfI+0/Fyf6D8f01oJK48Gs730d2RP6Q4UWhAVelCfx+dRz4qC1W4kdRdgyGps6Gl6kK622crUNVdQmZr+QhdBi4kdReyOhNMSV0WsiesQ8CT1mVPWJcVflCkH+Pvoi+Z9CfgUlLXAltSZ8C1pO4GqpK6KjQkdQ1osuWIwt1PARHTNcFlOo/8XXU+jZjOhSLT/aJl399F568W9MR0RSgx3ZRUuoPX8F0XvgZdUpkxXQlqTIezSddjxtmmlbm87uABma4G4Cg6TtifPn4InqZ9tk2sxwEAky1tM41pTTxFDu8x1UHg48TK6Y2Jxj1MY06xOggYynFxnu6L43TbUDkuGuoQ1RnRXvDDbJ2NeJ3Ao73wgoQNNeEBVHo8lh/eK3k8Bh4tgIsiuLKxjHBoJBtpyQZusnGgcFgpH6Vy2ocFvW3hGPr/h+TpEf6N0crkTMtJRvjVTYRfg1R+AyqRRSgxTWieAAAAAElFTkSuQmCC) no-repeat;background-size:39px}"
  },
  {
    "path": "public/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0,user-scalable=no\"/>\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"/>\n  <meta name=\"referrer\" content=\"no-referrer\"/>\n  <meta name=\"format-detection\" content=\"telephone=no\"/>\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"white\">\n  <meta name=\"wap-font-scale\" content=\"no\">\n  <title>Dark Dmzj</title>\n  <link rel=\"stylesheet\" href=\"dmzj.css\" />\n  <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.2.2/gh-fork-ribbon.min.css\" />\n  <style type=\"text/css\">\n    body, .UpdateList {\n      background: rgb(30, 30, 30);\n    }\n    .UpdateList .itemBox {\n      border-bottom: 1px solid rgb(90, 90, 90);\n    }\n    .UpdateList .itemTxt .title, .UpdateList .itemTxt .txtItme, .UpdateList .coll {\n      color: #fff;\n    }\n    .header {\n      background: transparent;\n    }\n    .header .serCh {\n      background: rgb(60, 60, 60);\n    }\n    .searInput, .searClose, .searBtn {\n      border: 1px solid rgb(129, 129, 129);\n      background-color: rgb(110, 110, 110);\n      color: #fff;\n    }\n    .github-fork-ribbon.right-bottom:before {\n        background-color: #333;\n    }\n    .messagSjr {\n      background: rgb(60, 60, 60);\n      color: #fff;\n      top: 44px;\n      display: none;\n    }\n    @media (min-width: 1281px) {\n      .messagSjr {\n        display: block;\n      }\n      .header {\n        height: 146px;\n      }\n    }\n  </style>\n  <script src=\"https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/vanilla-lazyload@8.17.0/dist/lazyload.min.js\"></script>\n  <script src=\"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js\"></script>\n  <script src=\"https://unpkg.com/unfetch/polyfill\"></script>\n</head>\n<body>\n  <div id=\"app\">\n    <div class=\"header\">\n      <div class=\"serCh\" id=\"serCh\" style=\"display: block;\">\n        <div id=\"searchForm\" action=\"\">\n          <a href=\"javascript:void(0);\" @click=\"searchClear\" class=\"searClose\"></a>\n          <a href=\"javascript:void(0);\" @click=\"searchAction\" class=\"searBtn\"></a>\n          <div class=\"serChinputBox\"><input @keyup.enter=\"searchAction\" v-model.trim=\"keyword\" type=\"search\" class=\"searInput\" placeholder=\"漫画名或作者\" id=\"searInput\"></div>\n        </div>\n      </div>\n      <div class=\"messagSjr\" style=\"padding-bottom: 20px;\">\n        <ul class=\"keyTit\" id=\"messagelist\">\n          <li>1. 下载安装动漫之家手机APP.</li>\n          <li>2. 手机浏览器打开 https://dark-dmzj.hloli.net</li>\n        </ul>\n      </div>\n    </div>\n    <div class=\"UpdateList\">\n      <div class=\"ClientVer\" style=\"color: #fff; font-size: 14px; padding: 10px; text-align: right;\">\n        <input type=\"radio\" id=\"cver1\" v-model=\"clientVer\" value=\"1\" />\n        <label for=\"cver1\">动漫之家</label>\n        /\n        <input type=\"radio\" id=\"cver2\" v-model=\"clientVer\" value=\"2\" />\n        <label for=\"cver2\">动漫之家社区</label>\n      </div>\n      <div class=\"itemBox\" v-for=\"item in items\" :key=\"item.id\">\n        <div class=\"itemImg\">\n          <a :href=\"formatUrl(item)\" title=\"\"><img :class=\"'lazy'\" :data-src=\"item.cover.replace(/https?:\\/\\/images\\.dmzj\\.com/, '')\" width=\"100%\"/></a>\n        </div>\n        <div class=\"itemTxt\">\n          <a :href=\"formatUrl(item)\" class=\"title\">{{ item.title }}</a>\n          <p class=\"txtItme\">{{ item.authors.join('/') }}<span class=\"icon icon01\"></span></p>\n          <p class=\"txtItme\">\n            <span class=\"icon icon02\"></span>\n            <span class=\"pd\" v-for=\"type in item.types\">{{ type }}</span>\n          </p>\n          <p class=\"txtItme\">\n            <span class=\"icon icon03\"></span>\n            <span class=\"date\">{{ moment(item.last_updatetime * 1000).format('YYYY-MM-DD H:mm') }}</span>\n          </p>\n        </div>\n        <a :href=\"formatUrl(item)\" class=\"coll\">{{ item.last_update_chapter_name }}</a>\n      </div>\n    </div>\n  </div>\n  <script>\n    (function () {\n      function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n      var lz = new LazyLoad({ elements_selector: \".lazy\" });\n      var data = [[], []];\n      var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);\n      new Vue({\n        el: '#app',\n        data: {\n          keyword: \"\",\n          items: [],\n          clientVer: (window.localStorage && localStorage.getItem(\"cver\")) || 2,\n        },\n        watch: {\n          clientVer: function(val, oldVal) {\n            window.localStorage && localStorage.setItem(\"cver\", val);\n          }\n        },\n        methods: {\n          formatUrl: function formatUrl(item) {\n            return ~~this.clientVer === 2\n                ? iOS\n                    ? \"dmzjsq://dmzj.com/comicReader?comicId=\" +\n                      item.id +\n                      \"&chapterId=\" +\n                      item.last_update_chapter_id\n                    : \"dmzj1://dmzj1.com/comic?id=\" + item.id\n                : iOS\n                ? \"dmzj://objectIntro/comic?objId=\" + item.id\n                : \"dmzj://dmzj.com/comic?id=\" + item.id;\n          },\n          loadMore: function loadMore() {\n            var _items;\n\n            (_items = this.items).push.apply(_items, _toConsumableArray(data[0].splice(0, 20)));\n            Vue.nextTick(function () {\n              return lz.update();\n            });\n          },\n          searchClear: function searchClear() {\n            var _this = this;\n\n            this.keyword = '';\n            Vue.nextTick(function () {\n              return _this.searchAction();\n            });\n          },\n          searchAction: function searchAction() {\n            var keyword = this.keyword.toLowerCase();\n            if (this.keyword.length === 0) {\n              data[0] = data[1].slice(0);\n            } else {\n              data[0] = data[1].filter(function (e) {\n                return e.title.toLowerCase().indexOf(keyword) > -1 || e.authors.join().toLowerCase().indexOf(keyword) > -1;\n              });\n            }\n            this.items = [];\n            this.loadMore();\n          }\n        },\n        created: function created() {\n          var _this2 = this;\n\n          fetch('data.json').then(function (e) {\n            return e.json();\n          }).then(function (e) {\n            return data = [e, e.slice(0)];\n          }).then(function () {\n            window.onscroll = function () {\n              if (window.innerHeight + (window.pageYOffset || document.documentElement.scrollTop) > _this2.$el.offsetHeight - 100) {\n                _this2.loadMore();\n              }\n            };\n          }).then(this.loadMore);\n        }\n      });\n    })();\n  </script>\n  <a class=\"github-fork-ribbon right-bottom fixed\" href=\"https://github.com/torta/dark-dmzj\" data-ribbon=\"Fork me on GitHub\" title=\"Fork me on GitHub\">Fork me on GitHub</a>\n</body>\n</html>\n"
  }
]