Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Alderaan
pan-light
提交
ed5697ec
P
pan-light
项目概览
Alderaan
/
pan-light
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
pan-light
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
ed5697ec
编写于
6月 22, 2019
作者:
P
peterq
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add: md5方式分享文件接口
上级
c65dacdd
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
556 addition
and
25 deletion
+556
-25
pc/functions/pan-api.go
pc/functions/pan-api.go
+9
-0
pc/gui/qml/js/util.js
pc/gui/qml/js/util.js
+11
-0
pc/gui/qml/layout/Layout.qml
pc/gui/qml/layout/Layout.qml
+1
-1
pc/gui/qml/pages/share-window.qml
pc/gui/qml/pages/share-window.qml
+123
-0
pc/gui/qml/pan/FileNode.qml
pc/gui/qml/pan/FileNode.qml
+8
-0
pc/gui/qml/qml.qrc
pc/gui/qml/qml.qrc
+1
-0
pc/gui/qml/widget/TopIndicator.qml
pc/gui/qml/widget/TopIndicator.qml
+3
-1
pc/login/baidu.go
pc/login/baidu.go
+1
-1
pc/pan-download/pan-download.go
pc/pan-download/pan-download.go
+33
-0
pc/server-api/server-api.go
pc/server-api/server-api.go
+1
-0
pc/util/fn.go
pc/util/fn.go
+8
-0
server/artisan/web.go
server/artisan/web.go
+7
-0
server/conf/consts.go
server/conf/consts.go
+1
-0
server/dao/file-share.go
server/dao/file-share.go
+31
-0
server/dao/vip-save-file.go
server/dao/vip-save-file.go
+82
-0
server/dao/vip.go
server/dao/vip.go
+6
-2
server/pan-viper/http-client.go
server/pan-viper/http-client.go
+15
-9
server/pan-viper/vip.go
server/pan-viper/vip.go
+144
-10
server/pc-api/handlers.go
server/pc-api/handlers.go
+66
-1
server/pc-api/pc-api-router.go
server/pc-api/pc-api-router.go
+5
-0
未找到文件。
pc/functions/pan-api.go
浏览文件 @
ed5697ec
...
...
@@ -3,6 +3,7 @@ package functions
import
(
"fmt"
"github.com/peterq/pan-light/pc/pan-api"
"github.com/peterq/pan-light/pc/pan-download"
)
func
init
()
{
...
...
@@ -48,4 +49,12 @@ var panApiAsyncRoutes = map[string]asyncHandler{
resolve
(
result
)
}
},
"pan.rapid.md5"
:
func
(
p
map
[
string
]
interface
{},
resolve
func
(
interface
{}),
reject
func
(
interface
{}),
progress
func
(
interface
{}),
qmlMsg
chan
interface
{})
{
sliceMd5
,
err
:=
pan_download
.
RapidUploadMd5
(
fmt
.
Sprint
(
int
(
p
[
"fid"
]
.
(
float64
))))
if
err
!=
nil
{
reject
(
err
)
return
}
resolve
(
sliceMd5
)
},
}
pc/gui/qml/js/util.js
浏览文件 @
ed5697ec
...
...
@@ -445,6 +445,17 @@ var openFeedback = (function () {
}
})()
var
openShare
=
(
function
()
{
var
comp
=
loadComponent
(
function
(){},
'
../pages/share-window.qml
'
)
var
ins
return
function
(
meta
){
if
(
!
ins
||
!
ins
.
visible
)
{
ins
=
comp
.
createObject
(
G
.
root
,
{
meta
:
meta
})
}
return
ins
}
})()
function
api
(
name
,
param
)
{
param
=
param
||
{}
return
callGoAsync
(
'
api.call
'
,
{
name
:
name
,
param
:
param
})
...
...
pc/gui/qml/layout/Layout.qml
浏览文件 @
ed5697ec
...
...
@@ -5,7 +5,7 @@ Item {
property
var
tabsUrl
:
{
'
我的网盘
'
:
'
pan
'
,
'
传输列表
'
:
'
transfer
'
,
'
探索
'
:
'
explore
'
}
property
var
tabs
:
[
'
我的网盘
'
,
'
传输列表
'
,
'
探索
'
]
property
var
colors
:
[
'
blue
'
,
'
red
'
,
'
green
'
]
property
string
activeTab
:
'
传输列表
'
property
string
activeTab
:
'
我的网盘
'
anchors.fill
:
parent
Header
{
id
:
header
...
...
pc/gui/qml/pages/share-window.qml
0 → 100644
浏览文件 @
ed5697ec
import
QtQuick
2.0
import
QtQuick
.
Window
2.2
import
QtQuick
.
Controls
2.2
import
QtQuick
.
Layouts
1.3
import
"
../js/app.js
"
as
App
import
"
../js/util.js
"
as
Util
import
"
../widget
"
Window
{
id
:
window
flags
:
Qt
.
Dialog
|
Qt
.
WindowModal
|
Qt
.
WindowCloseButtonHint
modality
:
Qt
.
ApplicationModal
title
:
'
分享到资源广场
'
minimumHeight
:
height
minimumWidth
:
width
maximumHeight
:
height
maximumWidth
:
width
visible
:
true
width
:
550
height
:
300
property
bool
submitting
:
flase
property
var
sliceMd5Promise
property
var
meta
property
var
timeMap
:
{
"
永久
"
:
365
,
"
7天
"
:
7
,
"
一个月
"
:
30
}
property
string
fileExtention
Component.onCompleted
:
{
getSliceMd5
()
}
function
getSliceMd5
()
{
sliceMd5Promise
=
Util
.
callGoAsync
(
'
pan.rapid.md5
'
,
{
"
fid
"
:
meta
.
fs_id
}).
then
(
function
(
sliceMd5
)
{
console
.
log
(
'
slice md5
'
,
sliceMd5
)
return
sliceMd5
})
sliceMd5Promise
.
catch
(
function
()
{
sliceMd5Promise
=
null
})
}
TopIndicator
{
id
:
topIndicator
z
:
2
}
GridLayout
{
columns
:
2
width
:
parent
.
width
-
20
y
:
20
rowSpacing
:
10
anchors.horizontalCenter
:
parent
.
horizontalCenter
Label
{
text
:
'
分享文件名
'
width
:
parent
.
width
*
30
Layout.alignment
:
Qt
.
AlignRight
}
TextField
{
id
:
titleInput
enabled
:
!
window
.
submitting
width
:
parent
.
width
*
60
placeholderText
:
"
文件名
"
Component.onCompleted
:
{
var
t
=
meta
.
server_filename
.
split
(
'
.
'
)
window
.
fileExtention
=
t
.
pop
()
text
=
t
.
join
(
'
.
'
)
}
}
Label
{
text
:
'
有效期
'
width
:
parent
.
width
*
30
Layout.alignment
:
Qt
.
AlignRight
}
ComboBox
{
id
:
selectDuraion
enabled
:
!
window
.
submitting
model
:
Object
.
keys
(
window
.
timeMap
)
}
Label
{
}
Button
{
id
:
btnShare
text
:
window
.
submitting
?
'
请稍后
'
:
'
分享
'
enabled
:
!
submitting
onClicked
:
{
if
(
!
titleInput
.
text
)
return
if
(
!
sliceMd5Promise
)
{
getSliceMd5
()
}
window
.
submitting
=
true
sliceMd5Promise
.
then
(
function
(
sliceMd5
)
{
return
Util
.
api
(
'
share
'
,
{
"
md5
"
:
window
.
meta
.
md5
,
"
sliceMd5
"
:
sliceMd5
,
"
title
"
:
titleInput
.
text
+
'
.
'
+
window
.
fileExtention
,
"
duration
"
:
window
.
timeMap
[
selectDuraion
.
currentText
],
"
fileSize
"
:
window
.
meta
.
size
})
})
.
then
(
function
()
{
topIndicator
.
success
(
'
分享成功
'
)
return
Util
.
sleep
(
1500
)
})
.
then
(
function
(){
window
.
visible
=
false
})
.
catch
(
function
(
err
)
{
topIndicator
.
fail
(
err
.
message
)
window
.
submitting
=
false
})
}
}
}
}
pc/gui/qml/pan/FileNode.qml
浏览文件 @
ed5697ec
...
...
@@ -99,6 +99,11 @@ Item {
"
cb
"
:
function
()
{
fileItem
.
clickDownloadViaVip
()
}
},
{
"
name
"
:
'
分享到资源广场
'
,
"
cb
"
:
function
()
{
fileItem
.
clickShare
()
}
}]
if
(
Util
.
isVideo
(
fileItem
.
meta
.
server_filename
))
{
fileItem
.
menus
=
fileItem
.
menus
.
concat
([{
...
...
@@ -152,4 +157,7 @@ Item {
console
.
log
(
'
vip down
'
)
App
.
appState
.
transferComp
.
addDownload
(
fileItem
.
meta
,
true
)
}
function
clickShare
()
{
Util
.
openShare
(
fileItem
.
meta
)
}
}
pc/gui/qml/qml.qrc
浏览文件 @
ed5697ec
...
...
@@ -168,5 +168,6 @@
<file>pages/about-window.qml</file>
<file>pages/feedback-window.qml</file>
<file>widget/TopIndicator.qml</file>
<file>pages/share-window.qml</file>
</qresource>
</RCC>
pc/gui/qml/widget/TopIndicator.qml
浏览文件 @
ed5697ec
...
...
@@ -8,13 +8,15 @@ Rectangle {
property
alias
duration
:
hideTimer
.
interval
width
:
parent
.
width
height
:
40
height
:
10
+
msgText
.
implicitHeight
y
:
-
height
Text
{
id
:
msgText
text
:
''
color
:
'
white
'
width
:
parent
.
width
-
20
wrapMode
:
Text
.
WrapAnywhere
anchors.centerIn
:
parent
}
...
...
pc/login/baidu.go
浏览文件 @
ed5697ec
...
...
@@ -122,7 +122,7 @@ func BaiduCookieLogin(cookieStr string) error {
if
j
:=
strings
.
Index
(
name
,
"="
);
j
>=
0
{
name
,
val
=
name
[
:
j
],
name
[
j
+
1
:
]
}
cookies
=
append
(
cookies
,
&
http
.
Cookie
{
Name
:
name
,
Value
:
val
})
cookies
=
append
(
cookies
,
&
http
.
Cookie
{
Name
:
name
,
Value
:
val
,
Domain
:
".baidu.com"
})
}
u
,
_
:=
url
.
Parse
(
"https://pan.baidu.com"
)
...
...
pc/pan-download/pan-download.go
浏览文件 @
ed5697ec
...
...
@@ -6,6 +6,8 @@ import (
"github.com/peterq/pan-light/pc/dep"
"github.com/peterq/pan-light/pc/downloader"
"github.com/peterq/pan-light/pc/pan-api"
"github.com/peterq/pan-light/pc/util"
"github.com/pkg/errors"
"io/ioutil"
"log"
"net/http"
...
...
@@ -76,6 +78,37 @@ func DownloadFile(fid, savePath string, useVip bool) (taskId downloader.TaskId,
return
}
func
RapidUploadMd5
(
fid
string
)
(
sliceMd5
string
,
err
error
)
{
link
,
err
:=
pan_api
.
Link
(
fid
)
if
err
!=
nil
{
err
=
errors
.
Wrap
(
err
,
"解析直链错误"
)
return
}
req
,
err
:=
http
.
NewRequest
(
"GET"
,
link
,
nil
)
if
err
!=
nil
{
errors
.
Wrap
(
err
,
"无法创建request"
)
return
}
requestDecorator
(
req
)
req
.
Header
.
Set
(
"Range"
,
fmt
.
Sprintf
(
"bytes=%d-%d"
,
0
,
256
*
1024
-
1
))
resp
,
err
:=
manager
.
HttpClient
.
Do
(
req
)
if
err
!=
nil
{
err
=
errors
.
Wrap
(
err
,
"访问直链错误"
)
return
}
defer
resp
.
Body
.
Close
()
bin
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
err
=
errors
.
Wrap
(
err
,
"获取前256k内容错误"
)
return
}
if
len
(
bin
)
!=
256
*
1024
{
err
=
errors
.
New
(
"文件内容小于256k"
)
}
sliceMd5
=
util
.
Md5bin
(
bin
)
return
}
func
requestDecorator
(
request
*
http
.
Request
)
*
http
.
Request
{
request
.
Header
.
Set
(
"User-Agent"
,
pan_api
.
BaiduUA
)
return
request
...
...
pc/server-api/server-api.go
浏览文件 @
ed5697ec
...
...
@@ -19,6 +19,7 @@ var urlMap = map[string]string{
"login"
:
"/api/pc/login"
,
"feedback"
:
"/api/pc/feedback"
,
"refresh-token"
:
"/api/pc/refresh-token"
,
"share"
:
"/api/pc/share"
,
}
var
httpClient
=
http
.
Client
{
//Timeout: 15 * time.Second,
...
...
pc/util/fn.go
浏览文件 @
ed5697ec
package
util
import
(
"crypto/md5"
"encoding/hex"
"math/rand"
"strconv"
"time"
...
...
@@ -18,3 +20,9 @@ func First(args ...interface{}) interface{} {
func
Second
(
args
...
interface
{})
interface
{}
{
return
args
[
1
]
}
func
Md5bin
(
bin
[]
byte
)
string
{
h
:=
md5
.
New
()
h
.
Write
(
bin
)
return
hex
.
EncodeToString
(
h
.
Sum
(
nil
))
}
server/artisan/web.go
浏览文件 @
ed5697ec
...
...
@@ -181,6 +181,13 @@ func (v JsonValue) Int() int {
panic
(
NewError
(
fmt
.
Sprintf
(
"%s needs to be int, %T given"
,
v
.
name
,
v
.
data
),
-
1
,
nil
))
}
func
(
v
JsonValue
)
Int64
()
int64
{
if
m
,
ok
:=
v
.
data
.
(
float64
);
ok
{
return
int64
(
m
)
}
panic
(
NewError
(
fmt
.
Sprintf
(
"%s needs to be int, %T given"
,
v
.
name
,
v
.
data
),
-
1
,
nil
))
}
func
(
v
JsonValue
)
Float
()
float64
{
if
m
,
ok
:=
v
.
data
.
(
float64
);
ok
{
return
m
...
...
server/conf/consts.go
浏览文件 @
ed5697ec
...
...
@@ -5,6 +5,7 @@ const (
CollectionVipSaveFile
=
"vip_save_file"
CollectionUser
=
"user"
CollectionFeedback
=
"feedback"
CollectionFileShare
=
"file_share"
)
const
(
...
...
server/dao/file-share.go
0 → 100644
浏览文件 @
ed5697ec
package
dao
import
(
"github.com/peterq/pan-light/server/conf"
"gopkg.in/mgo.v2"
)
type
FileShareModel
struct
{
Uk
string
Title
string
Md5
string
SliceMd5
string
`bson:"slice_md5"`
FileSize
int64
`bson:"file_size"`
ExpireAt
int64
`bson:"expire_at"`
}
type
fileShareDao
struct
{}
func
(
*
fileShareDao
)
collection
(
s
*
mgo
.
Session
)
*
mgo
.
Collection
{
return
s
.
DB
(
conf
.
Conf
.
Database
)
.
C
(
conf
.
CollectionFileShare
)
}
func
(
d
*
fileShareDao
)
Insert
(
data
FileShareModel
)
(
err
error
)
{
s
:=
conf
.
MongodbSession
.
Clone
()
defer
s
.
Refresh
()
collection
:=
d
.
collection
(
s
)
err
=
collection
.
Insert
(
data
)
return
}
var
FileShareDao
=
&
fileShareDao
{}
server/dao/vip-save-file.go
0 → 100644
浏览文件 @
ed5697ec
package
dao
import
(
"github.com/peterq/pan-light/server/conf"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"time"
)
type
VipSaveFileModel
struct
{
Id
bson
.
ObjectId
`bson:"_id,omitempty"`
Username
string
`bson:"username,omitempty"`
// vip 用户名
Md5
string
`bson:"md5,omitempty"`
SliceMd5
string
`bson:"slice_md5,omitempty"`
FileSize
int64
`bson:"file_size,omitempty"`
Fid
string
`bson:"fid,omitempty"`
AddAt
int64
`bson:"add_at,omitempty"`
// 转存时间
HitAt
int64
`bson:"hit_at,omitempty"`
// 重复转存命中时间
DeletedAt
int64
`bson:"deleted_at"`
// 删除时间
}
func
(
f
*
VipSaveFileModel
)
GetSavePath
()
string
{
return
"/pan-light-save/"
+
f
.
Md5
[
:
2
]
+
"/"
+
f
.
Md5
[
2
:
4
]
}
type
vipSaveFileDao
struct
{}
func
(
*
vipSaveFileDao
)
collection
(
s
*
mgo
.
Session
)
*
mgo
.
Collection
{
return
s
.
DB
(
conf
.
Conf
.
Database
)
.
C
(
conf
.
CollectionVipSaveFile
)
}
func
(
d
*
vipSaveFileDao
)
GetByMd5
(
md5
string
)
(
data
VipSaveFileModel
,
err
error
)
{
s
:=
conf
.
MongodbSession
.
Clone
()
defer
s
.
Refresh
()
collection
:=
d
.
collection
(
s
)
err
=
collection
.
Pipe
([]
bson
.
M
{
{
"$match"
:
bson
.
M
{
"deleted_at"
:
0
,
},
},
{
"$lookup"
:
bson
.
M
{
"from"
:
conf
.
CollectionVip
,
"localField"
:
"username"
,
"foreignField"
:
"username"
,
"as"
:
"viper"
,
},
},
{
"$match"
:
bson
.
M
{
"viper.enabled"
:
true
,
},
},
})
.
One
(
&
data
)
return
}
func
(
d
*
vipSaveFileDao
)
Insert
(
data
VipSaveFileModel
)
(
err
error
)
{
s
:=
conf
.
MongodbSession
.
Clone
()
defer
s
.
Refresh
()
collection
:=
d
.
collection
(
s
)
err
=
collection
.
Insert
(
data
)
return
}
func
(
d
*
vipSaveFileDao
)
Hit
(
data
VipSaveFileModel
)
(
err
error
)
{
data
.
HitAt
=
time
.
Now
()
.
Unix
()
s
:=
conf
.
MongodbSession
.
Clone
()
defer
s
.
Refresh
()
collection
:=
d
.
collection
(
s
)
err
=
collection
.
Update
(
bson
.
M
{
"_id"
:
data
.
Id
,
},
bson
.
M
{
"$set"
:
bson
.
M
{
"hit_at"
:
data
.
HitAt
,
},
})
return
}
var
VipSaveFileDao
=
&
vipSaveFileDao
{}
server/dao/vip.go
浏览文件 @
ed5697ec
...
...
@@ -3,11 +3,13 @@ package dao
import
(
"github.com/peterq/pan-light/server/conf"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type
VipModel
struct
{
Username
string
Bduss
string
Cookie
string
Enabled
bool
}
type
vipDao
struct
{}
...
...
@@ -20,7 +22,9 @@ func (d *vipDao) GetAll() (data []VipModel, err error) {
s
:=
conf
.
MongodbSession
.
Clone
()
defer
s
.
Refresh
()
collection
:=
d
.
collection
(
s
)
err
=
collection
.
Find
(
nil
)
.
All
(
&
data
)
err
=
collection
.
Find
(
bson
.
M
{
"enabled"
:
true
,
})
.
All
(
&
data
)
return
}
...
...
server/pan-viper/http-client.go
浏览文件 @
ed5697ec
...
...
@@ -16,17 +16,23 @@ type gson = map[string]interface{}
const
baiduUa
=
"netdisk;4.6.2.0;PC;PC-Windows;10.0.10240;WindowsBaiduYunGuanJia"
func
makeHttpClient
(
bduss
string
)
http
.
Client
{
func
makeHttpClient
(
cookieStr
string
)
http
.
Client
{
jar
,
_
:=
cookiejar
.
New
(
nil
)
u
,
_
:=
url
.
Parse
(
"https://pan.baidu.com"
)
jar
.
SetCookies
(
u
,
[]
*
http
.
Cookie
{
{
Name
:
"BDUSS"
,
Value
:
bduss
,
Path
:
"/"
,
Domain
:
".baidu.com"
,
},
})
var
cookies
[]
*
http
.
Cookie
parts
:=
strings
.
Split
(
strings
.
TrimSpace
(
cookieStr
),
";"
)
for
i
:=
0
;
i
<
len
(
parts
);
i
++
{
parts
[
i
]
=
strings
.
TrimSpace
(
parts
[
i
])
if
len
(
parts
[
i
])
==
0
{
continue
}
name
,
val
:=
parts
[
i
],
""
if
j
:=
strings
.
Index
(
name
,
"="
);
j
>=
0
{
name
,
val
=
name
[
:
j
],
name
[
j
+
1
:
]
}
cookies
=
append
(
cookies
,
&
http
.
Cookie
{
Name
:
name
,
Value
:
val
,
Domain
:
".baidu.com"
})
}
jar
.
SetCookies
(
u
,
cookies
)
httpClient
:=
http
.
Client
{
Transport
:
nil
,
CheckRedirect
:
func
(
req
*
http
.
Request
,
via
[]
*
http
.
Request
)
error
{
...
...
server/pan-viper/vip.go
浏览文件 @
ed5697ec
package
pan_viper
import
(
"encoding/base64"
"encoding/json"
"fmt"
"github.com/kataras/iris"
"github.com/peterq/pan-light/server/dao"
"github.com/pkg/errors"
"io/ioutil"
"log"
"net/http"
"path/filepath"
"regexp"
"strings"
"sync"
"time"
)
var
vipMap
=
map
[
string
]
*
Vip
{}
var
vipMap
sync
.
Map
func
init
()
{
data
,
err
:=
dao
.
Vip
.
GetAll
()
if
err
!=
nil
{
panic
(
err
)
}
if
len
(
data
)
==
0
{
panic
(
"no vip account available"
)
}
for
_
,
model
:=
range
data
{
v
ipMap
[
model
.
Username
]
=
&
Vip
{
http
:
makeHttpClient
(
model
.
Bduss
)
,
username
:
model
.
Usernam
e
,
v
:
=
&
Vip
{
username
:
model
.
Username
,
cookieRaw
:
model
.
Cooki
e
,
}
v
.
init
()
vipMap
.
Store
(
model
.
Username
,
v
)
}
}
type
loginSession
struct
{
Sign
string
Timestamp
string
Bdstoken
string
Bduss
string
}
type
Vip
struct
{
http
http
.
Client
username
string
_loginSession
loginSession
bduss
string
cookieRaw
string
_loginSession
*
loginSession
loginSessionLock
sync
.
RWMutex
}
func
(
v
*
Vip
)
loginSession
()
loginSession
{
func
(
v
*
Vip
)
loginSession
()
*
loginSession
{
v
.
loginSessionLock
.
RLock
()
defer
v
.
loginSessionLock
.
RUnlock
()
return
v
.
_loginSession
}
func
(
v
*
Vip
)
init
()
{
v
.
http
=
makeHttpClient
(
v
.
cookieRaw
)
go
v
.
CreateSession
()
}
func
(
v
*
Vip
)
Username
()
string
{
return
v
.
username
}
func
(
v
*
Vip
)
CreateSession
()
{
//v.request()
func
(
v
*
Vip
)
CreateSession
()
(
err
error
)
{
defer
func
()
{
if
err
!=
nil
{
(
&
iris
.
Application
{})
.
Logger
()
.
Error
(
v
.
username
,
"vip创建session错误"
,
err
)
}
}()
old
:=
v
.
loginSession
()
v
.
loginSessionLock
.
Lock
()
defer
v
.
loginSessionLock
.
Unlock
()
// 高并发下防止重复更新session
if
old
!=
v
.
_loginSession
{
return
}
homePageLink
:=
"https://pan.baidu.com/disk/homePageLink"
req
:=
newRequest
(
"GET"
,
homePageLink
)
res
,
err
:=
v
.
http
.
Do
(
req
)
if
err
!=
nil
{
err
=
errors
.
Wrap
(
err
,
"访问首页错误"
)
return
}
bin
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
err
!=
nil
{
err
=
errors
.
Wrap
(
err
,
"读取首页body错误"
)
return
}
body
:=
string
(
bin
)
reg
:=
regexp
.
MustCompile
(
`var context=(.*);\n`
)
find
:=
reg
.
FindStringSubmatch
(
body
)
if
res
.
Request
.
URL
.
String
()
!=
homePageLink
{
err
=
errors
.
New
(
"重定向到"
+
res
.
Request
.
URL
.
String
())
return
}
raw
:=
gson
{}
err
=
json
.
Unmarshal
([]
byte
(
find
[
1
]),
&
raw
)
if
err
!=
nil
{
log
.
Println
(
body
)
return
}
s
:=
loginSession
{
Sign
:
""
,
Timestamp
:
""
,
Bdstoken
:
""
,
Bduss
:
""
,
}
s
.
Sign
=
loginSign
(
raw
[
"sign3"
]
.
(
string
),
raw
[
"sign1"
]
.
(
string
))
s
.
Timestamp
=
fmt
.
Sprint
(
int
(
raw
[
"timestamp"
]
.
(
float64
)))
s
.
Bdstoken
=
raw
[
"bdstoken"
]
.
(
string
)
s
.
Bduss
=
v
.
bduss
v
.
_loginSession
=
&
s
log
.
Println
(
v
.
username
,
"完成loginSession"
)
return
}
func
loginSign
(
j
,
r
string
)
string
{
a
:=
[
256
]
int
{}
p
:=
[
256
]
int
{}
o
:=
make
([]
byte
,
len
(
r
))
v
:=
len
(
j
)
for
q
:=
0
;
q
<
256
;
q
++
{
a
[
q
]
=
int
(
j
[
q
%
v
:
q
%
v
+
1
][
0
])
p
[
q
]
=
q
}
for
u
,
q
:=
0
,
0
;
q
<
256
;
q
++
{
u
=
(
u
+
p
[
q
]
+
a
[
q
])
%
256
t
:=
p
[
q
]
p
[
q
]
=
p
[
u
]
p
[
u
]
=
t
}
for
i
,
u
,
q
:=
0
,
0
,
0
;
q
<
len
(
r
);
q
++
{
i
=
(
i
+
1
)
%
256
u
=
(
u
+
p
[
i
])
%
256
t
:=
p
[
i
]
p
[
i
]
=
p
[
u
]
p
[
u
]
=
t
k
:=
p
[((
p
[
i
]
+
p
[
u
])
%
256
)]
o
[
q
]
=
byte
(
int
(
r
[
q
:
q
+
1
][
0
])
^
k
)
}
return
base64
.
StdEncoding
.
EncodeToString
(
o
)
}
func
(
v
*
Vip
)
LoadShareFilenameAndUk
(
link
,
secret
string
)
(
uk
,
filename
string
,
share
gson
,
err
error
)
{
...
...
@@ -88,6 +184,31 @@ func (v *Vip) LoadShareFilenameAndUk(link, secret string) (uk, filename string,
return
}
func
(
v
*
Vip
)
SaveFileByMd5
(
md5
,
sliceMd5
,
path
string
,
contentLength
int64
)
(
fid
string
,
fileSize
int64
,
err
error
)
{
ss
:=
v
.
loginSession
()
data
,
err
:=
v
.
request
(
"POST"
,
"https://pan.baidu.com/api/rapidupload"
,
gson
{
"rtype"
:
1
,
"channel"
:
"chunlei"
,
"web"
:
1
,
"app_id"
:
250528
,
"bdstoken"
:
ss
.
Bdstoken
,
"logid"
:
time
.
Now
()
.
UnixNano
(),
"clienttype"
:
0
,
},
gson
{
"path"
:
path
,
"content-length"
:
contentLength
,
"content-md5"
:
md5
,
"slice-md5"
:
sliceMd5
,
"target_path"
:
filepath
.
Dir
(
path
),
"local_mtime"
:
1533345687
,
})
if
_
,
ok
:=
data
[
"errno"
];
!
ok
{
log
.
Println
(
data
)
err
=
errors
.
New
(
"极速上传失败"
)
}
return
}
func
(
v
*
Vip
)
inputSharePwd
(
link
,
secret
string
)
(
err
error
)
{
t
:=
strings
.
Split
(
link
,
"/"
)
...
...
@@ -138,14 +259,27 @@ func (v *Vip) request(method, link string, params gson, form gson) (data gson, e
return
}
if
n
,
ok
:=
data
[
"errno"
];
ok
&&
n
.
(
float64
)
!=
0
{
// 页面过期错误码
if
n
.
(
float64
)
==
112
{
go
v
.
CreateSession
()
}
err
=
errors
.
New
(
"pan api error code "
+
fmt
.
Sprint
(
data
[
"errno"
]))
}
return
}
func
GetVip
()
*
Vip
{
for
_
,
value
:=
range
vipMap
{
return
value
var
v
*
Vip
vipMap
.
Range
(
func
(
key
,
value
interface
{})
bool
{
v
=
value
.
(
*
Vip
)
return
false
})
return
v
}
func
GetVipByUsername
(
username
string
)
*
Vip
{
if
v
,
ok
:=
vipMap
.
Load
(
username
);
ok
{
return
v
.
(
*
Vip
)
}
return
nil
}
server/pc-api/handlers.go
浏览文件 @
ed5697ec
...
...
@@ -9,6 +9,8 @@ import (
"github.com/peterq/pan-light/server/dao"
"github.com/peterq/pan-light/server/pan-viper"
"github.com/peterq/pan-light/server/pc-api/middleware"
"gopkg.in/mgo.v2"
"log"
"strings"
"time"
)
...
...
@@ -94,7 +96,70 @@ func handleFeedBack(ctx context.Context, param artisan.JsonMap) (result interfac
Content
:
content
,
})
if
err
!=
nil
{
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
nil
)
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
err
)
}
return
}
func
handleShareToSquare
(
ctx
context
.
Context
,
param
artisan
.
JsonMap
)
(
result
interface
{},
err
error
)
{
md5
:=
param
.
Get
(
"md5"
)
.
String
()
sliceMd5
:=
param
.
Get
(
"sliceMd5"
)
.
String
()
title
:=
param
.
Get
(
"title"
)
.
String
()
duration
:=
param
.
Get
(
"duration"
)
.
Int
()
fileSize
:=
param
.
Get
(
"fileSize"
)
.
Int64
()
// 查找该文件是否被vip账号存储过
data
,
err
:=
dao
.
VipSaveFileDao
.
GetByMd5
(
md5
)
if
err
!=
nil
&&
err
!=
mgo
.
ErrNotFound
{
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
err
)
return
}
log
.
Println
(
data
,
err
)
// 没有存储过, 使用秒传进行存储
if
err
==
mgo
.
ErrNotFound
{
data
=
dao
.
VipSaveFileModel
{
Username
:
""
,
Md5
:
md5
,
SliceMd5
:
sliceMd5
,
FileSize
:
0
,
Fid
:
""
,
AddAt
:
time
.
Now
()
.
Unix
(),
HitAt
:
time
.
Now
()
.
Unix
(),
DeletedAt
:
0
,
}
viper
:=
pan_viper
.
GetVip
()
data
.
Username
=
viper
.
Username
()
data
.
Fid
,
data
.
FileSize
,
err
=
viper
.
SaveFileByMd5
(
md5
,
sliceMd5
,
data
.
GetSavePath
(),
fileSize
)
if
err
!=
nil
{
err
=
artisan
.
NewError
(
"vip账号转存文件错误"
,
-
1
,
err
)
return
}
err
=
dao
.
VipSaveFileDao
.
Insert
(
data
)
if
err
!=
nil
{
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
err
)
return
}
}
else
{
// 存储过, 更新命中时间戳
err
=
dao
.
VipSaveFileDao
.
Hit
(
data
)
if
err
!=
nil
{
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
err
)
return
}
}
// 写入分享表
share
:=
dao
.
FileShareModel
{
Uk
:
middleware
.
ContextLoginInfo
(
ctx
)
.
Uk
(),
Title
:
title
,
Md5
:
md5
,
SliceMd5
:
sliceMd5
,
FileSize
:
data
.
FileSize
,
ExpireAt
:
time
.
Now
()
.
Add
(
time
.
Hour
*
24
*
time
.
Duration
(
duration
))
.
Unix
(),
}
dao
.
FileShareDao
.
Insert
(
share
)
if
err
!=
nil
{
err
=
artisan
.
NewError
(
"database error"
,
-
1
,
err
)
return
}
result
=
share
return
}
server/pc-api/pc-api-router.go
浏览文件 @
ed5697ec
...
...
@@ -48,4 +48,9 @@ func pcAuthRoutes(r router.Party) {
},
handleFeedBack
)
post
(
"refresh-token"
,
handleRefreshToken
)
post
(
"share"
,
artisan
.
ThrottleOption
{
Duration
:
time
.
Hour
,
Number
:
500
,
},
handleShareToSquare
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录