diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml
index d80afae..75ae267 100644
--- a/.github/workflows/Release.yml
+++ b/.github/workflows/Release.yml
@@ -28,11 +28,18 @@ jobs:
with:
repository: ${{ github.event.inputs.repo }}
ref: 'master'
- - name: Checkout submodules
- run: git submodule update --init --recursive
- uses: actions/setup-go@v2
with:
go-version: ${{ env.go_version }}
+ - name: Cache go modules
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~/.cache/go-build
+ ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
- name: Check release
run: |
cd ci
@@ -75,6 +82,39 @@ jobs:
with:
go-version: ${{ env.go_version }}
+ - name: Cache go modules (Linux/Android)
+ if: matrix.config.target == 'android-arm32' || matrix.config.target == 'android-arm64' || matrix.config.target == 'android-x86_64' || matrix.config.target == 'linux'
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~/.cache/go-build
+ ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
+
+ - name: Cache go modules (macOS/ios)
+ if: matrix.config.target == 'macos' || matrix.config.target == 'ios'
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~/Library/Caches/go-build
+ ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
+
+ - name: Cache go modules (Windows)
+ if: matrix.config.target == 'windows'
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~\AppData\Local\go-build
+ ~\go\pkg\mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
+
- id: check_asset
name: Check asset
run: |
@@ -88,6 +128,20 @@ jobs:
channel: ${{ env.flutter_channel }}
flutter-version: ${{ env.flutter_version }}
+ - name: Check core
+ uses: actions/checkout@v3
+ with:
+ repository: 'niuhuan/pikapika-go-core'
+ token: ${{ secrets.GH_TOKEN }}
+ path: 'go'
+
+ - name: Cache Flutter dependencies (Linux/Android)
+ if: steps.check_asset.outputs.skip_build != 'true' && ( matrix.config.target == 'android-arm32' || matrix.config.target == 'android-arm64' || matrix.config.target == 'android-x86_64' || matrix.config.target == 'linux' )
+ uses: actions/cache@v3
+ with:
+ path: /opt/hostedtoolcache/flutter
+ key: ${{ runner.os }}-flutter
+
- name: Setup java (Android)
if: steps.check_asset.outputs.skip_build != 'true' && ( matrix.config.target == 'android-arm32' || matrix.config.target == 'android-arm64' || matrix.config.target == 'android-x86_64' )
uses: actions/setup-java@v3
diff --git a/go/.gitignore b/go/.gitignore
deleted file mode 100644
index 596bcc6..0000000
--- a/go/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-build
-.last_goflutter_check
-.last_go-flutter_check
-.last_go-flutter_check
diff --git a/go/assets/icon.png b/go/assets/icon.png
deleted file mode 100644
index f14bdd1..0000000
Binary files a/go/assets/icon.png and /dev/null differ
diff --git a/go/cmd/init.go b/go/cmd/init.go
deleted file mode 100644
index 97b27f8..0000000
--- a/go/cmd/init.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package main
-
-import (
- "errors"
- "os"
- "os/exec"
- "path"
- path2 "path"
- "path/filepath"
- "pikapika/pikapika/config"
- "runtime"
- "strings"
-)
-
-// 根据不通系统初始化数据的保存路径
-func init() {
- applicationDir, err := os.UserHomeDir()
- if err != nil {
- panic(err)
- }
- switch runtime.GOOS {
- case "windows":
- // applicationDir = path.Join(applicationDir, "AppData", "Roaming")
- file, err := exec.LookPath(os.Args[0])
- if err != nil {
- panic(err)
- }
- path, err := filepath.Abs(file)
- if err != nil {
- panic(err)
- }
- i := strings.LastIndex(path, "/")
- if i < 0 {
- i = strings.LastIndex(path, "\\")
- }
- if i < 0 {
- panic(errors.New(" can't find \"/\" or \"\\\""))
- }
- applicationDir = path2.Join(path[0:i+1], "data")
- case "darwin":
- applicationDir = path.Join(applicationDir, "Library", "Application Support", "pikapika")
- case "linux":
- applicationDir = path.Join(applicationDir, ".pikapika")
- default:
- panic(errors.New("not supported system"))
- }
- if _, err = os.Stat(applicationDir); err != nil {
- if os.IsNotExist(err) {
- err = os.MkdirAll(applicationDir, os.FileMode(0700))
- if err != nil {
- panic(err)
- }
- } else {
- panic(err)
- }
- }
- config.InitApplication(applicationDir)
-}
diff --git a/go/cmd/main.go b/go/cmd/main.go
deleted file mode 100644
index 8ac25b5..0000000
--- a/go/cmd/main.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package main
-
-import (
- "fmt"
- "github.com/go-flutter-desktop/go-flutter"
- "github.com/pkg/errors"
- "image"
- _ "image/gif"
- _ "image/jpeg"
- _ "image/png"
- "os"
- "path/filepath"
- "pikapika/pikapika/database/properties"
- "strconv"
- "strings"
-)
-
-// vmArguments may be set by hover at compile-time
-var vmArguments string
-
-func main() {
- // DO NOT EDIT, add options in options.go
- mainOptions := []flutter.Option{
- flutter.OptionVMArguments(strings.Split(vmArguments, ";")),
- flutter.WindowIcon(iconProvider),
- }
- // 窗口初始化大小的处理
- widthStr, _ := properties.LoadProperty("window_width", "600")
- heightStr, _ := properties.LoadProperty("window_height", "900")
- width, _ := strconv.Atoi(widthStr)
- height, _ := strconv.Atoi(heightStr)
- if width <= 0 {
- width = 600
- }
- if height <= 0 {
- height = 900
- }
- var runOptions []flutter.Option
- runOptions = append(runOptions, flutter.WindowInitialDimensions(width, height))
- fullScreen, _ := properties.LoadBoolProperty("full_screen", false)
- if fullScreen {
- runOptions = append(runOptions, flutter.WindowMode(flutter.WindowModeMaximize))
- }
- // ------
- err := flutter.Run(append(append(runOptions, options...), mainOptions...)...)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-}
-
-func iconProvider() ([]image.Image, error) {
- execPath, err := os.Executable()
- if err != nil {
- return nil, errors.Wrap(err, "failed to resolve executable path")
- }
- execPath, err = filepath.EvalSymlinks(execPath)
- if err != nil {
- return nil, errors.Wrap(err, "failed to eval symlinks for executable path")
- }
- imgFile, err := os.Open(filepath.Join(filepath.Dir(execPath), "assets", "icon.png"))
- if err != nil {
- return nil, errors.Wrap(err, "failed to open assets/icon.png")
- }
- img, _, err := image.Decode(imgFile)
- if err != nil {
- return nil, errors.Wrap(err, "failed to decode image")
- }
- return []image.Image{img}, nil
-}
diff --git a/go/cmd/options.go b/go/cmd/options.go
deleted file mode 100644
index 1c605ef..0000000
--- a/go/cmd/options.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package main
-
-import (
- "errors"
- "github.com/go-flutter-desktop/go-flutter"
- "github.com/go-flutter-desktop/go-flutter/plugin"
- "github.com/go-flutter-desktop/plugins/url_launcher"
- "github.com/go-gl/glfw/v3.3/glfw"
- "github.com/miguelpruivo/flutter_file_picker/go"
- "pikapika/pikapika"
- "pikapika/pikapika/database/properties"
- "strconv"
- "sync"
-)
-
-var options = []flutter.Option{
- flutter.AddPlugin(&PikapikaPlugin{}),
- flutter.AddPlugin(&file_picker.FilePickerPlugin{}),
- flutter.AddPlugin(&url_launcher.UrlLauncherPlugin{}),
-}
-
-var eventMutex = sync.Mutex{}
-var eventSink *plugin.EventSink
-
-type EventHandler struct {
-}
-
-func (s *EventHandler) OnListen(arguments interface{}, sink *plugin.EventSink) {
- eventMutex.Lock()
- defer eventMutex.Unlock()
- eventSink = sink
-}
-
-func (s *EventHandler) OnCancel(arguments interface{}) {
- eventMutex.Lock()
- defer eventMutex.Unlock()
- eventSink = nil
-}
-
-const channelName = "method"
-
-type PikapikaPlugin struct {
-}
-
-func (p *PikapikaPlugin) InitPlugin(messenger plugin.BinaryMessenger) error {
-
- channel := plugin.NewMethodChannel(messenger, channelName, plugin.StandardMethodCodec{})
-
- channel.HandleFunc("flatInvoke", func(arguments interface{}) (interface{}, error) {
- if argumentsMap, ok := arguments.(map[interface{}]interface{}); ok {
- if method, ok := argumentsMap["method"].(string); ok {
- if params, ok := argumentsMap["params"].(string); ok {
- return pikapika.FlatInvoke(method, params)
- }
- }
- }
- return nil, errors.New("params error")
- })
-
- exporting := plugin.NewEventChannel(messenger, "flatEvent", plugin.StandardMethodCodec{})
- exporting.Handle(&EventHandler{})
-
- pikapika.EventNotify = func(message string) {
- eventMutex.Lock()
- defer eventMutex.Unlock()
- sink := eventSink
- if sink != nil {
- sink.Success(message)
- }
- }
-
- return nil // no error
-}
-
-func (p *PikapikaPlugin) InitPluginGLFW(window *glfw.Window) error {
- window.SetSizeCallback(func(w *glfw.Window, width int, height int) {
- go func() {
- properties.SaveProperty("window_width", strconv.Itoa(width))
- properties.SaveProperty("window_height", strconv.Itoa(height))
- }()
- })
- window.SetMaximizeCallback(func(w *glfw.Window, iconified bool) {
- go func() {
- properties.SaveProperty("full_screen", strconv.FormatBool(iconified))
- }()
- })
- return nil
-}
diff --git a/go/go.mod b/go/go.mod
deleted file mode 100644
index e2a7248..0000000
--- a/go/go.mod
+++ /dev/null
@@ -1,21 +0,0 @@
-module pikapika
-
-go 1.16
-
-require (
- github.com/PuerkitoBio/goquery v1.7.1
- github.com/go-flutter-desktop/go-flutter v0.43.0
- github.com/go-flutter-desktop/plugins/url_launcher v0.1.2
- github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265
- github.com/miguelpruivo/flutter_file_picker/go v0.0.0-20210622152105-9f0a811028a0
- github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/niuhuan/pica-go v0.0.0-20220415110443-b5c4a97b0103
- github.com/pkg/errors v0.9.1
- golang.org/x/image v0.0.0-20190802002840-cff245a6509b
- golang.org/x/mobile v0.0.0-20220414153400-ce6a79cf6a13 // indirect
- golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
- golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect
- golang.org/x/text v0.3.7 // indirect
- gorm.io/driver/sqlite v1.1.4
- gorm.io/gorm v1.21.12
-)
diff --git a/go/go.sum b/go/go.sum
deleted file mode 100644
index 9dbc2de..0000000
--- a/go/go.sum
+++ /dev/null
@@ -1,127 +0,0 @@
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/PuerkitoBio/goquery v1.7.1 h1:oE+T06D+1T7LNrn91B4aERsRIeCLJ/oPSa6xB9FPnz4=
-github.com/PuerkitoBio/goquery v1.7.1/go.mod h1:XY0pP4kfraEmmV1O7Uf6XyjoslwsneBbgeDjLYuN8xY=
-github.com/Xuanwo/go-locale v1.0.0 h1:oqC32Kyiu2XZq+fxtwEg0mWiv9WyDhyHu+sT5cDkgME=
-github.com/Xuanwo/go-locale v1.0.0/go.mod h1:kB9tcLfr4Sp+ByIE9SE7vbUkXkGQqel2XH3EHpL0haA=
-github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE=
-github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/gen2brain/dlgs v0.0.0-20190708095831-3854608588f7 h1:qA8Mdjwrlv/r/aMqArqO0IMHUiy6ApdW4+8DtKr7PvA=
-github.com/gen2brain/dlgs v0.0.0-20190708095831-3854608588f7/go.mod h1:/eFcjDXaU2THSOOqLxOPETIbHETnamk8FA/hMjhg/gU=
-github.com/go-flutter-desktop/go-flutter v0.30.0/go.mod h1:NCryd/AqiRbYSd8pMzQldYkgH1tZIFGt2ToUghZcWGA=
-github.com/go-flutter-desktop/go-flutter v0.43.0 h1:7tdUbGKmHwdsUnBfC/h7zAO3T67cAkKSCWi9ZDFg25A=
-github.com/go-flutter-desktop/go-flutter v0.43.0/go.mod h1:GSCn6XOpB0cnYlK9/BdSwxi99t5YD1XEk0v4agI7SS4=
-github.com/go-flutter-desktop/plugins/url_launcher v0.1.2 h1:oFiIJjotMQvF8rfKWVJrf+1/JgTXShEIsibkiXrQnUw=
-github.com/go-flutter-desktop/plugins/url_launcher v0.1.2/go.mod h1:GYgRDaLDAJRYvaASQk8HEmI8YJurbZGW5VVDIMxwzBU=
-github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
-github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265 h1:BcbKYUZo/TKPsiSh7LymK3p+TNAJJW3OfGO/21sBbiA=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gopherjs/gopherjs v0.0.0-20190915194858-d3ddacdb130f h1:TyqzGm2z1h3AGhjOoRYyeLcW4WlW81MDQkWa+rx/000=
-github.com/gopherjs/gopherjs v0.0.0-20190915194858-d3ddacdb130f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
-github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
-github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
-github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
-github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
-github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
-github.com/miguelpruivo/flutter_file_picker/go v0.0.0-20210622152105-9f0a811028a0 h1:hXl9AMW20Php3xWlWZr2Acw50tqeblLgtLfLoRCACmA=
-github.com/miguelpruivo/flutter_file_picker/go v0.0.0-20210622152105-9f0a811028a0/go.mod h1:csuW+TFyYKtiUwNvcvhcpyX4quPI7Pvv0SUogdqCW4I=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/niuhuan/pica-go v0.0.0-20220224154849-76bf750f8c4d h1:f3V6V1Y+5j/AvhsIGA6aQ/K2Ez1AeYbuCG9uI4fGC6M=
-github.com/niuhuan/pica-go v0.0.0-20220224154849-76bf750f8c4d/go.mod h1:r76zBgH9AYkv0ptyEVoPUIdt33sT0Ts7xgcg742OZtw=
-github.com/niuhuan/pica-go v0.0.0-20220415110443-b5c4a97b0103 h1:Qc40/rqbtY0fXAlPEzlfBdQk7wIHTjcTmejmBvdKeco=
-github.com/niuhuan/pica-go v0.0.0-20220415110443-b5c4a97b0103/go.mod h1:r76zBgH9AYkv0ptyEVoPUIdt33sT0Ts7xgcg742OZtw=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20220224134551-8a0a1e50732f h1:G/wQ/Mbs60nXhRM80J4DOzy7FEIZjNprzOneArSgOl0=
-golang.org/x/mobile v0.0.0-20220224134551-8a0a1e50732f/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
-golang.org/x/mobile v0.0.0-20220307220422-55113b94f09c h1:9J0m/JcA5YXYbamDhF5I3T7cJnR7V75OCLnMCPb5gl4=
-golang.org/x/mobile v0.0.0-20220307220422-55113b94f09c/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
-golang.org/x/mobile v0.0.0-20220325161704-447654d348e3 h1:ZDL7hDvJEQEcHVkoZawKmRUgbqn1pOIzb8EinBh5csU=
-golang.org/x/mobile v0.0.0-20220325161704-447654d348e3/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
-golang.org/x/mobile v0.0.0-20220414153400-ce6a79cf6a13 h1:C4eR3yV9J3RkP8WKkcQzpcPyr/foOcUtxW72DvJEOlI=
-golang.org/x/mobile v0.0.0-20220414153400-ce6a79cf6a13/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
-golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200802091954-4b90ce9b60b3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
-golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098 h1:YuekqPskqwCCPM79F1X5Dhv4ezTCj+Ki1oNwiafxkA0=
-golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
-gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
-gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
-gorm.io/gorm v1.21.12 h1:3fQM0Eiz7jcJEhPggHEpoYnsGZqynMzverL77DV40RM=
-gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
diff --git a/go/hover.yaml b/go/hover.yaml
deleted file mode 100644
index 81c398e..0000000
--- a/go/hover.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-#application-name: "pikapi" # Uncomment to modify this value.
-#executable-name: "pikapi" # Uncomment to modify this value. Only lowercase a-z, numbers, underscores and no spaces
-#package-name: "pikapi" # Uncomment to modify this value. Only lowercase a-z, numbers and no underscores or spaces
-organization-name: "niuhuan"
-license: "" # MANDATORY: Fill in your SPDX license name: https://spdx.org/licenses
-target: lib/main_desktop.dart
-# opengl: "none" # Uncomment this line if you have trouble with your OpenGL driver (https://github.com/go-flutter-desktop/go-flutter/issues/272)
-docker: false
-engine-version: "" # change to a engine version commit
diff --git a/go/mobile/lib/.keep b/go/mobile/lib/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/go/mobile/mobile.go b/go/mobile/mobile.go
deleted file mode 100644
index e357c9f..0000000
--- a/go/mobile/mobile.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package mobile
-
-import (
- "pikapika/pikapika"
- "pikapika/pikapika/config"
-)
-
-func InitApplication(application string) {
- config.InitApplication(application)
-}
-
-func FlatInvoke(method string, params string) (string, error) {
- return pikapika.FlatInvoke(method, params)
-}
-
-func EventNotify(notify EventNotifyHandler) {
- pikapika.EventNotify = notify.OnNotify
-}
-
-type EventNotifyHandler interface {
- OnNotify(message string)
-}
diff --git a/go/packaging/darwin-bundle/{{.applicationName}} {{.version}}.app/Contents/Info.plist.tmpl b/go/packaging/darwin-bundle/{{.applicationName}} {{.version}}.app/Contents/Info.plist.tmpl
deleted file mode 100644
index e49ccf2..0000000
--- a/go/packaging/darwin-bundle/{{.applicationName}} {{.version}}.app/Contents/Info.plist.tmpl
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- {{.executableName}}
- CFBundleGetInfoString
- {{.description}}
- CFBundleIconFile
- icon.icns
- NSHighResolutionCapable
-
- CFBundleIdentifier
- {{.organizationName}}.{{.packageName}}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- {{.version}}
- CFBundleName
- {{.applicationName}}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- {{.version}}
- CFBundleSignature
- {{.organizationName}}.{{.packageName}}
- CFBundleVersion
- {{.version}}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
-
- NSPrincipalClass
- NSApplication
-
-
diff --git a/go/packaging/linux-appimage/AppRun.tmpl b/go/packaging/linux-appimage/AppRun.tmpl
deleted file mode 100644
index 9272c3d..0000000
--- a/go/packaging/linux-appimage/AppRun.tmpl
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-cd "$(dirname "$0")"
-exec ./build/{{.executableName}}
diff --git a/go/packaging/linux-appimage/{{.packageName}}.desktop.tmpl b/go/packaging/linux-appimage/{{.packageName}}.desktop.tmpl
deleted file mode 100644
index cd17a38..0000000
--- a/go/packaging/linux-appimage/{{.packageName}}.desktop.tmpl
+++ /dev/null
@@ -1,9 +0,0 @@
-[Desktop Entry]
-Version=1.0
-Type=Application
-Terminal=false
-Categories=
-Comment={{.description}}
-Name={{.applicationName}}
-Icon={{.iconPath}}
-Exec={{.executablePath}}
diff --git a/go/pikapika/client.go b/go/pikapika/client.go
deleted file mode 100644
index 681520e..0000000
--- a/go/pikapika/client.go
+++ /dev/null
@@ -1,617 +0,0 @@
-// 透传Client的功能并增加缓存
-
-package pikapika
-
-import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- source "github.com/niuhuan/pica-go"
- "golang.org/x/net/proxy"
- "net"
- "net/http"
- "net/url"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/database/network_cache"
- "pikapika/pikapika/database/properties"
- "regexp"
- "time"
-)
-
-import (
- "context"
- "strconv"
- "strings"
-)
-
-func InitClient() {
- client.Timeout = time.Second * 60
- switchAddress, _ = properties.LoadIntProperty("switchAddress", 1)
- imageSwitchAddress, _ = properties.LoadIntProperty("imageSwitchAddress", 1)
- proxy, _ := properties.LoadProxy()
- changeProxyUrl(proxy)
-}
-
-var client = source.Client{}
-var dialer = &net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
-}
-
-// SwitchAddress
-var switchAddresses = map[int]string{
- 1: "172.67.7.24:443",
- 2: "104.20.180.50:443",
- 3: "172.67.208.169:443",
-}
-
-var switchAddress = 1
-var switchAddressPattern, _ = regexp.Compile("^.+picacomic\\.com:\\d+$")
-
-func changeProxyUrl(urlStr string) bool {
- if urlStr == "" {
- client.Transport = &http.Transport{
- TLSHandshakeTimeout: time.Second * 10,
- ExpectContinueTimeout: time.Second * 10,
- ResponseHeaderTimeout: time.Second * 10,
- IdleConnTimeout: time.Second * 10,
- DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- if sAddr, ok := switchAddresses[switchAddress]; ok {
- addr = sAddr
- }
- return dialer.DialContext(ctx, network, addr)
- },
- }
- imageHttpClient.Transport = &http.Transport{
- TLSHandshakeTimeout: time.Second * 10,
- ExpectContinueTimeout: time.Second * 10,
- ResponseHeaderTimeout: time.Second * 10,
- IdleConnTimeout: time.Second * 10,
- DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- return dialer.DialContext(ctx, network, addr)
- },
- }
- return false
- }
- client.Transport = &http.Transport{
- TLSHandshakeTimeout: time.Second * 10,
- ExpectContinueTimeout: time.Second * 10,
- ResponseHeaderTimeout: time.Second * 10,
- IdleConnTimeout: time.Second * 10,
- DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- proxyUrl, err := url.Parse(urlStr)
- if err != nil {
- return nil, err
- }
- proxy, err := proxy.FromURL(proxyUrl, proxy.Direct)
- if err != nil {
- return nil, err
- }
- if sAddr, ok := switchAddresses[switchAddress]; ok {
- addr = sAddr
- }
- return proxy.Dial(network, addr)
- },
- }
- imageHttpClient.Transport = &http.Transport{
- TLSHandshakeTimeout: time.Second * 10,
- ExpectContinueTimeout: time.Second * 10,
- ResponseHeaderTimeout: time.Second * 10,
- IdleConnTimeout: time.Second * 10,
- DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- proxyUrl, err := url.Parse(urlStr)
- if err != nil {
- return nil, err
- }
- proxy, err := proxy.FromURL(proxyUrl, proxy.Direct)
- if err != nil {
- return nil, err
- }
- return proxy.Dial(network, addr)
- },
- }
- return true
-}
-
-func userProfile() (string, error) {
- return serialize(client.UserProfile())
-}
-
-func punchIn() (string, error) {
- return serialize(client.PunchIn())
-}
-
-func categories() (string, error) {
- key := "CATEGORIES"
- expire := time.Hour * 3
- cache := network_cache.LoadCache(key, expire)
- if cache != "" {
- return cache, nil
- }
- categories, err := client.Categories()
- if err != nil {
- return "", err
- }
- buff, _ := json.Marshal(&categories)
- cache = string(buff)
- network_cache.SaveCache(key, cache)
- return cache, nil
-}
-
-
-func collections(_ string) (string, error) {
- key := "COLLECTIONS"
- expire := time.Hour * 3
- cache := network_cache.LoadCache(key, expire)
- if cache != "" {
- return cache, nil
- }
- collections, err := client.Collections()
- if err != nil {
- return "", err
- }
- buff, _ := json.Marshal(&collections)
- cache = string(buff)
- network_cache.SaveCache(key, cache)
- return cache, nil
-}
-
-func comics(params string) (string, error) {
- var paramsStruct struct {
- Category string `json:"category"`
- Tag string `json:"tag"`
- CreatorId string `json:"creatorId"`
- ChineseTeam string `json:"chineseTeam"`
- Sort string `json:"sort"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- return cacheable(
- fmt.Sprintf("COMICS$%s$%s$%s$%s$%s$%d", paramsStruct.Category, paramsStruct.Tag, paramsStruct.CreatorId, paramsStruct.ChineseTeam, paramsStruct.Sort, paramsStruct.Page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.Comics(paramsStruct.Category, paramsStruct.Tag, paramsStruct.CreatorId, paramsStruct.ChineseTeam, paramsStruct.Sort, paramsStruct.Page)
- },
- )
-}
-
-func searchComics(params string) (string, error) {
- var paramsStruct struct {
- Categories []string `json:"categories"`
- Keyword string `json:"keyword"`
- Sort string `json:"sort"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- categories := paramsStruct.Categories
- keyword := paramsStruct.Keyword
- sort := paramsStruct.Sort
- page := paramsStruct.Page
- //
- var categoriesInKey string
- if len(categories) == 0 {
- categoriesInKey = ""
- } else {
- b, _ := json.Marshal(categories)
- categoriesInKey = string(b)
- }
- return cacheable(
- fmt.Sprintf("SEARCH$%s$%s$%s$%d", categoriesInKey, keyword, sort, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.SearchComics(categories, keyword, sort, page)
- },
- )
-}
-
-func randomComics() (string, error) {
- return cacheable(
- fmt.Sprintf("RANDOM"),
- time.Millisecond*1,
- func() (interface{}, error) {
- return client.RandomComics()
- },
- )
-}
-
-func leaderboard(typeName string) (string, error) {
- return cacheable(
- fmt.Sprintf("LEADERBOARD$%s", typeName),
- time.Second*200,
- func() (interface{}, error) {
- return client.Leaderboard(typeName)
- },
- )
-}
-
-func comicInfo(comicId string) (string, error) {
- var err error
- var comic *source.ComicInfo
- // cache
- key := fmt.Sprintf("COMIC_INFO$%s", comicId)
- expire := time.Hour * 24 * 7
- cache := network_cache.LoadCache(key, expire)
- if cache != "" {
- var co source.ComicInfo
- err = json.Unmarshal([]byte(cache), &co)
- if err != nil {
- panic(err)
- return "", err
- }
- comic = &co
- } else {
- // get
- comic, err = client.ComicInfo(comicId)
- if err != nil {
- return "", err
- }
- var buff []byte
- buff, err = json.Marshal(comic)
- if err != nil {
- return "", err
- }
- cache = string(buff)
- network_cache.SaveCache(key, cache)
- }
- // 标记历史记录
- view := comic_center.ComicView{}
- view.ID = comicId
- view.CreatedAt = comic.CreatedAt
- view.UpdatedAt = comic.UpdatedAt
- view.Title = comic.Title
- view.Author = comic.Author
- view.PagesCount = int32(comic.PagesCount)
- view.EpsCount = int32(comic.EpsCount)
- view.Finished = comic.Finished
- c, _ := json.Marshal(comic.Categories)
- view.Categories = string(c)
- view.ThumbOriginalName = comic.Thumb.OriginalName
- view.ThumbFileServer = comic.Thumb.FileServer
- view.ThumbPath = comic.Thumb.Path
- view.LikesCount = int32(comic.LikesCount)
- view.Description = comic.Description
- view.ChineseTeam = comic.ChineseTeam
- t, _ := json.Marshal(comic.Tags)
- view.Tags = string(t)
- view.AllowDownload = comic.AllowDownload
- view.ViewsCount = int32(comic.ViewsCount)
- view.IsFavourite = comic.IsFavourite
- view.IsLiked = comic.IsLiked
- view.CommentsCount = int32(comic.CommentsCount)
- err = comic_center.ViewComicUpdateInfo(&view)
- if err != nil {
- return "", err
- }
- // return
- return cache, nil
-}
-
-func ComicInfoCleanCache(comicId string) {
- key := fmt.Sprintf("COMIC_INFO$%s", comicId)
- network_cache.RemoveCache(key)
-}
-
-func epPage(params string) (string, error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comicId := paramsStruct.ComicId
- page := paramsStruct.Page
- //
- return cacheable(
- fmt.Sprintf("COMIC_EP_PAGE$%s$%d", comicId, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.ComicEpPage(comicId, page)
- },
- )
-}
-
-func comicPicturePageWithQuality(params string) (string, error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- EpOrder int `json:"epOrder"`
- Page int `json:"page"`
- Quality string `json:"quality"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comicId := paramsStruct.ComicId
- epOrder := paramsStruct.EpOrder
- page := paramsStruct.Page
- quality := paramsStruct.Quality
- //
- return cacheable(
- fmt.Sprintf("COMIC_EP_PAGE$%s$%ds$%ds$%s", comicId, epOrder, page, quality),
- time.Hour*2,
- func() (interface{}, error) {
- return client.ComicPicturePageWithQuality(comicId, epOrder, page, quality)
- },
- )
-}
-
-func switchLike(comicId string) (string, error) {
- point, err := client.SwitchLike(comicId)
- if err != nil {
- return "", err
- }
- // 更新viewLog里面的favour
- comic_center.ViewComicUpdateLike(comicId, strings.HasPrefix(*point, "un"))
- // 删除缓存
- ComicInfoCleanCache(comicId)
- return *point, nil
-}
-
-func switchFavourite(comicId string) (string, error) {
- point, err := client.SwitchFavourite(comicId)
- if err != nil {
- return "", err
- }
- // 更新viewLog里面的favour
- comic_center.ViewComicUpdateFavourite(comicId, strings.HasPrefix(*point, "un"))
- // 删除缓存
- ComicInfoCleanCache(comicId)
- return *point, nil
-}
-
-func favouriteComics(params string) (string, error) {
- var paramsStruct struct {
- Sort string `json:"sort"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- sort := paramsStruct.Sort
- page := paramsStruct.Page
- //
- point, err := client.FavouriteComics(sort, page)
- if err != nil {
- return "", err
- }
- str, err := json.Marshal(point)
- if err != nil {
- return "", err
- }
- return string(str), nil
-}
-
-func recommendation(comicId string) (string, error) {
- return cacheable(
- fmt.Sprintf("RECOMMENDATION$%s", comicId),
- time.Hour*2,
- func() (interface{}, error) {
- return client.ComicRecommendation(comicId)
- },
- )
-}
-
-func comments(params string) (string, error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comicId := paramsStruct.ComicId
- page := paramsStruct.Page
- return cacheable(
- fmt.Sprintf("COMMENTS$%s$%d", comicId, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.ComicCommentsPage(comicId, page)
- },
- )
-}
-
-func commentChildren(params string) (string, error) {
- var paramsStruct struct {
- CommentId string `json:"commentId"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- commentId := paramsStruct.CommentId
- page := paramsStruct.Page
- return cacheable(
- fmt.Sprintf("COMMENT_CHILDREN$%s$%d", commentId, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.CommentChildren(commentId, page)
- },
- )
-}
-
-func postComment(params string) (string, error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- Content string `json:"content"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- err := client.PostComment(paramsStruct.ComicId, paramsStruct.Content)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("COMMENTS$%s$%%", paramsStruct.ComicId))
- return "", nil
-}
-
-func postChildComment(params string) (string, error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- CommentId string `json:"commentId"`
- Content string `json:"content"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- err := client.PostChildComment(paramsStruct.CommentId, paramsStruct.Content)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches(fmt.Sprintf("COMMENT_CHILDREN$%s$%%", paramsStruct.CommentId))
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("COMMENTS$%s$%%", paramsStruct.ComicId))
- return "", nil
-}
-
-func postGameChildComment(params string) (string, error) {
- var paramsStruct struct {
- GameId string `json:"gameId"`
- CommentId string `json:"commentId"`
- Content string `json:"content"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- err := client.PostChildComment(paramsStruct.CommentId, paramsStruct.Content)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches(fmt.Sprintf("GAME_COMMENT_CHILDREN$%s$%%", paramsStruct.CommentId))
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("GAME_COMMENTS$%s$%%", paramsStruct.GameId))
- return "", nil
-}
-
-func switchLikeComment(params string) (string, error) {
- var paramsStruct struct {
- CommentId string `json:"commentId"`
- ComicId string `json:"comicId"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- rsp, err := client.SwitchLikeComment(paramsStruct.CommentId)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches(fmt.Sprintf("COMMENT_CHILDREN$%s$%%", paramsStruct.CommentId))
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("COMMENTS$%s$%%", paramsStruct.ComicId))
- return *rsp, nil
-}
-
-func myComments(pageStr string) (string, error) {
- page, err := strconv.Atoi(pageStr)
- if err != nil {
- return "", err
- }
- return cacheable(
- fmt.Sprintf("MY_COMMENTS$%d", page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.MyComments(page)
- },
- )
-}
-
-func games(pageStr string) (string, error) {
- page, err := strconv.Atoi(pageStr)
- if err != nil {
- return "", err
- }
- return cacheable(
- fmt.Sprintf("GAMES$%d", page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.GamePage(page)
- },
- )
-}
-
-func game(gameId string) (string, error) {
- return cacheable(
- fmt.Sprintf("GAME$%s", gameId),
- time.Hour*2,
- func() (interface{}, error) {
- return client.GameInfo(gameId)
- },
- )
-}
-
-func gameComments(params string) (string, error) {
- var paramsStruct struct {
- GameId string `json:"gameId"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- gameId := paramsStruct.GameId
- page := paramsStruct.Page
- return cacheable(
- fmt.Sprintf("GAME_COMMENTS$%s$%d", gameId, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.GameCommentsPage(gameId, page)
- },
- )
-}
-
-func postGameComment(params string) (string, error) {
- var paramsStruct struct {
- GameId string `json:"gameId"`
- Content string `json:"content"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- err := client.PostGameComment(paramsStruct.GameId, paramsStruct.Content)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("GAME_COMMENTS$%s$%%", paramsStruct.GameId))
- return "", nil
-}
-
-func gameCommentChildren(params string) (string, error) {
- var paramsStruct struct {
- CommentId string `json:"commentId"`
- Page int `json:"page"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- commentId := paramsStruct.CommentId
- page := paramsStruct.Page
- return cacheable(
- fmt.Sprintf("GAME_COMMENT_CHILDREN$%s$%d", commentId, page),
- time.Hour*2,
- func() (interface{}, error) {
- return client.GameCommentChildren(commentId, page)
- },
- )
-}
-
-func switchLikeGameComment(params string) (string, error) {
- var paramsStruct struct {
- CommentId string `json:"commentId"`
- GameId string `json:"gameId"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- rsp, err := client.SwitchLikeComment(paramsStruct.CommentId)
- if err != nil {
- return "", err
- }
- network_cache.RemoveCaches(fmt.Sprintf("GAME_COMMENT_CHILDREN$%s$%%", paramsStruct.CommentId))
- network_cache.RemoveCaches("MY_COMMENTS$%")
- network_cache.RemoveCaches(fmt.Sprintf("GAME_COMMENTS$%s$%%", paramsStruct.GameId))
- return *rsp, nil
-}
-
-func updatePassword(params string) (string, error) {
- var paramsStruct struct {
- OldPassword string `json:"oldPassword"`
- NewPassword string `json:"newPassword"`
- }
- err := json.Unmarshal([]byte(params), ¶msStruct)
- if err != nil {
- return "", err
- }
- err = client.UpdatePassword(paramsStruct.OldPassword, paramsStruct.NewPassword)
- if err != nil {
- return "", err
- }
- setPassword(paramsStruct.NewPassword)
- return "", nil
-}
-
-func updateSlogan(slogan string) (string, error) {
- return "", client.UpdateSlogan(slogan)
-}
-
-func updateAvatar(avatarBase64 string) (string, error) {
- buff, err := base64.StdEncoding.DecodeString(avatarBase64)
- if err != nil {
- return "", err
- }
- return "", client.UpdateAvatar(buff)
-}
diff --git a/go/pikapika/common.go b/go/pikapika/common.go
deleted file mode 100644
index 0ff18b5..0000000
--- a/go/pikapika/common.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package pikapika
-
-import (
- "encoding/json"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/database/network_cache"
- "time"
-)
-
-// EventNotify EventChannel 总线
-var EventNotify func(message string)
-
-// 所有的EventChannel都是从这里发出, 格式为json, function代表了是什么事件, content是消息的内容
-// 消息传到前端后由前端调度分发
-func onEvent(function string, content string) {
- event := EventNotify
- if event != nil {
- message := map[string]string{
- "function": function,
- "content": content,
- }
- buff, err := json.Marshal(message)
- if err == nil {
- event(string(buff))
- } else {
- print("SEND ERR?")
- }
- }
-}
-
-// 发送下载的事件
-func downloadComicEventSend(comicDownload *comic_center.ComicDownload) {
- buff, err := json.Marshal(comicDownload)
- if err == nil {
- onEvent("DOWNLOAD", string(buff))
- } else {
- print("SEND ERR?")
- }
-}
-
-// 发送导出的事件
-func notifyExport(str string) {
- onEvent("EXPORT", str)
-}
-
-// 缓存接口
-func cacheable(key string, expire time.Duration, reload func() (interface{}, error)) (string, error) {
- // CACHE
- cache := network_cache.LoadCache(key, expire)
- if cache != "" {
- return cache, nil
- }
- // obj
- obj, err := reload()
- if err != nil {
- return "", err
- }
- buff, err := json.Marshal(obj)
- // push to cache
- if err != nil {
- return "", err
- }
- // return
- cache = string(buff)
- network_cache.SaveCache(key, cache)
- return cache, nil
-}
-
-// 将interface序列化成字符串, 方便与flutter通信
-func serialize(point interface{}, err error) (string, error) {
- if err != nil {
- return "", err
- }
- buff, err := json.Marshal(point)
- return string(buff), nil
-}
diff --git a/go/pikapika/config/common.go b/go/pikapika/config/common.go
deleted file mode 100644
index fbebc90..0000000
--- a/go/pikapika/config/common.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package config
-
-import (
- "path"
- "pikapika/pikapika"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/database/network_cache"
- "pikapika/pikapika/database/properties"
- "pikapika/pikapika/utils"
-)
-
-// InitApplication 由不同的平台直接调用, 根据提供的路径初始化数据库, 资料文件夹
-func InitApplication(applicationDir string) {
- println("初始化 : " + applicationDir)
- var databasesDir, remoteDir, downloadDir, tmpDir string
- databasesDir = path.Join(applicationDir, "databases")
- remoteDir = path.Join(applicationDir, "pictures", "remote")
- downloadDir = path.Join(applicationDir, "download")
- tmpDir = path.Join(applicationDir, "tmp")
- utils.Mkdir(databasesDir)
- utils.Mkdir(remoteDir)
- utils.Mkdir(downloadDir)
- utils.Mkdir(tmpDir)
- properties.InitDBConnect(databasesDir)
- network_cache.InitDBConnect(databasesDir)
- comic_center.InitDBConnect(databasesDir)
- pikapika.InitClient()
- pikapika.InitPlugin(remoteDir, downloadDir, tmpDir)
-}
diff --git a/go/pikapika/database/comic_center/center.go b/go/pikapika/database/comic_center/center.go
deleted file mode 100644
index 85de0b6..0000000
--- a/go/pikapika/database/comic_center/center.go
+++ /dev/null
@@ -1,583 +0,0 @@
-package comic_center
-
-import (
- "gorm.io/driver/sqlite"
- "gorm.io/gorm"
- "gorm.io/gorm/clause"
- "path"
- "pikapika/pikapika/utils"
- "sync"
- "time"
-)
-
-var mutex = sync.Mutex{}
-var db *gorm.DB
-
-func InitDBConnect(databaseDir string) {
- mutex.Lock()
- defer mutex.Unlock()
- var err error
- db, err = gorm.Open(sqlite.Open(path.Join(databaseDir, "comic_center.db")), utils.GormConfig)
- if err != nil {
- panic("failed to connect database")
- }
- db.AutoMigrate(&ComicView{})
- db.AutoMigrate(&RemoteImage{})
- db.AutoMigrate(&ComicDownload{})
- db.AutoMigrate(&ComicDownloadEp{})
- db.AutoMigrate(&ComicDownloadPicture{})
-}
-
-func Transaction(t func(tx *gorm.DB) error) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(t)
-}
-
-func NoLockActionViewComicUpdateInfoDB(view *ComicView, db *gorm.DB) error {
- view.LastViewTime = time.Now()
- return db.Clauses(clause.OnConflict{
- Columns: []clause.Column{{Name: "id"}},
- DoUpdates: clause.AssignmentColumns([]string{
- "created_at",
- "updated_at",
- "title",
- "author",
- "pages_count",
- "eps_count",
- "finished",
- "categories",
- "thumb_original_name",
- "thumb_file_server",
- "thumb_path",
- "likes_count",
- "description",
- "chinese_team",
- "tags",
- "allow_download",
- "views_count",
- "is_favourite",
- "is_liked",
- "comments_count",
- "last_view_time",
- }),
- }).Create(view).Error
-}
-
-func ViewComicUpdateInfo(view *ComicView) error {
- mutex.Lock()
- defer mutex.Unlock()
- return NoLockActionViewComicUpdateInfoDB(view, db)
-}
-
-func ViewComic(comicId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicView{}).Where(
- "id = ?", comicId,
- ).Update(
- "last_view_time",
- time.Now(),
- ).Error
-}
-
-func ViewComicUpdateFavourite(comicId string, favourite bool) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicView{}).Where(
- "id = ?", comicId,
- ).Update(
- "is_favourite",
- favourite,
- ).Error
-}
-
-func ViewComicUpdateLike(comicId string, like bool) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicView{}).Where(
- "id = ?", comicId,
- ).Update(
- "is_like",
- like,
- ).Error
-}
-
-func ViewEpAndPicture(comicId string, epOrder int, epTitle string, pictureRank int) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicView{}).Where("id", comicId).Updates(
- map[string]interface{}{
- "last_view_time": time.Now(),
- "last_view_ep_order": epOrder,
- "last_view_ep_title": epTitle,
- "last_view_picture_rank": pictureRank,
- },
- ).Error
-}
-
-func LoadViewLog(comicId string) (*ComicView, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var view ComicView
- err := db.First(&view, "id = ?", comicId).Error
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- if err != nil {
- return nil, err
- }
- return &view, nil
-}
-
-func FindRemoteImage(fileServer string, path string) *RemoteImage {
- mutex.Lock()
- defer mutex.Unlock()
- var remoteImage RemoteImage
- err := db.First(&remoteImage, "file_server = ? AND path = ?", fileServer, path).Error
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil
- } else {
- panic(err)
- }
- }
- return &remoteImage
-}
-
-func SaveRemoteImage(remote *RemoteImage) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Clauses(clause.OnConflict{
- Columns: []clause.Column{{Name: "file_server"}, {Name: "path"}},
- DoUpdates: clause.AssignmentColumns([]string{
- "updated_at",
- "file_size",
- "format",
- "width",
- "height",
- "local_path",
- }),
- }).Create(remote).Error
-}
-
-func CreateDownload(comic *ComicDownload, epList *[]ComicDownloadEp) error {
- mutex.Lock()
- defer mutex.Unlock()
- comic.SelectedEpCount = int32(len(*epList))
- return db.Transaction(func(tx *gorm.DB) error {
- err := tx.Create(comic).Error
- if err != nil {
- return err
- }
- for _, ep := range *epList {
- err := tx.Create(&ep).Error
- if err != nil {
- return err
- }
- }
- return nil
- })
-}
-
-func AddDownload(comic *ComicDownload, epList *[]ComicDownloadEp) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(func(tx *gorm.DB) error {
- err := tx.Model(comic).Where("id = ?", comic.ID).Updates(map[string]interface{}{
- "created_at": comic.CreatedAt,
- "updated_at": comic.UpdatedAt,
- "title": comic.Title,
- "author": comic.Author,
- "pages_count": comic.PagesCount,
- "eps_count": comic.EpsCount,
- "finished": comic.Finished,
- "categories": comic.Categories,
- "thumb_original_name": comic.ThumbOriginalName,
- "thumb_file_server": comic.ThumbFileServer,
- "thumb_path": comic.ThumbPath,
- "description": comic.Description,
- "chinese_team": comic.ChineseTeam,
- "tags": comic.Tags,
- "download_finished": false, // restart
- }).Error
- if err != nil {
- return err
- }
- err = tx.Exec(
- "UPDATE comic_downloads SET eps_count = selected_ep_count + ? WHERE id = ?",
- len(*epList), comic.ID,
- ).Error
- if err != nil {
- return err
- }
- for _, ep := range *epList {
- err := tx.Create(&ep).Error
- if err != nil {
- return err
- }
- }
- return nil
- })
-}
-
-func UpdateDownloadLogo(comicId string, fileSize int64, format string, width int32, height int32, localPath string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownload{}).Where("id = ?", comicId).Updates(map[string]interface{}{
- "thumb_file_size": fileSize,
- "thumb_format": format,
- "thumb_width": width,
- "thumb_height": height,
- "thumb_local_path": localPath,
- }).Error
-}
-
-func FindComicDownloadById(comicId string) (*ComicDownload, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var download ComicDownload
- err := db.First(&download, "id = ?", comicId).Error
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- return nil, err
- }
- return &download, nil
-}
-
-func ListDownloadEpByComicId(comicId string) ([]ComicDownloadEp, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var epList []ComicDownloadEp
- err := db.Where("comic_id = ?", comicId).Order("ep_order ASC").Find(&epList).Error
- return epList, err
-}
-
-func ListDownloadPictureByEpId(epId string) ([]ComicDownloadPicture, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var pictureList []ComicDownloadPicture
- err := db.Where("ep_id = ?", epId).Order("rank_in_ep ASC").Find(&pictureList).Error
- return pictureList, err
-}
-
-func AllDownloads() (*[]ComicDownload, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var downloads []ComicDownload
- err := db.Table("comic_downloads").
- Joins("LEFT JOIN comic_views ON comic_views.id = comic_downloads.id").
- Select("comic_downloads.*").
- Order("comic_views.last_view_time DESC").
- Scan(&downloads).Error
- // err := db.Find(&downloads).Error
- return &downloads, err
-}
-
-func LoadFirstNeedDownload() (*ComicDownload, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var download ComicDownload
- err := db.First(&download, "download_failed = 0 AND pause = 0 AND deleting = 0 AND download_finished = 0").Error
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- return nil, err
- }
- return &download, nil
-}
-
-func LoadFirstNeedDownloadEp(comicId string) (*ComicDownloadEp, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var ep ComicDownloadEp
- err := db.First(
- &ep,
- " comic_id = ? AND download_failed = 0 AND download_finished = 0 AND fetched_pictures = 1",
- comicId,
- ).Error
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- return nil, err
- }
- return &ep, nil
-}
-
-// LoadNeedDownloadPictures 根据EP.ID获取需要下载的图片
-func LoadNeedDownloadPictures(epId string, limit int) (*[]ComicDownloadPicture, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var pictures []ComicDownloadPicture
- err := db.Find(
- &pictures,
- "ep_id = ? AND download_failed = 0 AND download_finished = 0 LIMIT ?",
- epId, limit,
- ).Error
- return &pictures, err
-}
-
-func FetchPictures(comicId string, epId string, list *[]ComicDownloadPicture) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(func(tx *gorm.DB) error {
- var rankInEp int32
- for _, picture := range *list {
- rankInEp = rankInEp + 1
- picture.RankInEp = rankInEp
- err := tx.Create(&picture).Error
- if err != nil {
- return err
- }
- }
- err := tx.Model(&ComicDownloadEp{}).Where("id = ?", epId).Updates(map[string]interface{}{
- "fetched_pictures": true,
- "selected_picture_count": len(*list),
- }).Error
- if err != nil {
- return err
- }
- return tx.Exec(
- "UPDATE comic_downloads SET selected_picture_count = selected_picture_count + ? WHERE id = ?",
- len(*list), comicId,
- ).Error
- })
-}
-
-func DownloadFailed(comicId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownload{}).Where("id = ?", comicId).Update("download_failed", true).Error
-}
-
-func DownloadSuccess(comicId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownload{}).Where("id = ?", comicId).Updates(map[string]interface{}{
- "download_finished": true,
- "download_finished_time": time.Now(),
- }).Error
-}
-
-func EpFailed(epId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownloadEp{}).Where("id = ?", epId).Update("download_failed", true).Error
-}
-
-func EpSuccess(comicId string, epId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(func(tx *gorm.DB) error {
- err := tx.Model(&ComicDownloadEp{}).Where("id = ?", epId).Updates(map[string]interface{}{
- "download_finished": true,
- "download_finished_time": time.Now(),
- }).Error
- if err != nil {
- return err
- }
- return tx.Exec(
- "UPDATE comic_downloads SET download_ep_count = download_ep_count + 1 WHERE id = ?",
- comicId,
- ).Error
- })
-}
-
-func PictureFailed(pictureId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownloadPicture{}).Where("id = ?", pictureId).Update("download_failed", true).Error
-}
-
-func PictureSuccess(
- comicId string, epId string, pictureId string,
- fileSize int64, format string, width int32, height int32, localPath string,
-) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(func(tx *gorm.DB) error {
- err := tx.Model(&ComicDownloadPicture{}).Where("id = ?", pictureId).Updates(map[string]interface{}{
- "file_size": fileSize,
- "format": format,
- "width": width,
- "height": height,
- "local_path": localPath,
- "download_finished": true,
- "download_finished_time": time.Now(),
- }).Error
- if err != nil {
- return err
- }
- err = tx.Exec(
- "UPDATE comic_download_eps SET download_picture_count = download_picture_count + 1 WHERE id = ?",
- epId,
- ).Error
- if err != nil {
- return err
- }
- return tx.Exec(
- "UPDATE comic_downloads SET download_picture_count = download_picture_count + 1 WHERE id = ?",
- comicId,
- ).Error
- })
-}
-
-func ResetAll() error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Transaction(func(tx *gorm.DB) error {
- err := tx.Model(&ComicDownload{}).Where("1 = 1").
- Update("download_failed", false).Error
- if err != nil {
- return err
- }
- err = tx.Model(&ComicDownloadEp{}).Where("1 = 1").
- Update("download_failed", false).Error
- if err != nil {
- return err
- }
- err = tx.Model(&ComicDownloadPicture{}).Where("1 = 1").
- Update("download_failed", false).Error
- return err
- })
-}
-
-func ViewLogPage(offset int, limit int) (*[]ComicView, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var list []ComicView
- err := db.Offset(offset).Limit(limit).Order("last_view_time DESC").Find(&list).Error
- return &list, err
-}
-
-func ClearAllViewLog() {
- mutex.Lock()
- defer mutex.Unlock()
- db.Unscoped().Where("1 = 1").Delete(&ComicView{})
-}
-
-func DeleteViewLog(id string) {
- mutex.Lock()
- defer mutex.Unlock()
- db.Unscoped().Where("id = ?", id).Delete(&ComicView{})
-}
-
-func DeletingComic() (*ComicDownload, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var download ComicDownload
- err := db.First(&download, "deleting = 1").Error
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- return &download, err
-}
-
-func TrueDelete(comicId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Transaction(func(tx *gorm.DB) error {
- err := tx.Unscoped().Delete(&ComicDownload{}, "id = ?", comicId).Error
- if err != nil {
- return err
- }
- err = tx.Unscoped().Delete(&ComicDownloadEp{}, "comic_id = ?", comicId).Error
- if err != nil {
- return err
- }
- err = tx.Unscoped().Delete(&ComicDownloadPicture{}, "comic_id = ?", comicId).Error
- if err != nil {
- return err
- }
- return nil
- })
- if err != nil {
- return err
- }
- return db.Raw("VACUUM").Error
-}
-
-func Deleting(comicId string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Model(&ComicDownload{}).Where("id = ?", comicId).Updates(map[string]interface{}{
- "deleting": true,
- }).Error
-}
-
-func RemoveAllRemoteImage() error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Unscoped().Delete(&RemoteImage{}, "1 = 1").Error
- if err != nil {
- return err
- }
- return db.Raw("VACUUM").Error
-}
-
-func EarliestRemoteImage(earliest time.Time, pageSize int) ([]RemoteImage, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var images []RemoteImage
- err := db.Where("strftime('%s',updated_at) < strftime('%s',?)", earliest).
- Order("updated_at").Limit(pageSize).Find(&images).Error
- return images, err
-}
-
-func DeleteRemoteImages(images []RemoteImage) error {
- mutex.Lock()
- defer mutex.Unlock()
- if len(images) == 0 {
- return nil
- }
- ids := make([]uint, len(images))
- for i := 0; i < len(images); i++ {
- ids[i] = images[i].ID
- }
- return db.Unscoped().Model(&RemoteImage{}).Delete("id in ?", ids).Error
-}
-
-func DownloadInfo(comicId string) (*ComicDownload, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var download ComicDownload
- err := db.First(&download, "id = ?", comicId).Error
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, nil
- }
- return nil, err
- }
- return &download, nil
-}
-
-func UpdateTimeCacheImageTime(id uint) {
- now := time.Now()
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Model(&RemoteImage{}).Where("id = ?", id).Updates(map[string]interface{}{
- "created_at": now,
- "updated_at": now,
- }).Error
- if err != nil {
- panic(err)
- }
-}
-
-func ViewedList(ids []string) (viewedList []ComicView) {
- err := db.Find(&viewedList, ids).Error
- if err != nil {
- panic(err)
- }
- return
-}
-
-func VACUUM() error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Raw("VACUUM").Error
-}
diff --git a/go/pikapika/database/comic_center/entities.go b/go/pikapika/database/comic_center/entities.go
deleted file mode 100644
index f2f6a6b..0000000
--- a/go/pikapika/database/comic_center/entities.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package comic_center
-
-import (
- "gorm.io/gorm"
- "time"
-)
-
-type RemoteImage struct {
- gorm.Model
- FileServer string `gorm:"index:uk_fp,unique" json:"fileServer"`
- Path string `gorm:"index:uk_fp,unique" json:"path"`
- FileSize int64 `json:"fileSize"`
- Format string `json:"format"`
- Width int32 `json:"width"`
- Height int32 `json:"height"`
- LocalPath string `json:"localPath"`
-}
-
-type ComicSimple struct {
- ID string `gorm:"primarykey" json:"id"`
- CreatedAt time.Time `json:"createdAt"`
- UpdatedAt time.Time `json:"updatedAt"`
- Title string `json:"title"`
- Author string `json:"author"`
- PagesCount int32 `json:"pagesCount"`
- EpsCount int32 `json:"epsCount"`
- Finished bool `json:"finished"`
- Categories string `json:"categories"`
- ThumbOriginalName string `json:"thumbOriginalName"`
- ThumbFileServer string `json:"thumbFileServer"`
- ThumbPath string `json:"thumbPath"`
-}
-
-type ComicInfo struct {
- ComicSimple
- LikesCount int32 `json:"likesCount"`
- Description string `json:"description"`
- ChineseTeam string `json:"chineseTeam"`
- Tags string `json:"tags"`
- AllowDownload bool `json:"allowDownload"`
- ViewsCount int32 `json:"viewsCount"`
- IsFavourite bool `json:"isFavourite"`
- IsLiked bool `json:"isLiked"`
- CommentsCount int32 `json:"commentsCount"`
-}
-
-type ComicView struct {
- ComicInfo
- LastViewTime time.Time `json:"lastViewTime"`
- LastViewEpOrder int32 `json:"lastViewEpOrder"`
- LastViewEpTitle string `json:"lastViewEpTitle"`
- LastViewPictureRank int32 `json:"lastViewPictureRank"`
-}
-
-type ComicDownload struct {
- ComicSimple
- Description string `json:"description"`
- ChineseTeam string `json:"chineseTeam"`
- Tags string `json:"tags"`
- SelectedEpCount int32 `json:"selectedEpCount"`
- SelectedPictureCount int32 `json:"selectedPictureCount"`
- DownloadEpCount int32 `json:"downloadEpCount"`
- DownloadPictureCount int32 `json:"downloadPictureCount"`
- DownloadFinished bool `json:"downloadFinished"`
- DownloadFinishedTime time.Time `json:"downloadFinishedTime"`
- DownloadFailed bool `json:"downloadFailed"`
- Deleting bool `json:"deleting"`
- ThumbFileSize int64 `json:"thumbFileSize"`
- ThumbFormat string `json:"thumbFormat"`
- ThumbWidth int32 `json:"thumbWidth"`
- ThumbHeight int32 `json:"thumbHeight"`
- ThumbLocalPath string `json:"thumbLocalPath"`
- Pause bool `json:"pause"`
-}
-
-type ComicDownloadEp struct {
- ComicId string `gorm:"index:idx_comic_id" json:"comicId"`
- ID string `gorm:"primarykey" json:"id"`
- UpdatedAt time.Time `json:"updated_at"`
- EpOrder int32 `json:"epOrder"`
- Title string `json:"title"`
- FetchedPictures bool `json:"fetchedPictures"`
- SelectedPictureCount int32 `json:"selectedPictureCount"`
- DownloadPictureCount int32 `json:"downloadPictureCount"`
- DownloadFinished bool `json:"downloadFinish"`
- DownloadFinishedTime time.Time `json:"downloadFinishTime"`
- DownloadFailed bool `json:"downloadFailed"`
-}
-
-type ComicDownloadPicture struct {
- ID string `gorm:"primarykey" json:"id"`
- ComicId string `gorm:"index:idx_comic_id" json:"comicId"`
- EpId string `gorm:"index:idx_ep_id" json:"epId"`
- EpOrder int32 `gorm:"index:idx_ep_order" json:"epOrder"`
- RankInEp int32 `json:"rankInEp"`
- DownloadFinished bool `json:"downloadFinish"`
- DownloadFinishedTime time.Time `json:"downloadFinishTime"`
- DownloadFailed bool `json:"downloadFailed"`
- OriginalName string
- FileServer string `gorm:"index:idx_fp,priority:1" json:"fileServer"`
- Path string `gorm:"index:idx_fp,priority:2" json:"path"`
- FileSize int64 `json:"fileSize"`
- Format string `json:"format"`
- Width int32 `json:"width"`
- Height int32 `json:"height"`
- LocalPath string `json:"localPath"`
-}
diff --git a/go/pikapika/database/network_cache/cache.go b/go/pikapika/database/network_cache/cache.go
deleted file mode 100644
index 3bf8e31..0000000
--- a/go/pikapika/database/network_cache/cache.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package network_cache
-
-import (
- "errors"
- "gorm.io/driver/sqlite"
- "gorm.io/gorm"
- "gorm.io/gorm/clause"
- "path"
- "pikapika/pikapika/utils"
- "sync"
- "time"
-)
-
-var mutex = sync.Mutex{}
-var db *gorm.DB
-
-type NetworkCache struct {
- gorm.Model
- K string `gorm:"index:uk_k,unique"`
- V string
-}
-
-func InitDBConnect(databaseDir string) {
- mutex.Lock()
- defer mutex.Unlock()
- var err error
- db, err = gorm.Open(sqlite.Open(path.Join(databaseDir, "network_cache.db")), utils.GormConfig)
- if err != nil {
- panic("failed to connect database")
- }
- db.AutoMigrate(&NetworkCache{})
-}
-
-func LoadCache(key string, expire time.Duration) string {
- mutex.Lock()
- defer mutex.Unlock()
- var cache NetworkCache
- err := db.First(&cache, "k = ? AND updated_at > ?", key, time.Now().Add(expire*-1)).Error
- if err == nil {
- return cache.V
- }
- if gorm.ErrRecordNotFound == err {
- return ""
- }
- panic(errors.New("?"))
-}
-
-func SaveCache(key string, value string) {
- mutex.Lock()
- defer mutex.Unlock()
- db.Clauses(clause.OnConflict{
- Columns: []clause.Column{{Name: "k"}},
- DoUpdates: clause.AssignmentColumns([]string{"created_at", "updated_at", "v"}),
- }).Create(&NetworkCache{
- K: key,
- V: value,
- })
-}
-
-func RemoveCache(key string) error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Unscoped().Delete(&NetworkCache{}, "k = ?", key).Error
- if err == gorm.ErrRecordNotFound {
- return nil
- }
- return err
-}
-
-func RemoveCaches(like string) error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Unscoped().Delete(&NetworkCache{}, "k LIKE ?", like).Error
- if err == gorm.ErrRecordNotFound {
- return nil
- }
- return err
-}
-
-func RemoveAll() error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Unscoped().Delete(&NetworkCache{}, "1 = 1").Error
- if err != nil {
- return err
- }
- return db.Raw("VACUUM").Error
-}
-
-func RemoveEarliest(earliest time.Time) error {
- mutex.Lock()
- defer mutex.Unlock()
- err := db.Unscoped().Where("strftime('%s',updated_at) < strftime('%s',?)", earliest).
- Delete(&NetworkCache{}).Error
- if err != nil {
- return err
- }
- return db.Raw("VACUUM").Error
-}
diff --git a/go/pikapika/database/properties/properties.go b/go/pikapika/database/properties/properties.go
deleted file mode 100644
index 573cd01..0000000
--- a/go/pikapika/database/properties/properties.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package properties
-
-import (
- "errors"
- "fmt"
- "gorm.io/driver/sqlite"
- "gorm.io/gorm"
- "gorm.io/gorm/clause"
- "path"
- "pikapika/pikapika/utils"
- "strconv"
- "sync"
-)
-
-var mutex = sync.Mutex{}
-var db *gorm.DB
-
-func InitDBConnect(databaseDir string) {
- mutex.Lock()
- defer mutex.Unlock()
- var err error
- db, err = gorm.Open(sqlite.Open(path.Join(databaseDir, "properties.db")), utils.GormConfig)
- if err != nil {
- panic("failed to connect database")
- }
- db.AutoMigrate(&Property{})
-}
-
-type Property struct {
- gorm.Model
- K string `gorm:"index:uk_k,unique"`
- V string
-}
-
-func LoadProperty(name string, defaultValue string) (string, error) {
- mutex.Lock()
- defer mutex.Unlock()
- var property Property
- err := db.First(&property, "k", name).Error
- if err == nil {
- return property.V, nil
- }
- if gorm.ErrRecordNotFound == err {
- return defaultValue, nil
- }
- panic(errors.New("?"))
-}
-
-func SaveProperty(name string, value string) error {
- mutex.Lock()
- defer mutex.Unlock()
- return db.Clauses(clause.OnConflict{
- Columns: []clause.Column{{Name: "k"}},
- DoUpdates: clause.AssignmentColumns([]string{"created_at", "updated_at", "v"}),
- }).Create(&Property{
- K: name,
- V: value,
- }).Error
-}
-
-func LoadBoolProperty(name string, defaultValue bool) (bool, error) {
- stringValue, err := LoadProperty(name, strconv.FormatBool(defaultValue))
- if err != nil {
- return false, err
- }
- return strconv.ParseBool(stringValue)
-}
-
-func SaveBoolProperty(name string, value bool) error {
- return SaveProperty(name, strconv.FormatBool(value))
-}
-
-func LoadIntProperty(name string, defaultValue int) (int, error) {
- str, err := LoadProperty(name, fmt.Sprintf("%d", defaultValue))
- if err != nil {
- return 0, err
- }
- return strconv.Atoi(str)
-}
-
-func SaveIntProperty(name string, value int) error {
- return SaveProperty(name, strconv.Itoa(value))
-}
-
-func SaveProxy(value string) error {
- return SaveProperty("proxy", value)
-}
-
-func LoadProxy() (string, error) {
- return LoadProperty("proxy", "")
-}
-
-func SaveUsername(value string) error {
- return SaveProperty("username", value)
-}
-
-func LoadUsername() (string, error) {
- return LoadProperty("username", "")
-}
-
-func SavePassword(value string) error {
- return SaveProperty("password", value)
-}
-
-func LoadPassword() (string, error) {
- return LoadProperty("password", "")
-}
-
-func SaveToken(value string) {
- SaveProperty("token", value)
-}
-
-func LoadToken() (string, error) {
- return LoadProperty("token", "")
-}
-
-func SaveTokenTime(value int64) {
- SaveProperty("token_time", strconv.FormatInt(value, 10))
-}
-
-func LoadTokenTime() (int64, error) {
- str, err := LoadProperty("token_time", "0")
- if err != nil {
- return 0, err
- }
- return strconv.ParseInt(str, 10, 64)
-}
diff --git a/go/pikapika/download.go b/go/pikapika/download.go
deleted file mode 100644
index cd3b8ee..0000000
--- a/go/pikapika/download.go
+++ /dev/null
@@ -1,498 +0,0 @@
-package pikapika
-
-import (
- "bytes"
- "fmt"
- "image"
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- comic_center2 "pikapika/pikapika/database/comic_center"
- utils2 "pikapika/pikapika/utils"
- "sync"
- "time"
-)
-
-// 使用协程进行后台下载
-// downloadRunning 如果为false则停止下载
-// downloadRestart 为true则取消从新启动下载功能
-
-var downloadThreadCount = 1
-var downloadThreadFetch = 100
-
-var downloadRunning = false
-var downloadRestart = false
-
-var downloadingComic *comic_center2.ComicDownload
-var downloadingEp *comic_center2.ComicDownloadEp
-
-var dlFlag = true
-
-// 程序启动后仅调用一次, 启动后台线程
-func downloadBackground() {
- println("后台线程启动")
- if dlFlag {
- dlFlag = false
- go downloadBegin()
- }
-}
-
-// 下载启动/重新启动会暂停三秒
-func downloadBegin() {
- time.Sleep(time.Second * 3)
- go downloadLoadComic()
-}
-
-// 下载周期中, 每个下载单元会调用此方法, 如果返回true应该停止当前动作
-func downloadHasStop() bool {
- if !downloadRunning {
- return true
- }
- if downloadRestart {
- downloadRestart = false
- return true
- }
- return false
-}
-
-// 删除下载任务, 当用户要删除下载的时候, 他会被加入删除队列, 而不是直接被删除, 以减少出错
-func downloadDelete() bool {
- c, e := comic_center2.DeletingComic()
- if e != nil {
- panic(e)
- }
- if c != nil {
- os.RemoveAll(downloadPath(c.ID))
- e = comic_center2.TrueDelete(c.ID)
- if e != nil {
- panic(e)
- }
- return true
- }
- return false
-}
-
-// 加载第一个需要下载的漫画
-func downloadLoadComic() {
- // 每次下载完一个漫画, 或者启动的时候, 首先进行删除任务
- for downloadDelete() {
- }
- // 检测是否需要停止
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 找到第一个要下载的漫画, 查库有错误就停止, 因为这些错误很少出现, 一旦出现必然是严重的, 例如数据库文件突然被删除
- var err error
- downloadingComic, err = comic_center2.LoadFirstNeedDownload()
- if err != nil {
- panic(err)
- }
- // 处理找到的下载任务
- go downloadInitComic()
-}
-
-// 初始化找到的下载任务
-func downloadInitComic() {
- // 检测是否需要停止
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 若没有漫画要下载则重新启动
- if downloadingComic == nil {
- println("没有找到要下载的漫画")
- go downloadBegin()
- return
- }
- // 打印日志, 并向前端的eventChannel发送下载信息
- println("正在下载漫画 " + downloadingComic.Title)
- downloadComicEventSend(downloadingComic)
- eps, err := comic_center2.ListDownloadEpByComicId(downloadingComic.ID)
- if err != nil {
- panic(err)
- }
- // 找到这个漫画需要下载的EP, 并搜索获取图片地址
- for _, ep := range eps {
- // FetchedPictures字段标志着这个章节的图片地址有没有获取过, 如果没有获取过就重新获取
- if !ep.FetchedPictures {
- println("正在获取章节的图片 " + downloadingComic.Title + " " + ep.Title)
- // 搜索图片地址, 如果五次没有请求成功, 就不在请求
- for i := 0; i < 5; i++ {
- if client.Token == "" {
- continue
- }
- err := downloadFetchPictures(&ep)
- if err != nil {
- println(err.Error())
- continue
- }
- ep.FetchedPictures = true
- break
- }
- // 如果未能获取图片地址, 则直接置为失败
- if !ep.FetchedPictures {
- println("章节的图片获取失败 " + downloadingComic.Title + " " + ep.Title)
- err = comic_center2.EpFailed(ep.ID)
- if err != nil {
- panic(err)
- }
- } else {
- println("章节的图片获取成功 " + downloadingComic.Title + " " + ep.Title)
- downloadingComic.SelectedPictureCount = downloadingComic.SelectedPictureCount + ep.SelectedPictureCount
- downloadComicEventSend(downloadingComic)
- }
- }
- }
- // 获取图片地址结束, 去初始化下载的章节
- go downloadLoadEp()
-}
-
-// 获取图片地址
-func downloadFetchPictures(downloadEp *comic_center2.ComicDownloadEp) error {
- var list []comic_center2.ComicDownloadPicture
- // 官方的图片只能分页获取, 从第1页开始获取, 每页最多40张图片
- page := 1
- for true {
- rsp, err := client.ComicPicturePage(downloadingComic.ID, int(downloadEp.EpOrder), page)
- if err != nil {
- return err
- }
- for _, doc := range rsp.Docs {
- list = append(list, comic_center2.ComicDownloadPicture{
- ID: doc.Id,
- ComicId: downloadEp.ComicId,
- EpId: downloadEp.ID,
- EpOrder: downloadEp.EpOrder,
- OriginalName: doc.Media.OriginalName,
- FileServer: doc.Media.FileServer,
- Path: doc.Media.Path,
- })
- }
- // 如果不是最后一页, 页码加1, 获取下一页
- if rsp.Page < rsp.Pages {
- page++
- continue
- }
- break
- }
- // 保存获取到的图片
- err := comic_center2.FetchPictures(downloadEp.ComicId, downloadEp.ID, &list)
- if err != nil {
- panic(err)
- }
- downloadEp.SelectedPictureCount = int32(len(list))
- return err
-}
-
-// 初始化下载
-func downloadLoadEp() {
- // 周期停止检测
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 找到第一个需要下载的章节并去处理 (未下载失败的, 且未完成下载的)
- var err error
- downloadingEp, err = comic_center2.LoadFirstNeedDownloadEp(downloadingComic.ID)
- if err != nil {
- panic(err)
- }
- go downloadInitEp()
-}
-
-// 处理需要下载的EP
-func downloadInitEp() {
- if downloadingEp == nil {
- // 所有Ep都下完了, 汇总Download下载情况
- go downloadSummaryDownload()
- return
- }
- // 没有下载完则去下载图片
- println("正在下载章节 " + downloadingEp.Title)
- go downloadLoadPicture()
-}
-
-// EP下载汇总
-func downloadSummaryDownload() {
- // 暂停检测
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 加载这个漫画的所有EP
- list, err := comic_center2.ListDownloadEpByComicId(downloadingComic.ID)
- if err != nil {
- panic(err)
- }
- // 判断所有章节是否下载完成
- over := true
- for _, downloadEp := range list {
- over = over && downloadEp.DownloadFinished
- }
- if over {
- // 如果所有章节下载完成则下载成功
- downloadAndExportLogo(downloadingComic)
- err = comic_center2.DownloadSuccess(downloadingComic.ID)
- if err != nil {
- panic(err)
- }
- downloadingComic.DownloadFinished = true
- downloadingComic.DownloadFinishedTime = time.Now()
- } else {
- // 否则下载失败
- err = comic_center2.DownloadFailed(downloadingComic.ID)
- if err != nil {
- panic(err)
- }
- downloadingComic.DownloadFailed = true
- }
- // 向前端发送下载状态
- downloadComicEventSend(downloadingComic)
- // 去下载下一个漫画
- go downloadLoadComic()
-}
-
-// 加载需要下载的图片
-func downloadLoadPicture() {
- // 暂停检测
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 获取到这个章节需要下载的图片
- downloadingPictures, err := comic_center2.LoadNeedDownloadPictures(downloadingEp.ID, downloadThreadFetch)
- if err != nil {
- panic(err)
- }
- // 如果不需要下载
- if len(*downloadingPictures) == 0 {
- // 所有图片都下完了, 汇总EP下载情况
- go downloadSummaryEp()
- return
- }
- // 线程池
- channel := make(chan int, downloadThreadCount)
- defer close(channel)
- wg := sync.WaitGroup{}
- for i := 0; i < len(*downloadingPictures); i++ {
- // 暂停检测
- if downloadHasStop() {
- wg.Wait()
- go downloadBegin()
- return
- }
- channel <- 0
- wg.Add(1)
- // 不放入携程, 防止i已经变化
- picPoint := &((*downloadingPictures)[i])
- go func() {
- downloadPicture(picPoint)
- <-channel
- wg.Done()
- }()
- }
- wg.Wait()
- // 再次新一轮的下载, 直至 len(*downloadingPictures) == 0
- go downloadLoadPicture()
-}
-
-var downloadEventChannelMutex = sync.Mutex{}
-
-// 这里不能使用暂停检测, 多次检测会导致问题
-func downloadPicture(downloadingPicture *comic_center2.ComicDownloadPicture) {
- // 下载图片, 最多重试5次
- println("正在下载图片 " + fmt.Sprintf("%d", downloadingPicture.RankInEp))
- for i := 0; i < 5; i++ {
- err := downloadThePicture(downloadingPicture)
- if err != nil {
- continue
- }
- func() {
- downloadEventChannelMutex.Lock()
- defer downloadEventChannelMutex.Unlock()
- // 对下载的漫画临时变量热更新并通知前端
- downloadingPicture.DownloadFinished = true
- downloadingEp.DownloadPictureCount = downloadingEp.DownloadPictureCount + 1
- downloadingComic.DownloadPictureCount = downloadingComic.DownloadPictureCount + 1
- downloadComicEventSend(downloadingComic)
- }()
- break
- }
- // 没能下载成功, 图片置为下载失败
- if !downloadingPicture.DownloadFinished {
- err := comic_center2.PictureFailed(downloadingPicture.ID)
- if err != nil {
- // ??? panic X channel ???
- // panic(err)
- }
- }
-}
-
-// 下载指定图片
-func downloadThePicture(picturePoint *comic_center2.ComicDownloadPicture) error {
- // 为了不和页面前端浏览的数据冲突, 使用url做hash锁
- lock := utils2.HashLock(fmt.Sprintf("%s$%s", picturePoint.FileServer, picturePoint.Path))
- lock.Lock()
- defer lock.Unlock()
- // 图片保存位置使用相对路径储存, 使用绝对路径操作
- picturePath := fmt.Sprintf("%s/%d/%d", picturePoint.ComicId, picturePoint.EpOrder, picturePoint.RankInEp)
- realPath := downloadPath(picturePath)
- // 从缓存获取图片
- buff, img, format, err := decodeFromCache(picturePoint.FileServer, picturePoint.Path)
- if err != nil {
- // 若缓存不存在, 则从网络获取
- buff, img, format, err = decodeFromUrl(picturePoint.FileServer, picturePoint.Path)
- }
- if err != nil {
- return err
- }
- // 将图片保存到文件
- dir := filepath.Dir(realPath)
- if _, err := os.Stat(dir); os.IsNotExist(err) {
- os.Mkdir(dir, utils2.CreateDirMode)
- }
- err = ioutil.WriteFile(downloadPath(picturePath), buff, utils2.CreateFileMode)
- if err != nil {
- return err
- }
- // 下载时同时导出
- downloadAndExport(downloadingComic, downloadingEp, picturePoint, buff, format)
- // 存入数据库
- return comic_center2.PictureSuccess(
- picturePoint.ComicId,
- picturePoint.EpId,
- picturePoint.ID,
- int64(len(buff)),
- format,
- int32(img.Bounds().Dx()),
- int32(img.Bounds().Dy()),
- picturePath,
- )
-}
-
-// EP 下载内容汇总
-func downloadSummaryEp() {
- // 暂停检测
- if downloadHasStop() {
- go downloadBegin()
- return
- }
- // 找到所有下载的图片
- list, err := comic_center2.ListDownloadPictureByEpId(downloadingEp.ID)
- if err != nil {
- panic(err)
- }
- // 全部下载完成置为成功, 否则置为失败
- over := true
- for _, downloadPicture := range list {
- over = over && downloadPicture.DownloadFinished
- }
- if over {
- err = comic_center2.EpSuccess(downloadingEp.ComicId, downloadingEp.ID)
- if err != nil {
- panic(err)
- }
- } else {
- err = comic_center2.EpFailed(downloadingEp.ID)
- if err != nil {
- panic(err)
- }
- }
- // 去加载下一个EP
- go downloadLoadEp()
-}
-
-// 边下载边导出(导出路径)
-var downloadAndExportPath = ""
-
-// 边下载边导出(导出图片)
-func downloadAndExport(
- downloadingComic *comic_center2.ComicDownload,
- downloadingEp *comic_center2.ComicDownloadEp,
- downloadingPicture *comic_center2.ComicDownloadPicture,
- buff []byte,
- format string,
-) {
- if downloadAndExportPath == "" {
- return
- }
- if i, e := os.Stat(downloadAndExportPath); e == nil {
- if i.IsDir() {
- // 进入漫画目录
- comicDir := path.Join(downloadAndExportPath, utils2.ReasonableFileName(downloadingComic.Title))
- i, e = os.Stat(comicDir)
- if e != nil {
- if os.IsNotExist(e) {
- e = os.Mkdir(comicDir, utils2.CreateDirMode)
- } else {
- return
- }
- }
- if e != nil {
- return
- }
- // 进入章节目录
- epDir := path.Join(comicDir, utils2.ReasonableFileName(fmt.Sprintf("%02d - ", downloadingEp.EpOrder)+downloadingEp.Title))
- i, e = os.Stat(epDir)
- if e != nil {
- if os.IsNotExist(e) {
- e = os.Mkdir(epDir, utils2.CreateDirMode)
- } else {
- return
- }
- }
- if e != nil {
- return
- }
- // 写入文件
- filePath := path.Join(epDir, fmt.Sprintf("%03d.%s", downloadingPicture.RankInEp, aliasFormat(format)))
- ioutil.WriteFile(filePath, buff, utils2.CreateFileMode)
- }
- }
-}
-
-// 边下载边导出(导出logo)
-func downloadAndExportLogo(
- downloadingComic *comic_center2.ComicDownload,
-) {
- if downloadAndExportPath == "" {
- return
- }
- comicLogoPath := downloadPath(path.Join(downloadingComic.ID, "logo"))
- if _, e := os.Stat(comicLogoPath); e == nil {
- buff, e := ioutil.ReadFile(comicLogoPath)
- if e == nil {
- _, f, e := image.Decode(bytes.NewBuffer(buff))
- if e == nil {
- if i, e := os.Stat(downloadAndExportPath); e == nil {
- if i.IsDir() {
- // 进入漫画目录
- comicDir := path.Join(downloadAndExportPath, utils2.ReasonableFileName(downloadingComic.Title))
- i, e = os.Stat(comicDir)
- if e != nil {
- if os.IsNotExist(e) {
- e = os.Mkdir(comicDir, utils2.CreateDirMode)
- }
- }
- if e != nil {
- return
- }
- // 写入文件
- filePath := path.Join(comicDir, fmt.Sprintf("%s.%s", "logo", aliasFormat(f)))
- ioutil.WriteFile(filePath, buff, utils2.CreateFileMode)
- }
- }
- }
- }
- }
-}
-
-// jpeg的拓展名
-func aliasFormat(format string) string {
- if format == "jpeg" {
- return "jpg"
- }
- return format
-}
diff --git a/go/pikapika/export.go b/go/pikapika/export.go
deleted file mode 100644
index 231d632..0000000
--- a/go/pikapika/export.go
+++ /dev/null
@@ -1,510 +0,0 @@
-package pikapika
-
-import (
- "archive/tar"
- "archive/zip"
- "compress/gzip"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "os"
- "path"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/utils"
- "strings"
- "time"
-)
-
-// 通过局域网导出
-
-var exportingListener net.Listener
-var exportingConn net.Conn
-
-func exportComicUsingSocket(comicId string) (int, error) {
- var err error
- exportingListener, err = net.Listen("tcp", ":0")
- if err != nil {
- return 0, err
- }
- go handleExportingConn(comicId)
- return exportingListener.Addr().(*net.TCPAddr).Port, nil
-}
-
-func handleExportingConn(comicId string) {
- defer exportingListener.Close()
- var err error
- exportingConn, err = exportingListener.Accept()
- if err != nil {
- notifyExport(fmt.Sprintf("导出失败"))
- println(err.Error())
- return
- }
- defer exportingConn.Close()
- gw := gzip.NewWriter(exportingConn)
- defer gw.Close()
- tw := tar.NewWriter(gw)
- defer tw.Close()
- err = exportComicDownloadFetch(comicId, func(path string, size int64) (io.Writer, error) {
- header := tar.Header{}
- header.Name = path
- header.Size = size
- return tw, tw.WriteHeader(&header)
- })
- if err != nil {
- notifyExport(fmt.Sprintf("导出失败"))
- } else {
- notifyExport(fmt.Sprintf("导出成功"))
- }
-}
-
-func exportComicUsingSocketExit() error {
- if exportingConn != nil {
- exportingConn.Close()
- }
- if exportingListener != nil {
- exportingListener.Close()
- }
- return nil
-}
-
-func exportComicDownload(params string) (filePath string, err error) {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- Dir string `json:"dir"`
- Name string `json:"name"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comicId := paramsStruct.ComicId
- dir := paramsStruct.Dir
- println(fmt.Sprintf("导出 %s 到 %s", comicId, dir))
- comic, err := comic_center.FindComicDownloadById(comicId)
- if err != nil {
- return
- }
- if comic == nil {
- err = errors.New("not found")
- return
- }
- if !comic.DownloadFinished {
- err = errors.New("not download finish")
- return
- }
- name := strings.TrimSpace(paramsStruct.Name)
- if len(name) > 0 {
- name = utils.ReasonableFileName(name) + ".zip"
- } else {
- name = fmt.Sprintf("%s-%s.zip", utils.ReasonableFileName(comic.Title), time.Now().Format("2006_01_02_15_04_05.999"))
- }
- filePath = path.Join(dir, name)
- ex, err := utils.Exists(filePath)
- if err != nil {
- return "", err
- }
- if ex {
- err = errors.New("exists")
- return
- }
- println(fmt.Sprintf("ZIP : %s", filePath))
- fileStream, err := os.Create(filePath)
- if err != nil {
- return
- }
- defer fileStream.Close()
- zipWriter := zip.NewWriter(fileStream)
- defer zipWriter.Close()
- err = exportComicDownloadFetch(comicId, func(path string, size int64) (io.Writer, error) {
- header := tar.Header{}
- header.Name = path
- header.Size = size
- return zipWriter.Create(path)
- })
- return
-}
-
-func exportComicDownloadFetch(comicId string, onWriteFile func(path string, size int64) (io.Writer, error)) error {
- comic, err := comic_center.FindComicDownloadById(comicId)
- if err != nil {
- return err
- }
- if comic == nil {
- return errors.New("not found")
- }
- if !comic.DownloadFinished {
- return errors.New("not download finish")
- }
- epList, err := comic_center.ListDownloadEpByComicId(comicId)
- if err != nil {
- return err
- }
- jsonComic := JsonComicDownload{}
- jsonComic.ComicDownload = *comic
- jsonComic.EpList = make([]JsonComicDownloadEp, 0)
- for _, ep := range epList {
- jsonEp := JsonComicDownloadEp{}
- jsonEp.ComicDownloadEp = ep
- jsonEp.PictureList = make([]JsonComicDownloadPicture, 0)
- pictures, err := comic_center.ListDownloadPictureByEpId(ep.ID)
- if err != nil {
- return err
- }
- for _, picture := range pictures {
- jsonPicture := JsonComicDownloadPicture{}
- jsonPicture.ComicDownloadPicture = picture
- jsonPicture.SrcPath = fmt.Sprintf("pictures/%04d_%04d", ep.EpOrder, picture.RankInEp)
- notifyExport(fmt.Sprintf("正在导出 EP:%d PIC:%d", ep.EpOrder, picture.RankInEp))
- entryWriter, err := onWriteFile(jsonPicture.SrcPath, jsonPicture.FileSize)
- if err != nil {
- return err
- }
- source, err := os.Open(downloadPath(picture.LocalPath))
- if err != nil {
- return err
- }
- _, err = func() (int64, error) {
- defer source.Close()
- return io.Copy(entryWriter, source)
- }()
- if err != nil {
- return err
- }
- jsonEp.PictureList = append(jsonEp.PictureList, jsonPicture)
- }
- jsonComic.EpList = append(jsonComic.EpList, jsonEp)
- }
- if comic.ThumbLocalPath != "" {
- logoBuff, err := ioutil.ReadFile(downloadPath(comic.ThumbLocalPath))
- if err == nil {
- entryWriter, err := onWriteFile("logo", int64(len(logoBuff)))
- if err != nil {
- return err
- }
- _, err = entryWriter.Write(logoBuff)
- if err != nil {
- return err
- }
- }
- }
- // JS
- {
- buff, err := json.Marshal(&jsonComic)
- if err != nil {
- return err
- }
- logoBuff := append([]byte("data = "), buff...)
- if err == nil {
- entryWriter, err := onWriteFile("data.js", int64(len(logoBuff)))
- if err != nil {
- return err
- }
- _, err = entryWriter.Write(logoBuff)
- if err != nil {
- return err
- }
- }
- }
- // HTML
- {
- var htmlBuff = []byte(indexHtml)
- if err == nil {
- entryWriter, err := onWriteFile("index.html", int64(len(htmlBuff)))
- if err != nil {
- return err
- }
- _, err = entryWriter.Write(htmlBuff)
- if err != nil {
- return err
- }
- }
- }
- println("OK")
- //
- return nil
-}
-
-const indexHtml = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`
-
-func exportComicDownloadToJPG(params string) error {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- Dir string `json:"dir"`
- Name string `json:"name"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comicId := paramsStruct.ComicId
- dir := paramsStruct.Dir
- println(fmt.Sprintf("导出 %s 到 %s", comicId, dir))
- comic, err := comic_center.FindComicDownloadById(comicId)
- if err != nil {
- return err
- }
- if comic == nil {
- return errors.New("not found")
- }
- if !comic.DownloadFinished {
- return errors.New("not download finish")
- }
- name := strings.TrimSpace(paramsStruct.Name)
- if len(name) > 0 {
- name = utils.ReasonableFileName(name)
- } else {
- name = fmt.Sprintf("%s-%s", utils.ReasonableFileName(comic.Title), time.Now().Format("2006_01_02_15_04_05.999"))
- }
- dirPath := path.Join(dir, name)
- println(fmt.Sprintf("DIR : %s", dirPath))
- ex, err := utils.Exists(dirPath)
- if err != nil {
- return err
- }
- if ex {
- return errors.New("exists")
- }
- err = os.Mkdir(dirPath, utils.CreateDirMode)
- if err != nil {
- return err
- }
- err = os.Mkdir(path.Join(dirPath, "pictures"), utils.CreateDirMode)
- if err != nil {
- return err
- }
-
- epList, err := comic_center.ListDownloadEpByComicId(comicId)
- if err != nil {
- return err
- }
- jsonComic := JsonComicDownload{}
- jsonComic.ComicDownload = *comic
- jsonComic.EpList = make([]JsonComicDownloadEp, 0)
- for _, ep := range epList {
- jsonEp := JsonComicDownloadEp{}
- jsonEp.ComicDownloadEp = ep
- jsonEp.PictureList = make([]JsonComicDownloadPicture, 0)
- pictures, err := comic_center.ListDownloadPictureByEpId(ep.ID)
- if err != nil {
- return err
- }
- for _, picture := range pictures {
- jsonPicture := JsonComicDownloadPicture{}
- jsonPicture.ComicDownloadPicture = picture
- jsonPicture.SrcPath = fmt.Sprintf("pictures/%04d_%04d.%s", ep.EpOrder, picture.RankInEp, picture.Format)
- notifyExport(fmt.Sprintf("正在导出 EP:%d PIC:%d", ep.EpOrder, picture.RankInEp))
- entryWriter, err := os.Create(path.Join(dirPath, jsonPicture.SrcPath))
- if err != nil {
- return err
- }
- err = func() error {
- defer entryWriter.Close()
- source, err := os.Open(downloadPath(picture.LocalPath))
- if err != nil {
- return err
- }
- _, err = func() (int64, error) {
- defer source.Close()
- return io.Copy(entryWriter, source)
- }()
- return err
- }()
- jsonEp.PictureList = append(jsonEp.PictureList, jsonPicture)
- }
- jsonComic.EpList = append(jsonComic.EpList, jsonEp)
- }
- if comic.ThumbLocalPath != "" {
- logoBuff, err := ioutil.ReadFile(downloadPath(comic.ThumbLocalPath))
- if err == nil {
- entryWriter, err := os.Create(path.Join(dirPath, "logo"))
- if err != nil {
- return err
- }
- defer entryWriter.Close()
- if err != nil {
- return err
- }
- _, err = entryWriter.Write(logoBuff)
- if err != nil {
- return err
- }
- }
- }
- // JS
- {
- buff, err := json.Marshal(&jsonComic)
- if err != nil {
- return err
- }
- logoBuff := append([]byte("data = "), buff...)
- if err == nil {
-
- entryWriter, err := os.Create(path.Join(dirPath, "data.js"))
- if err != nil {
- return err
- }
- defer entryWriter.Close()
- _, err = entryWriter.Write(logoBuff)
- if err != nil {
- return err
- }
- }
- }
- // HTML
- {
- var htmlBuff = []byte(indexHtml)
- if err == nil {
- entryWriter, err := os.Create(path.Join(dirPath, "index.html"))
- if err != nil {
- return err
- }
- defer entryWriter.Close()
- _, err = entryWriter.Write(htmlBuff)
- if err != nil {
- return err
- }
- }
- }
- println("OK")
- return nil
-}
diff --git a/go/pikapika/game.go b/go/pikapika/game.go
deleted file mode 100644
index e064d43..0000000
--- a/go/pikapika/game.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package pikapika
-
-import (
- "errors"
- "fmt"
- "github.com/PuerkitoBio/goquery"
- "net/http"
- "regexp"
- "time"
-)
-
-var downloadGameUrlPattern, _ = regexp.Compile("^https://game\\.eroge\\.xyz/hhh\\.php\\?id=\\d+$")
-
-func downloadGame(url string) (string, error) {
- if downloadGameUrlPattern.MatchString(url) {
- return cacheable(fmt.Sprintf("GAME_PAGE$%s", url), time.Hour*1000, func() (interface{}, error) {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
- req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36")
- rsp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
- defer rsp.Body.Close()
- doc, err := goquery.NewDocumentFromReader(rsp.Body)
- if err != nil {
- return nil, err
- }
- find := doc.Find("a.layui-btn")
- list := make([]string, find.Size())
- find.Each(func(i int, selection *goquery.Selection) {
- list[i] = selection.AttrOr("href", "")
- })
- return list, nil
- })
- }
- return "", errors.New("not support url")
-}
diff --git a/go/pikapika/image.go b/go/pikapika/image.go
deleted file mode 100644
index 6a34b08..0000000
--- a/go/pikapika/image.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package pikapika
-
-import (
- "bytes"
- "context"
- "errors"
- _ "golang.org/x/image/webp"
- "image"
- _ "image/gif"
- _ "image/jpeg"
- _ "image/png"
- "io/ioutil"
- "net"
- "net/http"
- "pikapika/pikapika/database/comic_center"
- "sync"
- "time"
-)
-
-var mutexCounter = -1
-var busMutex *sync.Mutex
-var subMutexes []*sync.Mutex
-var imageHttpClient *http.Client
-
-// imageSwitchAddress
-// 图片的分流直接使用 switchAddressPattern 可以正常使用
-// 通过ping发现图片的分流地址与ip一致
-// 这里为了域名与官方一致改为域名分流
-var imageSwitchAddresses = map[int]string{
- 1: "https://storage.wika" + "wika.xyz",
- 2: "https://s2.pica" + "comic.com",
- 3: "https://s3.pica" + "comic.com",
-}
-
-var imageSwitchAddress int
-
-func init() {
- busMutex = &sync.Mutex{}
- for i := 0; i < 5; i++ {
- subMutexes = append(subMutexes, &sync.Mutex{})
- }
- imageHttpClient = &http.Client{
- Transport: &http.Transport{
- TLSHandshakeTimeout: time.Second * 10,
- ExpectContinueTimeout: time.Second * 10,
- ResponseHeaderTimeout: time.Second * 10,
- IdleConnTimeout: time.Second * 10,
- DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
- return dialer.DialContext(ctx, network, addr)
- },
- },
- }
-}
-
-// takeMutex 下载图片获取一个锁, 这样只能同时下载5张图片
-func takeMutex() *sync.Mutex {
- busMutex.Lock()
- defer busMutex.Unlock()
- mutexCounter = (mutexCounter + 1) % len(subMutexes)
- return subMutexes[mutexCounter]
-}
-
-func decodeInfoFromBuff(buff []byte) (image.Image, string, error) {
- buffer := bytes.NewBuffer(buff)
- return image.Decode(buffer)
-}
-
-func decodeFromFile(path string) ([]byte, image.Image, string, error) {
- b, e := ioutil.ReadFile(path)
- if e != nil {
- return nil, nil, "", e
- }
- i, f, e := decodeInfoFromBuff(b)
- if e != nil {
- return nil, nil, "", e
- }
- return b, i, f, e
-}
-
-// 下载图片并decode
-func decodeFromUrl(fileServer string, path string) ([]byte, image.Image, string, error) {
- useClient := imageHttpClient
- if imageSwitchAddress == -1 {
- useClient = &client.Client
- }
- if server, ok := imageSwitchAddresses[imageSwitchAddress]; ok {
- fileServer = server
- }
- m := takeMutex()
- m.Lock()
- defer m.Unlock()
- request, err := http.NewRequest("GET", fileServer+"/static/"+path, nil)
- if err != nil {
- return nil, nil, "", err
- }
- response, err := useClient.Do(request)
- if err != nil {
- return nil, nil, "", err
- }
- defer response.Body.Close()
- if response.StatusCode != 200 {
- return nil, nil, "", errors.New("code is not 200")
- }
- buff, err := ioutil.ReadAll(response.Body)
- if err != nil {
- return nil, nil, "", err
- }
- img, format, err := decodeInfoFromBuff(buff)
- if err != nil {
- return nil, nil, "", err
- }
- return buff, img, format, err
-}
-
-// decodeFromCache 仅下载使用
-func decodeFromCache(fileServer string, path string) ([]byte, image.Image, string, error) {
- cache := comic_center.FindRemoteImage(fileServer, path)
- if cache != nil {
- buff, err := ioutil.ReadFile(remotePath(cache.LocalPath))
- if err != nil {
- return nil, nil, "", err
- }
- img, format, err := decodeInfoFromBuff(buff)
- if err != nil {
- return nil, nil, "", err
- }
- return buff, img, format, err
- }
- return nil, nil, "", errors.New("not found")
-}
diff --git a/go/pikapika/import.go b/go/pikapika/import.go
deleted file mode 100644
index d6d35a2..0000000
--- a/go/pikapika/import.go
+++ /dev/null
@@ -1,196 +0,0 @@
-package pikapika
-
-import (
- "archive/tar"
- "archive/zip"
- "compress/gzip"
- "encoding/json"
- "gorm.io/gorm"
- "io"
- "io/ioutil"
- "net"
- "os"
- path2 "path"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/utils"
- "strconv"
- "strings"
-)
-
-func importComicDownloadUsingSocket(addr string) error {
- //
- conn, err := net.Dial("tcp", addr)
- if err != nil {
- return err
- }
- defer conn.Close()
- gr, err := gzip.NewReader(conn)
- if err != nil {
- return err
- }
- tr := tar.NewReader(gr)
- //
- zipPath := path2.Join(tmpDir, "tmp.zip")
- closed := false
- zipFile, err := os.Create(zipPath)
- if err != nil {
- return err
- }
- defer func() {
- if !closed {
- zipFile.Close()
- }
- os.Remove(zipPath)
- }()
- zipWriter := zip.NewWriter(zipFile)
- defer func() {
- if !closed {
- zipWriter.Close()
- }
- }()
- //
- for {
- header, err := tr.Next()
- if err == io.EOF {
- break
- }
- if err != nil {
- return err
- }
- if header.Typeflag != tar.TypeReg {
- continue
- }
- writer, err := zipWriter.Create(header.Name)
- if err != nil {
- return err
- }
- _, err = io.Copy(writer, tr)
- if err != nil {
- return err
- }
- }
- err = zipWriter.Close()
- zipFile.Close()
- closed = true
- return importComicDownload(zipPath)
-}
-
-func importComicDownload(zipPath string) error {
- zip, err := zip.OpenReader(zipPath)
- if err != nil {
- return err
- }
- defer zip.Close()
- dataJs, err := zip.Open("data.js")
- if err != nil {
- return err
- }
- defer dataJs.Close()
- dataBuff, err := ioutil.ReadAll(dataJs)
- if err != nil {
- return err
- }
- data := strings.TrimLeft(string(dataBuff), "data = ")
- var jsonComicDownload JsonComicDownload
- err = json.Unmarshal([]byte(data), &jsonComicDownload)
- if err != nil {
- return err
- }
- return comic_center.Transaction(func(tx *gorm.DB) error {
- // 删除
- err := tx.Unscoped().Delete(&comic_center.ComicDownload{}, "id = ?", jsonComicDownload.ID).Error
- if err != nil {
- return err
- }
- err = tx.Unscoped().Delete(&comic_center.ComicDownloadEp{}, "comic_id = ?", jsonComicDownload.ID).Error
- if err != nil {
- return err
- }
- err = tx.Unscoped().Delete(&comic_center.ComicDownloadPicture{}, "comic_id = ?", jsonComicDownload.ID).Error
- if err != nil {
- return err
- }
- // 插入
- err = tx.Save(&jsonComicDownload.ComicDownload).Error
- if err != nil {
- return err
- }
- for _, ep := range jsonComicDownload.EpList {
- err = tx.Save(&ep.ComicDownloadEp).Error
- if err != nil {
- return err
- }
- for _, picture := range ep.PictureList {
- notifyExport("事务 : " + picture.LocalPath)
- err = tx.Save(&picture.ComicDownloadPicture).Error
- if err != nil {
- return err
- }
- }
- }
- // VIEW日志
- view := comic_center.ComicView{}
- view.ID = jsonComicDownload.ID
- view.CreatedAt = jsonComicDownload.CreatedAt
- view.UpdatedAt = jsonComicDownload.UpdatedAt
- view.Title = jsonComicDownload.Title
- view.Author = jsonComicDownload.Author
- view.PagesCount = jsonComicDownload.PagesCount
- view.EpsCount = jsonComicDownload.EpsCount
- view.Finished = jsonComicDownload.Finished
- c, _ := json.Marshal(jsonComicDownload.Categories)
- view.Categories = string(c)
- view.ThumbOriginalName = jsonComicDownload.ThumbOriginalName
- view.ThumbFileServer = jsonComicDownload.ThumbFileServer
- view.ThumbPath = jsonComicDownload.ThumbPath
- view.LikesCount = 0
- view.Description = jsonComicDownload.Description
- view.ChineseTeam = jsonComicDownload.ChineseTeam
- t, _ := json.Marshal(jsonComicDownload.Tags)
- view.Tags = string(t)
- view.AllowDownload = true
- view.ViewsCount = 0
- view.IsFavourite = false
- view.IsLiked = false
- view.CommentsCount = 0
- err = comic_center.NoLockActionViewComicUpdateInfoDB(&view, tx)
- if err != nil {
- return err
- }
- // 覆盖文件
- comicDirPath := downloadPath(jsonComicDownload.ID)
- utils.Mkdir(comicDirPath)
- logoReader, err := zip.Open("logo")
- if err == nil {
- defer logoReader.Close()
- logoBuff, err := ioutil.ReadAll(logoReader)
- if err != nil {
- return err
- }
- ioutil.WriteFile(path2.Join(comicDirPath, "logo"), logoBuff, utils.CreateFileMode)
- }
- for _, ep := range jsonComicDownload.EpList {
- utils.Mkdir(path2.Join(comicDirPath, strconv.Itoa(int(ep.EpOrder))))
- for _, picture := range ep.PictureList {
- notifyExport("写入 : " + picture.LocalPath)
- zipEntry, err := zip.Open(picture.SrcPath)
- if err != nil {
- return err
- }
- err = func() error {
- defer zipEntry.Close()
- entryBuff, err := ioutil.ReadAll(zipEntry)
- if err != nil {
- return err
- }
- return ioutil.WriteFile(downloadPath(picture.LocalPath), entryBuff, utils.CreateFileMode)
- }()
- if err != nil {
- return err
- }
- }
- }
- // 结束
- return nil
- })
-}
diff --git a/go/pikapika/modles.go b/go/pikapika/modles.go
deleted file mode 100644
index 8370be4..0000000
--- a/go/pikapika/modles.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package pikapika
-
-import (
- "pikapika/pikapika/database/comic_center"
-)
-
-type DisplayImageData struct {
- FileSize int64 `json:"fileSize"`
- Format string `json:"format"`
- Width int32 `json:"width"`
- Height int32 `json:"height"`
- FinalPath string `json:"finalPath"`
-}
-
-type ComicDownloadPictureWithFinalPath struct {
- comic_center.ComicDownloadPicture
- FinalPath string `json:"finalPath"`
-}
-
-type JsonComicDownload struct {
- comic_center.ComicDownload
- EpList []JsonComicDownloadEp `json:"epList"`
-}
-
-type JsonComicDownloadEp struct {
- comic_center.ComicDownloadEp
- PictureList []JsonComicDownloadPicture `json:"pictureList"`
-}
-
-type JsonComicDownloadPicture struct {
- comic_center.ComicDownloadPicture
- SrcPath string `json:"srcPath"`
-}
diff --git a/go/pikapika/network.go b/go/pikapika/network.go
deleted file mode 100644
index 892806c..0000000
--- a/go/pikapika/network.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package pikapika
-
-import (
- "net"
- "strings"
-)
-
-// 获取IP的集合
-func clientIpSet() (string, error) {
- address, err := net.InterfaceAddrs()
- if err != nil {
- return "", err
- }
- ipSet := make([]string, 0)
- for _, address := range address {
- // 检查ip地址判断是否回环地址
- if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
- if ipNet.IP.To4() != nil {
- ipSet = append(ipSet, ipNet.IP.To4().String())
- }
- }
- }
- return strings.Join(ipSet, ","), nil
-}
diff --git a/go/pikapika/pikapika.go b/go/pikapika/pikapika.go
deleted file mode 100644
index b1436de..0000000
--- a/go/pikapika/pikapika.go
+++ /dev/null
@@ -1,755 +0,0 @@
-package pikapika
-
-import (
- "crypto/md5"
- "encoding/json"
- "errors"
- "fmt"
- source "github.com/niuhuan/pica-go"
- "image/jpeg"
- "io/ioutil"
- "net/http"
- "os"
- path2 "path"
- "pikapika/pikapika/database/comic_center"
- "pikapika/pikapika/database/network_cache"
- "pikapika/pikapika/database/properties"
- "pikapika/pikapika/utils"
- "strconv"
- "time"
-)
-
-var (
- remoteDir string
- downloadDir string
- tmpDir string
-)
-
-var initFlag bool
-
-func InitPlugin(_remoteDir string, _downloadDir string, _tmpDir string) {
- if initFlag {
- return
- }
- initFlag = true
- remoteDir = _remoteDir
- downloadDir = _downloadDir
- tmpDir = _tmpDir
- comic_center.ResetAll()
- downloadAndExportPath = loadDownloadAndExportPath()
- downloadThreadCount = loadDownloadThreadCount()
- go downloadBackground()
- downloadRunning = true
-}
-
-func remotePath(path string) string {
- return path2.Join(remoteDir, path)
-}
-
-func downloadPath(path string) string {
- return path2.Join(downloadDir, path)
-}
-
-func saveProperty(params string) error {
- var paramsStruct struct {
- Name string `json:"name"`
- Value string `json:"value"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- return properties.SaveProperty(paramsStruct.Name, paramsStruct.Value)
-}
-
-func loadProperty(params string) (string, error) {
- var paramsStruct struct {
- Name string `json:"name"`
- DefaultValue string `json:"defaultValue"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- return properties.LoadProperty(paramsStruct.Name, paramsStruct.DefaultValue)
-}
-
-func saveDownloadAndExportPath(value string) error {
- err := properties.SaveProperty("downloadAndExportPath", value)
- if err == nil {
- downloadAndExportPath = value
- }
- return err
-}
-
-func loadDownloadAndExportPath() string {
- p, _ := properties.LoadProperty("downloadAndExportPath", "")
- return p
-}
-
-func saveDownloadThreadCount(value int) {
- strValue := strconv.Itoa(value)
- properties.SaveProperty("downloadThreadCount", strValue)
- downloadThreadCount = value
- downloadRestart = true
-}
-
-func loadDownloadThreadCount() int {
- count, err := properties.LoadProperty("downloadThreadCount", "2")
- if err != nil {
- return 1
- }
- i, err := strconv.Atoi(count)
- if err != nil {
- return 1
- }
- return i
-}
-
-func setSwitchAddress(nSwitchAddress string) error {
- num, err := strconv.Atoi(nSwitchAddress)
- if err != nil {
- return err
- }
- err = properties.SaveIntProperty("switchAddress", num)
- if err != nil {
- return err
- }
- switchAddress = num
- return nil
-}
-
-func getSwitchAddress() (string, error) {
- return strconv.Itoa(switchAddress), nil
-}
-
-func setImageSwitchAddress(nSwitchAddress string) error {
- num, err := strconv.Atoi(nSwitchAddress)
- if err != nil {
- return err
- }
- err = properties.SaveIntProperty("imageSwitchAddress", num)
- if err != nil {
- return err
- }
- switchAddress = num
- return nil
-}
-
-func getImageSwitchAddress() (string, error) {
- return strconv.Itoa(imageSwitchAddress), nil
-}
-
-func setProxy(value string) error {
- err := properties.SaveProxy(value)
- if err != nil {
- return err
- }
- changeProxyUrl(value)
- return nil
-}
-
-func getProxy() (string, error) {
- return properties.LoadProxy()
-}
-
-func setUsername(value string) error {
- return properties.SaveUsername(value)
-}
-
-func getUsername() (string, error) {
- return properties.LoadUsername()
-}
-
-func setPassword(value string) error {
- return properties.SavePassword(value)
-}
-
-func getPassword() (string, error) {
- return properties.LoadPassword()
-}
-
-func preLogin() (string, error) {
- token, _ := properties.LoadToken()
- tokenTime, _ := properties.LoadTokenTime()
- if token != "" && tokenTime > 0 {
- if utils.Timestamp()-(1000*60*60*24) < tokenTime {
- client.Token = token
- return "true", nil
- }
- }
- err := login()
- if err == nil {
- return "true", nil
- }
- return "false", nil
-}
-
-func login() error {
- username, _ := properties.LoadUsername()
- password, _ := properties.LoadPassword()
- if password == "" || username == "" {
- return errors.New(" 需要设定用户名和密码 ")
- }
- err := client.Login(username, password)
- if err != nil {
- return err
- }
- properties.SaveToken(client.Token)
- properties.SaveTokenTime(utils.Timestamp())
- return nil
-}
-
-func register(params string) error {
- var dto source.RegisterDto
- err := json.Unmarshal([]byte(params), &dto)
- if err != nil {
- return err
- }
- return client.Register(dto)
-}
-
-func clearToken() error {
- properties.SaveTokenTime(0)
- properties.SaveToken("")
- return nil
-}
-
-func remoteImageData(params string) (string, error) {
- var paramsStruct struct {
- FileServer string `json:"fileServer"`
- Path string `json:"path"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- fileServer := paramsStruct.FileServer
- path := paramsStruct.Path
- lock := utils.HashLock(fmt.Sprintf("%s$%s", fileServer, path))
- lock.Lock()
- defer lock.Unlock()
- cache := comic_center.FindRemoteImage(fileServer, path)
- if cache == nil {
- remote, err := decodeAndSaveImage(fileServer, path)
- if err != nil {
- return "", err
- }
- cache = remote
- } else {
- go comic_center.UpdateTimeCacheImageTime(cache.ID)
- }
- display := DisplayImageData{
- FileSize: cache.FileSize,
- Format: cache.Format,
- Width: cache.Width,
- Height: cache.Height,
- FinalPath: remotePath(cache.LocalPath),
- }
- return serialize(&display, nil)
-}
-
-func remoteImagePreload(params string) error {
- var paramsStruct struct {
- FileServer string `json:"fileServer"`
- Path string `json:"path"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- fileServer := paramsStruct.FileServer
- path := paramsStruct.Path
- lock := utils.HashLock(fmt.Sprintf("%s$%s", fileServer, path))
- lock.Lock()
- defer lock.Unlock()
- cache := comic_center.FindRemoteImage(fileServer, path)
- var err error
- if cache == nil {
- _, err = decodeAndSaveImage(fileServer, path)
- }
- return err
-}
-
-func decodeAndSaveImage(fileServer string, path string) (*comic_center.RemoteImage, error) {
- buff, img, format, err := decodeFromUrl(fileServer, path)
- if err != nil {
- println(fmt.Sprintf("decode error : %s/static/%s %s", fileServer, path, err.Error()))
- return nil, err
- }
- local :=
- fmt.Sprintf("%x",
- md5.Sum([]byte(fmt.Sprintf("%s$%s", fileServer, path))),
- )
- real := remotePath(local)
- err = ioutil.WriteFile(
- real,
- buff, os.FileMode(0600),
- )
- if err != nil {
- return nil, err
- }
- remote := comic_center.RemoteImage{
- FileServer: fileServer,
- Path: path,
- FileSize: int64(len(buff)),
- Format: format,
- Width: int32(img.Bounds().Dx()),
- Height: int32(img.Bounds().Dy()),
- LocalPath: local,
- }
- err = comic_center.SaveRemoteImage(&remote)
- return &remote, err
-}
-
-func downloadImagePath(path string) (string, error) {
- return downloadPath(path), nil
-}
-
-func createDownload(params string) error {
- var paramsStruct struct {
- Comic comic_center.ComicDownload `json:"comic"`
- EpList []comic_center.ComicDownloadEp `json:"epList"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comic := paramsStruct.Comic
- epList := paramsStruct.EpList
- if comic.Title == "" || len(epList) == 0 {
- return errors.New("params error")
- }
- err := comic_center.CreateDownload(&comic, &epList)
- if err != nil {
- return err
- }
- // 创建文件夹
- utils.Mkdir(downloadPath(comic.ID))
- // 复制图标
- downloadComicLogo(&comic)
- return nil
-}
-
-func downloadComicLogo(comic *comic_center.ComicDownload) {
- lock := utils.HashLock(fmt.Sprintf("%s$%s", comic.ThumbFileServer, comic.ThumbPath))
- lock.Lock()
- defer lock.Unlock()
- buff, image, format, err := decodeFromCache(comic.ThumbFileServer, comic.ThumbPath)
- if err != nil {
- buff, image, format, err = decodeFromUrl(comic.ThumbFileServer, comic.ThumbPath)
- }
- if err == nil {
- comicLogoPath := path2.Join(comic.ID, "logo")
- ioutil.WriteFile(downloadPath(comicLogoPath), buff, utils.CreateFileMode)
- comic_center.UpdateDownloadLogo(
- comic.ID,
- int64(len(buff)),
- format,
- int32(image.Bounds().Dx()),
- int32(image.Bounds().Dy()),
- comicLogoPath,
- )
- comic.ThumbFileSize = int64(len(buff))
- comic.ThumbFormat = format
- comic.ThumbWidth = int32(image.Bounds().Dx())
- comic.ThumbHeight = int32(image.Bounds().Dy())
- comic.ThumbLocalPath = comicLogoPath
- }
- if err != nil {
- println(err.Error())
- }
-}
-
-func addDownload(params string) error {
- var paramsStruct struct {
- Comic comic_center.ComicDownload `json:"comic"`
- EpList []comic_center.ComicDownloadEp `json:"epList"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- comic := paramsStruct.Comic
- epList := paramsStruct.EpList
- if comic.Title == "" || len(epList) == 0 {
- return errors.New("params error")
- }
- return comic_center.AddDownload(&comic, &epList)
-}
-
-func deleteDownloadComic(comicId string) error {
- err := comic_center.Deleting(comicId)
- if err != nil {
- return err
- }
- downloadRestart = true
- return nil
-}
-
-func loadDownloadComic(comicId string) (string, error) {
- download, err := comic_center.FindComicDownloadById(comicId)
- if err != nil {
- return "", err
- }
- if download == nil {
- return "", nil
- }
- comic_center.ViewComic(comicId) // VIEW
- return serialize(download, err)
-}
-
-func allDownloads() (string, error) {
- return serialize(comic_center.AllDownloads())
-}
-
-func downloadEpList(comicId string) (string, error) {
- return serialize(comic_center.ListDownloadEpByComicId(comicId))
-}
-
-func viewLogPage(params string) (string, error) {
- var paramsStruct struct {
- Offset int `json:"offset"`
- Limit int `json:"limit"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- return serialize(comic_center.ViewLogPage(paramsStruct.Offset, paramsStruct.Limit))
-}
-
-func downloadPicturesByEpId(epId string) (string, error) {
- return serialize(comic_center.ListDownloadPictureByEpId(epId))
-}
-
-func getDownloadRunning() bool {
- return downloadRunning
-}
-
-func setDownloadRunning(status bool) {
- downloadRunning = status
-}
-
-func cleanNetworkCache() error {
- err := network_cache.RemoveAll()
- if err != nil {
- return err
- }
- notifyExport("清理结束")
- return nil
-}
-
-func cleanImageCache() error {
- notifyExport("清理图片缓存")
- err := comic_center.RemoveAllRemoteImage()
- if err != nil {
- return err
- }
- notifyExport("清理图片文件")
- os.RemoveAll(remoteDir)
- utils.Mkdir(remoteDir)
- notifyExport("清理结束")
- return nil
-}
-
-func clean() error {
- var err error
- notifyExport("清理网络缓存")
- err = network_cache.RemoveAll()
- if err != nil {
- return err
- }
- notifyExport("清理图片缓存")
- err = comic_center.RemoveAllRemoteImage()
- if err != nil {
- return err
- }
- notifyExport("清理图片文件")
- os.RemoveAll(remoteDir)
- utils.Mkdir(remoteDir)
- notifyExport("清理结束")
- return nil
-}
-
-func autoClean(expire int64) error {
- now := time.Now()
- earliest := now.Add(time.Second * time.Duration(0-expire))
- err := network_cache.RemoveEarliest(earliest)
- if err != nil {
- return err
- }
- pageSize := 10
- for true {
- images, err := comic_center.EarliestRemoteImage(earliest, pageSize)
- if err != nil {
- return err
- }
- if len(images) == 0 {
- return comic_center.VACUUM()
- }
- // delete data & remove pic
- err = comic_center.DeleteRemoteImages(images)
- if err != nil {
- return err
- }
- for i := 0; i < len(images); i++ {
- err = os.Remove(remotePath(images[i].LocalPath))
- if err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func storeViewEp(params string) error {
- var paramsStruct struct {
- ComicId string `json:"comicId"`
- EpOrder int `json:"epOrder"`
- EpTitle string `json:"epTitle"`
- PictureRank int `json:"pictureRank"`
- }
- json.Unmarshal([]byte(params), ¶msStruct)
- return comic_center.ViewEpAndPicture(
- paramsStruct.ComicId,
- paramsStruct.EpOrder,
- paramsStruct.EpTitle,
- paramsStruct.PictureRank,
- )
-}
-
-func loadView(comicId string) (string, error) {
- view, err := comic_center.LoadViewLog(comicId)
- if err != nil {
- return "", nil
- }
- if view != nil {
- b, err := json.Marshal(view)
- if err != nil {
- return "", err
- }
- return string(b), nil
- }
- return "", nil
-}
-
-func convertImageToJPEG100(params string) error {
- var paramsStruct struct {
- Path string `json:"path"`
- Dir string `json:"dir"`
- }
- err := json.Unmarshal([]byte(params), ¶msStruct)
- if err != nil {
- return err
- }
- _, i, _, err := decodeFromFile(paramsStruct.Path)
- if err != nil {
- return err
- }
- to := path2.Join(paramsStruct.Dir, path2.Base(paramsStruct.Path)+".jpg")
- stream, err := os.Create(to)
- if err != nil {
- return err
- }
- defer stream.Close()
- return jpeg.Encode(stream, i, &jpeg.Options{Quality: 100})
-}
-
-// 检查更新只能使用defaultHttpClient, 而不能使用pika的client, 否则会 "tls handshake failure"
-func defaultHttpClientGet(url string) (string, error) {
- rsp, err := http.DefaultClient.Get(url)
- if err != nil {
- return "", err
- }
- defer rsp.Body.Close()
- buff, err := ioutil.ReadAll(rsp.Body)
- if err != nil {
- return "", err
- }
- return string(buff), nil
-}
-
-func loadViewedList(params string) (string, error) {
- var ids []string
- err := json.Unmarshal([]byte(params), &ids)
- if err != nil {
- return "", err
- }
- viewedList := comic_center.ViewedList(ids)
- ids = make([]string, len(viewedList))
- for i, view := range viewedList {
- ids[i] = view.ID
- }
- return serialize(ids, nil)
-}
-
-func FlatInvoke(method string, params string) (string, error) {
- switch method {
- case "saveProperty":
- return "", saveProperty(params)
- case "loadProperty":
- return loadProperty(params)
- case "setSwitchAddress":
- return "", setSwitchAddress(params)
- case "getSwitchAddress":
- return getSwitchAddress()
- case "setImageSwitchAddress":
- return "", setImageSwitchAddress(params)
- case "getImageSwitchAddress":
- return getImageSwitchAddress()
- case "setProxy":
- return "", setProxy(params)
- case "getProxy":
- return getProxy()
- case "setUsername":
- return "", setUsername(params)
- case "setPassword":
- return "", setPassword(params)
- case "getUsername":
- return getUsername()
- case "getPassword":
- return getPassword()
- case "preLogin":
- return preLogin()
- case "login":
- return "", login()
- case "register":
- return "", register(params)
- case "clearToken":
- return "", clearToken()
- case "userProfile":
- return userProfile()
- case "punchIn":
- return punchIn()
- case "categories":
- return categories()
- case "comics":
- return comics(params)
- case "searchComics":
- return searchComics(params)
- case "randomComics":
- return randomComics()
- case "leaderboard":
- return leaderboard(params)
- case "comicInfo":
- return comicInfo(params)
- case "comicEpPage":
- return epPage(params)
- case "comicPicturePageWithQuality":
- return comicPicturePageWithQuality(params)
- case "switchLike":
- return switchLike(params)
- case "switchFavourite":
- return switchFavourite(params)
- case "favouriteComics":
- return favouriteComics(params)
- case "recommendation":
- return recommendation(params)
- case "comments":
- return comments(params)
- case "commentChildren":
- return commentChildren(params)
- case "myComments":
- return myComments(params)
- case "postComment":
- return postComment(params)
- case "postChildComment":
- return postChildComment(params)
- case "game":
- return game(params)
- case "games":
- return games(params)
- case "gameComments":
- return gameComments(params)
- case "postGameComment":
- return postGameComment(params)
- case "gameCommentChildren":
- return gameCommentChildren(params)
- case "switchLikeGameComment":
- return switchLikeGameComment(params)
- case "postGameChildComment":
- return postGameChildComment(params)
- case "viewLogPage":
- return viewLogPage(params)
- case "clearAllViewLog":
- comic_center.ClearAllViewLog()
- return "", nil
- case "deleteViewLog":
- comic_center.DeleteViewLog(params)
- return "", nil
- case "cleanNetworkCache":
- return "", cleanNetworkCache()
- case "cleanImageCache":
- return "", cleanImageCache()
- case "clean":
- return "", clean()
- case "autoClean":
- expire, err := strconv.ParseInt(params, 10, 64)
- if err != nil {
- return "", err
- }
- return "", autoClean(expire)
- case "storeViewEp":
- return "", storeViewEp(params)
- case "loadView":
- return loadView(params)
- case "downloadRunning":
- return strconv.FormatBool(getDownloadRunning()), nil
- case "setDownloadRunning":
- b, e := strconv.ParseBool(params)
- if e != nil {
- return "", e
- }
- setDownloadRunning(b)
- return "", nil
- case "createDownload":
- return "", createDownload(params)
- case "addDownload":
- return "", addDownload(params)
- case "loadDownloadComic":
- return loadDownloadComic(params)
- case "allDownloads":
- return allDownloads()
- case "deleteDownloadComic":
- return "", deleteDownloadComic(params)
- case "downloadEpList":
- return downloadEpList(params)
- case "downloadPicturesByEpId":
- return downloadPicturesByEpId(params)
- case "resetAllDownloads":
- return "", comic_center.ResetAll()
- case "exportComicDownload":
- return exportComicDownload(params)
- case "exportComicDownloadToJPG":
- return "", exportComicDownloadToJPG(params)
- case "exportComicUsingSocket":
- i, e := exportComicUsingSocket(params)
- return fmt.Sprintf("%d", i), e
- case "exportComicUsingSocketExit":
- return "", exportComicUsingSocketExit()
- case "importComicDownload":
- return "", importComicDownload(params)
- case "importComicDownloadUsingSocket":
- return "", importComicDownloadUsingSocket(params)
- case "remoteImageData":
- return remoteImageData(params)
- case "remoteImagePreload":
- return "", remoteImagePreload(params)
- case "clientIpSet":
- return clientIpSet()
- case "downloadImagePath":
- return downloadImagePath(params)
- case "downloadGame":
- return downloadGame(params)
- case "convertImageToJPEG100":
- return "", convertImageToJPEG100(params)
- case "loadDownloadAndExportPath":
- return loadDownloadAndExportPath(), nil
- case "saveDownloadAndExportPath":
- return "", saveDownloadAndExportPath(params)
- case "saveDownloadThreadCount":
- i, e := strconv.Atoi(params)
- if e != nil {
- return "", e
- }
- saveDownloadThreadCount(i)
- return "", nil
- case "loadDownloadThreadCount":
- return strconv.Itoa(loadDownloadThreadCount()), nil
- case "switchLikeComment":
- return switchLikeComment(params)
- case "updatePassword":
- return updatePassword(params)
- case "updateSlogan":
- return updateSlogan(params)
- case "updateAvatar":
- return updateAvatar(params)
- case "defaultHttpClientGet":
- return defaultHttpClientGet(params)
- case "loadViewedList":
- return loadViewedList(params)
- case "collections":
- return collections(params)
- }
- return "", errors.New("method not found : " + method)
-}
diff --git a/go/pikapika/utils/const.go b/go/pikapika/utils/const.go
deleted file mode 100644
index 79bef19..0000000
--- a/go/pikapika/utils/const.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package utils
-
-import (
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
- "os"
-)
-
-var (
- CreateDirMode = os.FileMode(0700)
- CreateFileMode = os.FileMode(0600)
- GormConfig = &gorm.Config{
- Logger: logger.Default.LogMode(logger.Info),
- }
-)
-
diff --git a/go/pikapika/utils/file.go b/go/pikapika/utils/file.go
deleted file mode 100644
index 0ba204c..0000000
--- a/go/pikapika/utils/file.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package utils
-
-import (
- "errors"
- "os"
- "strings"
-)
-
-func Mkdir(dir string) {
- if _, err := os.Stat(dir); err != nil {
- if os.IsNotExist(err) {
- err = os.MkdirAll(dir, CreateDirMode)
- if err != nil {
- panic(err)
- }
- } else {
- panic(err)
- }
- }
-}
-
-func ReasonableFileName(title string) string {
- title = strings.ReplaceAll(title, "\\", "_")
- title = strings.ReplaceAll(title, "/", "_")
- title = strings.ReplaceAll(title, "*", "_")
- title = strings.ReplaceAll(title, "?", "_")
- title = strings.ReplaceAll(title, "<", "_")
- title = strings.ReplaceAll(title, ">", "_")
- title = strings.ReplaceAll(title, "|", "_")
- return title
-}
-
-func Exists(name string) (bool, error) {
- _, err := os.Stat(name)
- if err == nil {
- return true, nil
- }
- if errors.Is(err, os.ErrNotExist) {
- return false, nil
- }
- return false, err
-}
\ No newline at end of file
diff --git a/go/pikapika/utils/mutex.go b/go/pikapika/utils/mutex.go
deleted file mode 100644
index 9f73309..0000000
--- a/go/pikapika/utils/mutex.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package utils
-
-import (
- "hash/fnv"
- "sync"
-)
-
-var hashMutex []*sync.Mutex
-
-func init() {
- for i := 0; i < 32; i++ {
- hashMutex = append(hashMutex, &sync.Mutex{})
- }
-}
-
-// HashLock Hash一样的图片不同时处理
-func HashLock(key string) *sync.Mutex {
- hash := fnv.New32()
- hash.Write([]byte(key))
- return hashMutex[int(hash.Sum32()%uint32(len(hashMutex)))]
-}
diff --git a/go/pikapika/utils/time.go b/go/pikapika/utils/time.go
deleted file mode 100644
index 8b1b471..0000000
--- a/go/pikapika/utils/time.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package utils
-
-import "time"
-
-// Timestamp 获取当前的Unix时间戳
-func Timestamp() int64 {
- return time.Now().UnixNano() / int64(time.Millisecond)
-}
diff --git a/lib/basic/Method.dart b/lib/basic/Method.dart
index 6e2ee33..0d0035a 100644
--- a/lib/basic/Method.dart
+++ b/lib/basic/Method.dart
@@ -285,7 +285,7 @@ class Method {
return ComicsPage.fromJson(json.decode(rsp));
}
- /// 看了此漫画的人还看了...(此接口似乎失效了)
+ /// 看了此漫画的人还看了...
Future> recommendation(String comicId) async {
String rsp = await _flatInvoke("recommendation", comicId);
List list = json.decode(rsp);
diff --git a/lib/screens/ComicInfoScreen.dart b/lib/screens/ComicInfoScreen.dart
index 3d6082c..70cd7d6 100644
--- a/lib/screens/ComicInfoScreen.dart
+++ b/lib/screens/ComicInfoScreen.dart
@@ -7,6 +7,7 @@ import 'package:pikapika/basic/Navigator.dart';
import 'package:pikapika/screens/ComicsScreen.dart';
import 'package:pikapika/screens/components/CommentMainType.dart';
import 'package:pikapika/screens/components/ItemBuilder.dart';
+import 'package:pikapika/screens/components/Recommendation.dart';
import 'ComicReaderScreen.dart';
import 'DownloadConfirmScreen.dart';
@@ -111,10 +112,12 @@ class _ComicInfoScreenState extends State with RouteAware {
var _tabs = [
Tab(text: '章节 (${_comicInfo.epsCount})'),
Tab(text: '评论 (${_comicInfo.commentsCount})'),
+ const Tab(text: '推荐'),
];
var _views = [
_buildEpWrap(_epListFuture, _comicInfo),
CommentList(CommentMainType.COMIC, _comicInfo.id),
+ Recommendation(comicId: _comicInfo.id),
];
return DefaultTabController(
length: _tabs.length,
diff --git a/lib/screens/components/Recommendation.dart b/lib/screens/components/Recommendation.dart
index 44c0ba9..4ea310a 100644
--- a/lib/screens/components/Recommendation.dart
+++ b/lib/screens/components/Recommendation.dart
@@ -7,7 +7,6 @@ import 'ItemBuilder.dart';
import 'Images.dart';
// 看过此本子的也在看
-// 一直返回空数组, 所以没有使用
class Recommendation extends StatefulWidget {
final String comicId;