mirror of https://github.com/midoks/mdserver-web
parent
0310cab3ae
commit
062a518492
@ -0,0 +1,413 @@ |
||||
# coding:utf-8 |
||||
|
||||
import sys |
||||
import io |
||||
import os |
||||
import time |
||||
import re |
||||
import json |
||||
import io |
||||
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core") |
||||
import mw |
||||
|
||||
# ----------------------------- |
||||
import google.oauth2.credentials |
||||
import google_auth_oauthlib.flow |
||||
from googleapiclient.discovery import build |
||||
from google_auth_oauthlib.flow import InstalledAppFlow |
||||
from google.auth.transport.requests import Request |
||||
from googleapiclient.http import MediaFileUpload |
||||
from googleapiclient.http import MediaIoBaseDownload |
||||
|
||||
|
||||
class gdriveclient(): |
||||
__plugin_dir = '' |
||||
__server_dir = '' |
||||
|
||||
__credentials = "/root/credentials.json" |
||||
__backup_dir_name = "backup" |
||||
__creds = None |
||||
__exclude = "" |
||||
__scpos = ['https://www.googleapis.com/auth/drive.file'] |
||||
_title = 'Google Drive' |
||||
_name = 'Google Drive' |
||||
__debug = False |
||||
|
||||
_DEFAULT_AUTH_PROMPT_MESSAGE = ( |
||||
'Please visit this URL to authorize this application: {url}') |
||||
"""str: The message to display when prompting the user for |
||||
authorization.""" |
||||
_DEFAULT_AUTH_CODE_MESSAGE = ( |
||||
'Enter the authorization code: ') |
||||
"""str: The message to display when prompting the user for the |
||||
authorization code. Used only by the console strategy.""" |
||||
|
||||
_DEFAULT_WEB_SUCCESS_MESSAGE = ( |
||||
'The authentication flow has completed, you may close this window.') |
||||
|
||||
def __init__(self, plugin_dir, server_dir): |
||||
self.__plugin_dir = plugin_dir |
||||
self.__server_dir = server_dir |
||||
self.set_creds() |
||||
# self.set_libList() |
||||
|
||||
# self.get_exclode() |
||||
|
||||
def setDebug(self, d=False): |
||||
self.__debug = d |
||||
|
||||
def D(self, msg=''): |
||||
if self.__debug: |
||||
print(msg) |
||||
|
||||
# 检查gdrive连接 |
||||
def _check_connect(self): |
||||
try: |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list( |
||||
pageSize=10, fields="nextPageToken, files(id, name)").execute() |
||||
results.get('files', []) |
||||
except: |
||||
return False |
||||
return True |
||||
|
||||
# 设置creds |
||||
def set_creds(self): |
||||
token_file = self.__server_dir + '/token.json' |
||||
if os.path.exists(token_file): |
||||
with open(token_file, 'rb') as token: |
||||
tmp_data = json.load(token)['credentials'] |
||||
self.__creds = google.oauth2.credentials.Credentials( |
||||
tmp_data['token'], |
||||
tmp_data['refresh_token'], |
||||
tmp_data['id_token'], |
||||
tmp_data['token_uri'], |
||||
tmp_data['client_id'], |
||||
tmp_data['client_secret'], |
||||
tmp_data['scopes']) |
||||
# if not self._check_connect(): |
||||
# return False |
||||
# else: |
||||
# return True |
||||
|
||||
def get_sign_in_url(self): |
||||
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( |
||||
self.__plugin_dir + '/credentials.json', |
||||
scopes=self.__scpos) |
||||
flow.redirect_uri = 'https://localhost' |
||||
auth_url, state = flow.authorization_url( |
||||
access_type='offline', |
||||
prompt='consent', |
||||
include_granted_scopes='false') |
||||
return auth_url, state |
||||
|
||||
def set_auth_url(self, url): |
||||
token_file = self.__server_dir + '/token.json' |
||||
if os.path.exists(token_file): |
||||
return mw.returnJson(True, "验证成功") |
||||
|
||||
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( |
||||
self.__plugin_dir + '/credentials.json', |
||||
scopes=self.__scpos, |
||||
state=url.split('state=')[1].split('&code=')[0]) |
||||
flow.redirect_uri = 'https://localhost' |
||||
flow.fetch_token(authorization_response=url) |
||||
credentials = flow.credentials |
||||
|
||||
credentials_data = {} |
||||
credentials_data['credentials'] = { |
||||
'token': credentials.token, |
||||
'id_token': credentials.id_token, |
||||
'refresh_token': credentials.refresh_token, |
||||
'token_uri': credentials.token_uri, |
||||
'client_id': credentials.client_id, |
||||
'client_secret': credentials.client_secret, |
||||
'scopes': credentials.scopes} |
||||
with open(token_file, 'w') as token: |
||||
json.dump(credentials_data, token) |
||||
if not self.set_creds(): |
||||
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证") |
||||
return mw.returnJson(True, "验证成功") |
||||
|
||||
def set_libList(self): |
||||
libList = public.readFile("/www/server/panel/data/libList.conf") |
||||
if libList: |
||||
libList = json.loads(libList) |
||||
for i in libList: |
||||
if "gdrive" in i.values(): |
||||
return |
||||
d = { |
||||
"name": "Google Drive", |
||||
"type": "Cron job", |
||||
"ps": "Back up your website or database to Google Cloud Storage.", |
||||
"status": False, |
||||
"opt": "gdrive", |
||||
"module": "os", |
||||
"script": "gdrive", |
||||
"help": "http://forum.aapanel.com", |
||||
"key": "", |
||||
"secret": "", |
||||
"bucket": "", |
||||
"domain": "", |
||||
"check": ["/www/server/panel/plugin/gdrive/gdrive_main.py", |
||||
"/www/server/panel/script/backup_gdrive.py"] |
||||
} |
||||
d1 = { |
||||
"name": "谷歌硬盘", |
||||
"type": "计划任务", |
||||
"ps": "将网站或数据库打包备份到谷歌硬盘.", |
||||
"status": False, |
||||
"opt": "gdrive", |
||||
"module": "os", |
||||
"script": "gdrive", |
||||
"help": "http://www.bt.cn/bbs", |
||||
"key": "", |
||||
"secret": "", |
||||
"bucket": "", |
||||
"domain": "", |
||||
"check": ["/www/server/panel/plugin/gdrive/gdrive_main.py", |
||||
"/www/server/panel/script/backup_gdrive.py"] |
||||
} |
||||
language = public.readFile("/www/server/panel/config/config.json") |
||||
if "English" in language: |
||||
data = d |
||||
else: |
||||
data = d1 |
||||
libList.append(data) |
||||
public.writeFile("/www/server/panel/data/libList.conf", |
||||
json.dumps(libList)) |
||||
return libList |
||||
|
||||
# 获取token |
||||
def get_token(self, get): |
||||
token_file = self.__server_dir + '/token.json' |
||||
import requests |
||||
try: |
||||
respone = requests.get("https://www.google.com", timeout=2) |
||||
except: |
||||
return mw.returnJson(False, "连接谷歌失败") |
||||
if respone.status_code != 200: |
||||
return mw.returnJson(False, "连接谷歌失败") |
||||
if not self.set_creds(): |
||||
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证") |
||||
if not os.path.exists(token_file): |
||||
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证") |
||||
return mw.returnJson(True, "验证成功") |
||||
|
||||
# 获取auth_url |
||||
def get_auth_url(self, get): |
||||
self.get_sign_in_url() |
||||
if os.path.exists("/tmp/auth_url"): |
||||
return mw.readFile("/tmp/auth_url") |
||||
|
||||
# 检查连接 |
||||
def check_connect(self, get): |
||||
token_file = self.__server_dir + '/token.json' |
||||
if os.path.exists(token_file): |
||||
with open(token_file, 'rb') as token: |
||||
self.set_creds() |
||||
else: |
||||
self.D("Failed to get Google token, please verify before use") |
||||
return mw.returnJson(True, "Failed to get Google token, please verify before use") |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list( |
||||
pageSize=10, fields="nextPageToken, files(id, name)").execute() |
||||
try: |
||||
results.get('files', []) |
||||
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证") |
||||
return mw.returnJson(True, "验证成功") |
||||
except: |
||||
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证") |
||||
|
||||
def _get_filename(self, filename): |
||||
l = filename.split("/") |
||||
return l[-1] |
||||
|
||||
def _create_folder_cycle(self, filepath): |
||||
l = filepath.split("/") |
||||
fid_list = [] |
||||
for i in l: |
||||
if not i: |
||||
continue |
||||
fid = self.__get_folder_id(i) |
||||
if fid: |
||||
fid_list.append(fid) |
||||
continue |
||||
if not fid_list: |
||||
fid_list.append("") |
||||
fid_list.append(self.create_folder(i, fid_list[-1])) |
||||
return fid_list[-1] |
||||
|
||||
def build_object_name(self, data_type, file_name): |
||||
"""根据数据类型构建对象存储名称 |
||||
|
||||
:param data_type: |
||||
:param file_name: |
||||
:return: |
||||
""" |
||||
|
||||
import re |
||||
prefix_dict = { |
||||
"site": "web", |
||||
"database": "db", |
||||
"path": "path", |
||||
} |
||||
|
||||
if not prefix_dict.get(data_type): |
||||
print("data_type 类型错误!!!") |
||||
exit(1) |
||||
|
||||
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\." |
||||
sub_search = re.search(file_regx.lower(), file_name) |
||||
sub_path_name = "" |
||||
if sub_search: |
||||
sub_path_name = sub_search.groups()[0] |
||||
sub_path_name += '/' |
||||
# 构建OS存储路径 |
||||
object_name = self.__backup_dir_name + \ |
||||
'/{}/{}'.format(data_type, sub_path_name) |
||||
|
||||
if object_name[:1] == "/": |
||||
object_name = object_name[1:] |
||||
return object_name |
||||
|
||||
# 上传文件 |
||||
def upload_file(self, filename, data_type=None): |
||||
""" |
||||
get.filename 上传后的文件名 |
||||
get.filepath 上传文件路径 |
||||
被面板新版计划任务调用时 |
||||
get表示file_name |
||||
:param get: |
||||
:return: |
||||
""" |
||||
# filename = filename |
||||
filepath = self.build_object_name(data_type, filename) |
||||
_filename = self._get_filename(filename) |
||||
self.D(filepath) |
||||
self.D(filename) |
||||
|
||||
parents = self._create_folder_cycle(filepath) |
||||
self.D(parents) |
||||
drive_service = build('drive', 'v3', credentials=self.__creds) |
||||
file_metadata = {'name': _filename, 'parents': [parents]} |
||||
media = MediaFileUpload(filename, resumable=True) |
||||
file = drive_service.files().create( |
||||
body=file_metadata, media_body=media, fields='id').execute() |
||||
self.D('Upload Success ,File ID: %s' % file.get('id')) |
||||
return True |
||||
|
||||
def _get_file_id(self, filename): |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list(pageSize=10, q="name='{}'".format( |
||||
filename), fields="nextPageToken, files(id, name)").execute() |
||||
items = results.get('files', []) |
||||
if not items: |
||||
return [] |
||||
else: |
||||
for item in items: |
||||
return item["id"] |
||||
|
||||
def delete_file(self, filename=None, data_type=None): |
||||
file_id = self._get_file_id(filename) |
||||
self.delete_file_by_id(file_id) |
||||
return True |
||||
|
||||
def delete_file_by_id(self, file_id): |
||||
self.D("delete id:{}".format(file_id)) |
||||
try: |
||||
drive_service = build('drive', 'v3', credentials=self.__creds) |
||||
drive_service.files().delete(fileId=file_id).execute() |
||||
return True |
||||
except Exception as e: |
||||
return False |
||||
|
||||
# 创建目录 |
||||
def create_folder(self, folder_name, parents=""): |
||||
self.D(self.__creds) |
||||
self.D("folder_name: {}".format(folder_name)) |
||||
self.D("parents: {}".format(parents)) |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
file_metadata = { |
||||
'name': folder_name, |
||||
'mimeType': 'application/vnd.google-apps.folder' |
||||
} |
||||
if parents: |
||||
file_metadata['parents'] = [parents] |
||||
folder = service.files().create(body=file_metadata, fields='id').execute() |
||||
self.D('Create Folder ID: %s' % folder.get('id')) |
||||
return folder.get('id') |
||||
|
||||
def get_rootdir_id(self, folder_name='backup'): |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(folder_name), |
||||
fields="nextPageToken, files(id, name,size,parents,webViewLink)").execute() |
||||
items = results.get('files', []) |
||||
if len(items) == 0: |
||||
self.create_folder(folder_name) |
||||
return self.get_rootdir_id(folder_name) |
||||
|
||||
return items[0]['parents'][0] |
||||
|
||||
# 获取目录id |
||||
def __get_folder_id(self, floder_name): |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(floder_name), |
||||
fields="nextPageToken, files(id, name)").execute() |
||||
items = results.get('files', []) |
||||
if not items: |
||||
return [] |
||||
else: |
||||
for item in items: |
||||
return item["id"] |
||||
|
||||
def get_res_info(self, rid): |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().get(fileId='{}'.format(rid)).execute() |
||||
return results |
||||
|
||||
def get_id_list(self, driveId=''): |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
results = service.files().list(pageSize=10, driveId="{}".format(driveId), |
||||
fields="nextPageToken, files(id, name,size,parents)").execute() |
||||
items = results.get('files', []) |
||||
return items |
||||
|
||||
def get_list(self, dir_id='', next_page_token=''): |
||||
if dir_id == '': |
||||
dir_id = self.get_rootdir_id(self.__backup_dir_name) |
||||
|
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
cmd_query = "trashed=false and '{}' in parents".format(dir_id) |
||||
results = service.files().list(pageSize=10, q=cmd_query, orderBy='folder asc', |
||||
fields="nextPageToken, files(id, name,size,createdTime,parents,webViewLink)").execute() |
||||
items = results.get('files', []) |
||||
nextPageToken = results.get('nextPageToken', []) |
||||
# print(items) |
||||
# print(nextPageToken) |
||||
return items |
||||
|
||||
def get_exclode(self, exclude=[]): |
||||
if not exclude: |
||||
tmp_exclude = os.getenv('BT_EXCLUDE') |
||||
if tmp_exclude: |
||||
exclude = tmp_exclude.split(',') |
||||
if not exclude: |
||||
return "" |
||||
for ex in exclude: |
||||
self.__exclude += " --exclude=\"" + ex + "\"" |
||||
self.__exclude += " " |
||||
return self.__exclude |
||||
|
||||
def download_file(self, filename): |
||||
file_id = self._get_file_id(filename) |
||||
service = build('drive', 'v3', credentials=self.__creds) |
||||
request = service.files().get_media(fileId=file_id) |
||||
with open('/tmp/{}'.format(filename), 'wb') as fh: |
||||
downloader = MediaIoBaseDownload(fh, request) |
||||
done = False |
||||
while done is False: |
||||
status, done = downloader.next_chunk() |
||||
print("Download %d%%." % int(status.progress() * 100)) |
@ -0,0 +1,11 @@ |
||||
{ |
||||
"web": { |
||||
"client_id": "540181629246-1horo9i4htamdbhiqar9rcbq33bqe2ob.apps.googleusercontent.com", |
||||
"project_id": "plated-inn-369901", |
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", |
||||
"token_uri": "https://oauth2.googleapis.com/token", |
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", |
||||
"client_secret": "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", |
||||
"redirect_uris": ["https://drive.aapanel.com"] |
||||
} |
||||
} |
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,310 @@ |
||||
<style> |
||||
.upyunCon { |
||||
height: 428px; |
||||
} |
||||
|
||||
.up-place { |
||||
height: 62px; |
||||
border-bottom: 1px solid #ddd; |
||||
} |
||||
|
||||
.up-place .btn { |
||||
border-radius: 0; |
||||
} |
||||
|
||||
.up-place .place-input { |
||||
background-color: #f3f3f3; |
||||
border: 1px solid #ccc; |
||||
height: 30px; |
||||
line-height: 28px; |
||||
overflow: hidden; |
||||
margin: 1px 0 0 -1px; |
||||
width: 340px; |
||||
} |
||||
|
||||
.place-input ul { |
||||
display: inline-block; |
||||
position: relative; |
||||
width: auto; |
||||
} |
||||
|
||||
.place-input ul li { |
||||
background: url("/static/img/ico/ico-ltr.png") no-repeat right center; |
||||
float: left; |
||||
padding-left: 10px; |
||||
padding-right: 18px; |
||||
} |
||||
|
||||
.place-input ul li a { |
||||
height: 28px; |
||||
cursor: pointer; |
||||
display: inline-block; |
||||
} |
||||
|
||||
.upyunlist { |
||||
height: 516px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.up-bottom { |
||||
background-color: #fafafa; |
||||
border-top: 1px solid #eee; |
||||
bottom: 0; |
||||
position: absolute; |
||||
width: 100%; |
||||
} |
||||
|
||||
.up-use { |
||||
line-height: 50px |
||||
} |
||||
|
||||
.list-list .cursor span { |
||||
line-height: 30px; |
||||
} |
||||
|
||||
.btn-title { |
||||
margin-top: 1px |
||||
} |
||||
|
||||
.tip { |
||||
font-size: 10px; |
||||
font-style: oblique; |
||||
color: green; |
||||
} |
||||
</style> |
||||
<div class="upyunCon"> |
||||
<div class="up-place pd15"> |
||||
<button id="backBtn" class="btn btn-default btn-sm glyphicon glyphicon-arrow-left pull-left" title="后退"></button> |
||||
<input id="myPath" type="hidden" value=""> |
||||
<input id="curPath" type="hidden" value=""> |
||||
<div class="place-input pull-left"> |
||||
<div style="width:1400px;height:28px"><ul></ul></div> |
||||
</div> |
||||
<button class="refreshBtn btn btn-default btn-sm glyphicon glyphicon-refresh pull-left mr20" title="刷新" style="margin-left:-1px;"></button> |
||||
<button class="btn btn-default btn-sm pull-right btn-title" onclick="authApi()">授权</button> |
||||
<button class="btn btn-default btn-sm pull-right mr20 btn-title" onclick="createDir()">新建文件夹</button> |
||||
</div> |
||||
|
||||
<div class="upyunlist pd15"> |
||||
<div class="divtable" style="margin-bottom:15px"> |
||||
<table class="table table-hover"> |
||||
<thead><tr><th>名称</th><th>大小</th><th>更新时间</th><th class="text-right">操作</th></tr></thead> |
||||
<tbody class="list-list"></tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<style type="text/css"> |
||||
.check_api { |
||||
padding: 20px; |
||||
} |
||||
|
||||
.up-place { |
||||
height: 62px; |
||||
border-bottom: 1px solid #ddd; |
||||
} |
||||
|
||||
.up-place .btn { |
||||
border-radius: 0; |
||||
} |
||||
|
||||
.up-place .place-input { |
||||
background-color: #f3f3f3; |
||||
border: 1px solid #ccc; |
||||
height: 30px; |
||||
line-height: 28px; |
||||
overflow: hidden; |
||||
margin: 1px 0 0 -1px; |
||||
width: 340px; |
||||
} |
||||
|
||||
.place-input ul { |
||||
display: inline-block; |
||||
position: relative; |
||||
width: auto; |
||||
} |
||||
|
||||
.place-input ul li { |
||||
background: url("/static/img/ico/ico-ltr.png") no-repeat right center; |
||||
float: left; |
||||
padding-left: 10px; |
||||
padding-right: 18px; |
||||
} |
||||
|
||||
.place-input ul li a { |
||||
height: 28px; |
||||
cursor: pointer; |
||||
display: inline-block; |
||||
} |
||||
|
||||
.upyunlist { |
||||
height: 546px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.up-bottom { |
||||
background-color: #fafafa; |
||||
border-top: 1px solid #eee; |
||||
bottom: 0; |
||||
position: absolute; |
||||
width: 100%; |
||||
} |
||||
|
||||
.up-use { |
||||
line-height: 50px |
||||
} |
||||
|
||||
.list-list .cursor span { |
||||
line-height: 30px; |
||||
} |
||||
|
||||
.btn-title { |
||||
margin-top: 1px |
||||
} |
||||
|
||||
.step_item{ |
||||
clear: both; |
||||
} |
||||
|
||||
.step_item .serial_box{ |
||||
display: inline-block; |
||||
clear: both; |
||||
} |
||||
|
||||
.step_item .serial{ |
||||
width: 70px; |
||||
height: 30px; |
||||
line-height: 30px; |
||||
text-align: center; |
||||
display: inline-block; |
||||
float: left; |
||||
} |
||||
.step_item .serial span{ |
||||
display: inline-block; |
||||
width: 30px; |
||||
height: 30px; |
||||
text-align: center; |
||||
line-height: 28px; |
||||
font-size: 11px; |
||||
border-radius: 50%; |
||||
color: #20a53a; |
||||
border: 2px solid #20a53a; |
||||
} |
||||
.step_item .serial_title{ |
||||
margin-bottom: 10px; |
||||
font-size: 15px; |
||||
line-height: 30px; |
||||
color: #666; |
||||
} |
||||
.step_two_url{ |
||||
display: inline-block; |
||||
overflow: hidden; |
||||
width: 380px; |
||||
/*text-overflow: ellipsis;*/ |
||||
white-space: nowrap; |
||||
height: 35px; |
||||
line-height: 35px; |
||||
margin-right: 15px; |
||||
border-radius: 2px; |
||||
padding: 0 10px; |
||||
float: left; |
||||
width:360px; |
||||
padding-right: 35px; |
||||
} |
||||
.btn_btlink{ |
||||
display: inline-block; |
||||
padding: 5px 10px; |
||||
font-size: 12px; |
||||
line-height: 1.5; |
||||
border-radius: 3px; |
||||
text-align: center; |
||||
white-space: nowrap; |
||||
vertical-align: middle; |
||||
cursor: pointer; |
||||
border: 1px solid #20a53a; |
||||
color: #fff; |
||||
background-color: #20a53a; |
||||
margin-right:10px; |
||||
} |
||||
.btn_btlink:hover{ |
||||
color: #fff; |
||||
background-color: #10952a; |
||||
border-color: #398439; |
||||
} |
||||
.btn_btlink a:visited{ |
||||
color: #fff; |
||||
background-color: #10952a; |
||||
border-color: #398439; |
||||
} |
||||
.view_video{ |
||||
margin-bottom: 10px; |
||||
} |
||||
.view_video ul li{ |
||||
line-height: 20px; |
||||
font-size: 13px; |
||||
} |
||||
.setp_one i{ |
||||
position: absolute; |
||||
top: 8px; |
||||
left: 25px; |
||||
width: 30px; |
||||
height: 30px; |
||||
} |
||||
.google_drive{ |
||||
width:465px; |
||||
height:100px; |
||||
margin-bottom:10px; |
||||
} |
||||
</style> |
||||
<script type="text/html" id="check_api"> |
||||
<div class="check_api"> |
||||
<div class="step_two"> |
||||
<div class="step_item"> |
||||
<div class="serial"><span>1</span></div> |
||||
<div class="serial_box"> |
||||
<div class="serial_title">阅读简易操作教程:如何获取Google Drive授权?</div> |
||||
<div class="serial_conter"> |
||||
<div class="view_video"> |
||||
<ul> |
||||
<li>1. 点击下面第<div class="serial" style="float: none;width: 45px;"><span>2</span></div>步中的 打开授权链接。<li> |
||||
<li>2. 在新窗口页面上登录Google Drive账号。阅读授权权限,并同意。<li> |
||||
<li>3. 页面跳转后,将浏览器的地址栏地址复制到第<div class="serial" style="float: none;width: 45px;"><span>3</span></div>步的文本框中。<li> |
||||
<li>4. 点击 获取授权,随即完成授权。<li> |
||||
</ul> |
||||
</div> |
||||
<hr/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="step_item pb15"> |
||||
<div class="serial"><span>2</span></div> |
||||
<div class="serial_box"> |
||||
<div class="serial_title">操作1:👇打开授权链接,根据网页提示对插件进行授权。</div> |
||||
<div class="serial_conter step_two" style="width: 500px;"> |
||||
<input class="bt-input-text mr5 step_two_url" type="text" disabled> |
||||
<span class="ico-copy mr10" data-copy="" style="vertical-align: middle;cursor: pointer;margin-left: -37px;margin-right: 20px;"></span> |
||||
<a href="" class="btn_btlink open_btlink" target="_blank" style="padding: 7px 10px;">打开授权链接</a> |
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
<div class="step_item"> |
||||
<div class="serial"><span>3</span></div> |
||||
<div class="serial_box"> |
||||
<div class="serial_title">操作2:复制回浏览器跳转后的地址:</div> |
||||
<div class="serial_conter"> |
||||
<textarea row="3" placeholder="验证URL地址" class="bt-input-text google_drive" style="resize: none;"/></br> |
||||
<button type="button" class="btn btn-success btn-sm set_auth_btn">获取授权</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</script> |
||||
<script type="text/javascript" src="/plugins/file?name=gdrive&f=js/gdrive.js"></script> |
||||
<script type="text/javascript"> |
||||
$.getScript( "/plugins/file?name=gdrive&f=js/gdrive.js", function(){ |
||||
gdList(''); |
||||
}); |
||||
</script> |
@ -0,0 +1,342 @@ |
||||
# coding:utf-8 |
||||
|
||||
import sys |
||||
import io |
||||
import os |
||||
import time |
||||
import re |
||||
import json |
||||
|
||||
|
||||
# print(sys.platform) |
||||
if sys.platform != "darwin": |
||||
os.chdir("/www/server/mdserver-web") |
||||
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core") |
||||
import mw |
||||
import db |
||||
|
||||
_ver = sys.version_info |
||||
is_py2 = (_ver[0] == 2) |
||||
is_py3 = (_ver[0] == 3) |
||||
|
||||
DEBUG = False |
||||
|
||||
if is_py2: |
||||
reload(sys) |
||||
sys.setdefaultencoding('utf-8') |
||||
|
||||
app_debug = False |
||||
if mw.isAppleSystem(): |
||||
app_debug = True |
||||
|
||||
|
||||
def getPluginName(): |
||||
return 'gdrive' |
||||
|
||||
|
||||
def getPluginDir(): |
||||
return mw.getPluginDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getServerDir(): |
||||
return mw.getServerDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def in_array(name, arr=[]): |
||||
for x in arr: |
||||
if name == x: |
||||
return True |
||||
return False |
||||
|
||||
|
||||
sys.path.append(getPluginDir() + "/class") |
||||
from gdriveclient import gdriveclient |
||||
|
||||
|
||||
gd = gdriveclient(getPluginDir(), getServerDir()) |
||||
gd.setDebug(False) |
||||
|
||||
|
||||
def getArgs(): |
||||
args = sys.argv[2:] |
||||
tmp = {} |
||||
args_len = len(args) |
||||
if args_len == 1: |
||||
t = args[0].strip('{').strip('}') |
||||
if t.strip() == '': |
||||
tmp = [] |
||||
else: |
||||
t = t.split(':', 1) |
||||
tmp[t[0]] = t[1] |
||||
elif args_len > 1: |
||||
for i in range(len(args)): |
||||
t = args[i].split(':', 1) |
||||
tmp[t[0]] = t[1] |
||||
return tmp |
||||
|
||||
|
||||
def checkArgs(data, ck=[]): |
||||
for i in range(len(ck)): |
||||
if not ck[i] in data: |
||||
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) |
||||
return (True, mw.returnJson(True, 'ok')) |
||||
|
||||
|
||||
def status(): |
||||
return 'start' |
||||
|
||||
|
||||
def isAuthApi(): |
||||
cfg = getServerDir() + "/token.json" |
||||
if os.path.exists(cfg): |
||||
return True |
||||
return False |
||||
|
||||
|
||||
def getConf(): |
||||
if not isAuthApi(): |
||||
sign_in_url, state = gd.get_sign_in_url() |
||||
return mw.returnJson(False, "未授权!", {'auth_url': sign_in_url}) |
||||
return mw.returnJson(True, "OK") |
||||
|
||||
|
||||
def setAuthUrl(): |
||||
args = getArgs() |
||||
data = checkArgs(args, ['url']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
url = args['url'] |
||||
|
||||
try: |
||||
if url.startswith("http://"): |
||||
url = url.replace("http://", "https://") |
||||
token = gd.set_auth_url(url) |
||||
# gd.store_token(token) |
||||
# gd.store_user() |
||||
return mw.returnJson(True, "授权成功!") |
||||
except Exception as e: |
||||
return mw.returnJson(False, "授权失败2!:" + str(e)) |
||||
return mw.returnJson(False, "授权失败!:" + str(e)) |
||||
|
||||
|
||||
def clearAuth(): |
||||
cfg = getServerDir() + "/user.conf" |
||||
if os.path.exists(cfg): |
||||
os.remove(cfg) |
||||
|
||||
token = getServerDir() + "/token.pickle" |
||||
if os.path.exists(token): |
||||
os.remove(token) |
||||
|
||||
return mw.returnJson(True, "清空授权成功!") |
||||
|
||||
|
||||
def getList(): |
||||
if not isAuthApi(): |
||||
return mw.returnJson(False, "未配置,请点击`授权`", []) |
||||
|
||||
args = getArgs() |
||||
data = checkArgs(args, ['file_id']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
try: |
||||
flist = gd.get_list(args['file_id']) |
||||
return mw.returnJson(True, "ok", flist) |
||||
except Exception as e: |
||||
return mw.returnJson(False, str(e), []) |
||||
|
||||
|
||||
def createDir(): |
||||
if not isAuthApi(): |
||||
return mw.returnJson(False, "未配置,请点击`授权`", []) |
||||
|
||||
args = getArgs() |
||||
data = checkArgs(args, ['parents', 'name']) |
||||
if not data[0]: |
||||
return data[1] |
||||
isok = gd.create_folder(args['name'], args['parents']) |
||||
if isok: |
||||
return mw.returnJson(True, "创建成功") |
||||
return mw.returnJson(False, "创建失败") |
||||
|
||||
|
||||
def deleteDir(): |
||||
args = getArgs() |
||||
data = checkArgs(args, ['dir_name', 'path']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
isok = gd.delete_file_by_id(args['dir_name']) |
||||
if isok: |
||||
return mw.returnJson(True, "删除成功") |
||||
return mw.returnJson(False, "文件不为空,删除失败!") |
||||
|
||||
|
||||
def deleteFile(): |
||||
args = getArgs() |
||||
data = checkArgs(args, ['path', 'filename']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
isok = gd.delete_file(args['filename']) |
||||
if isok: |
||||
return mw.returnJson(True, "删除成功") |
||||
return mw.returnJson(False, "删除失败") |
||||
|
||||
|
||||
def findPathName(path, filename): |
||||
f = os.scandir(path) |
||||
l = [] |
||||
for ff in f: |
||||
t = {} |
||||
if ff.name.find(filename) > -1: |
||||
t['filename'] = path + '/' + ff.name |
||||
l.append(t) |
||||
return l |
||||
|
||||
|
||||
def backupAllFunc(stype): |
||||
if not isAuthApi(): |
||||
mw.echoInfo("未授权API,无法使用!!!") |
||||
return '' |
||||
|
||||
os.chdir(mw.getRunDir()) |
||||
backup_dir = mw.getBackupDir() |
||||
run_dir = mw.getRunDir() |
||||
|
||||
stype = sys.argv[1] |
||||
name = sys.argv[2] |
||||
num = sys.argv[3] |
||||
|
||||
prefix_dict = { |
||||
"site": "web", |
||||
"database": "db", |
||||
"path": "path", |
||||
} |
||||
|
||||
backups = [] |
||||
sql = db.Sql() |
||||
|
||||
# print("stype:", stype) |
||||
# 提前获取-清理多余备份 |
||||
if stype == 'site': |
||||
pid = sql.table('sites').where('name=?', (name,)).getField('id') |
||||
backups = sql.table('backup').where( |
||||
'type=? and pid=?', ('0', pid)).field('id,filename').select() |
||||
if stype == 'database': |
||||
db_path = mw.getServerDir() + '/mysql' |
||||
pid = mw.M('databases').dbPos(db_path, 'mysql').where( |
||||
'name=?', (name,)).getField('id') |
||||
backups = sql.table('backup').where( |
||||
'type=? and pid=?', ('1', pid)).field('id,filename').select() |
||||
if stype == 'path': |
||||
backup_path = backup_dir + '/path' |
||||
_name = 'path_{}'.format(os.path.basename(name)) |
||||
backups = findPathName(backup_path, _name) |
||||
|
||||
# 其他类型关系性数据库(mysql类的) |
||||
if stype.find('database_') > -1: |
||||
plugin_name = stype.replace('database_', '') |
||||
db_path = mw.getServerDir() + '/' + plugin_name |
||||
pid = mw.M('databases').dbPos(db_path, 'mysql').where( |
||||
'name=?', (name,)).getField('id') |
||||
backups = sql.table('backup').where( |
||||
'type=? and pid=?', ('1', pid)).field('id,filename').select() |
||||
|
||||
args = stype + " " + name + " " + num |
||||
cmd = 'python3 ' + run_dir + '/scripts/backup.py ' + args |
||||
if stype.find('database_') > -1: |
||||
plugin_name = stype.replace('database_', '') |
||||
args = "database " + name + " " + num |
||||
cmd = 'python3 ' + run_dir + '/plugins/' + \ |
||||
plugin_name + '/scripts/backup.py ' + args |
||||
|
||||
if stype == 'path': |
||||
name = os.path.basename(name) |
||||
|
||||
# print("cmd:", cmd) |
||||
os.system(cmd) |
||||
|
||||
# 开始执行上传信息. |
||||
if stype.find('database_') > -1: |
||||
bk_name = 'database' |
||||
plugin_name = stype.replace('database_', '') |
||||
bk_prefix = plugin_name + '/db' |
||||
stype = 'database' |
||||
else: |
||||
bk_prefix = prefix_dict[stype] |
||||
bk_name = stype |
||||
|
||||
find_path = backup_dir + '/' + bk_name + '/' + bk_prefix + '_' + name |
||||
find_new_file = "ls " + find_path + \ |
||||
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'" |
||||
|
||||
# print(find_new_file) |
||||
|
||||
filename = mw.execShell(find_new_file)[0].strip() |
||||
if filename == "": |
||||
mw.echoInfo("not find upload file!") |
||||
return False |
||||
|
||||
mw.echoInfo("准备上传文件 {}".format(filename)) |
||||
mw.echoStart('开始上传') |
||||
gd.upload_file(filename, stype) |
||||
mw.echoEnd('上传成功') |
||||
|
||||
# print(backups) |
||||
backups = sorted(backups, key=lambda x: x['filename'], reverse=False) |
||||
mw.echoStart('开始删除远程备份') |
||||
num = int(num) |
||||
sep = len(backups) - num |
||||
if sep > -1: |
||||
for backup in backups: |
||||
fn = os.path.basename(backup['filename']) |
||||
gd.delete_file(fn, stype) |
||||
mw.echoInfo("---已清理远程过期备份文件:" + fn) |
||||
sep -= 1 |
||||
if sep < 0: |
||||
break |
||||
mw.echoEnd('结束删除远程备份') |
||||
|
||||
return '' |
||||
|
||||
|
||||
def installPreInspection(): |
||||
return 'ok' |
||||
|
||||
if __name__ == "__main__": |
||||
func = sys.argv[1] |
||||
if func == 'status': |
||||
print(status()) |
||||
elif func == 'start': |
||||
print(start()) |
||||
elif func == 'stop': |
||||
print(stop()) |
||||
elif func == 'restart': |
||||
print(restart()) |
||||
elif func == 'reload': |
||||
print(reload()) |
||||
elif func == 'install_pre_inspection': |
||||
print(installPreInspection()) |
||||
elif func == 'conf': |
||||
print(getConf()) |
||||
elif func == 'set_auth_url': |
||||
print(setAuthUrl()) |
||||
elif func == 'clear_auth': |
||||
print(clearAuth()) |
||||
elif func == "get_list": |
||||
print(getList()) |
||||
elif func == "create_dir": |
||||
print(createDir()) |
||||
elif func == "delete_dir": |
||||
print(deleteDir()) |
||||
elif func == 'delete_file': |
||||
print(deleteFile()) |
||||
elif in_array(func, ['site', 'database', 'path']) or func.find('database_') > -1: |
||||
print(backupAllFunc(func)) |
||||
else: |
||||
print('error') |
@ -0,0 +1,19 @@ |
||||
{ |
||||
"hook":["backup"], |
||||
"id":998, |
||||
"title":"谷歌云网盘", |
||||
"tip":"lib", |
||||
"name":"gdrive", |
||||
"type":"扩展", |
||||
"ps":"备份你的数据到谷歌云网盘", |
||||
"versions":"2.0", |
||||
"shell":"install.sh", |
||||
"checks": "server/gdrive", |
||||
"path":"server/gdrive", |
||||
"author":"google", |
||||
"home":"https://drive.google.com/", |
||||
"api_doc":"https://developers.google.com/drive/api/guides/about-sdk?hl=zh_CN", |
||||
"api_doc2":"https://developers.google.cn/drive/api/reference/rest/v3/comments/list?hl=zh-cn", |
||||
"date":"2022-06-26", |
||||
"pid":"4" |
||||
} |
@ -0,0 +1,79 @@ |
||||
#!/bin/bash |
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin |
||||
export PATH |
||||
|
||||
curPath=`pwd` |
||||
rootPath=$(dirname "$curPath") |
||||
rootPath=$(dirname "$rootPath") |
||||
serverPath=$(dirname "$rootPath") |
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl |
||||
|
||||
PATH=$PATH:${rootPath}/bin |
||||
export PATH |
||||
|
||||
VERSION=$2 |
||||
|
||||
Install_App() |
||||
{ |
||||
tmp_ping=`ping -c 1 google.com 2>&1` |
||||
echo $tmp_ping |
||||
if [ $? -eq 0 ];then |
||||
tmp=`python -V 2>&1|awk '{print $2}'` |
||||
pVersion=${tmp:0:3} |
||||
|
||||
which pip |
||||
if [ $? -eq 0 ];then |
||||
tmp=$(pip list|grep google-api-python-client|awk '{print $2}') |
||||
if [ "$tmp" != '2.39.0' ];then |
||||
pip install --upgrade google-api-python-client |
||||
# pip uninstall google-api-python-client -y |
||||
pip install -I google-api-python-client==2.39.0 -i https://pypi.Python.org/simple |
||||
fi |
||||
tmp=$(pip list|grep google-auth-httplib2|awk '{print $2}') |
||||
if [ "$tmp" != '0.1.0' ];then |
||||
pip uninstall google-auth-httplib2 -y |
||||
pip install -I google-auth-httplib2==0.1.0 -i https://pypi.Python.org/simple |
||||
fi |
||||
tmp=$(pip list|grep google-auth-oauthlib|awk '{print $2}') |
||||
if [ "$tmp" != '0.5.0' ];then |
||||
# pip uninstall google-auth-oauthlib -y |
||||
pip install -I google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple |
||||
fi |
||||
tmp=$(pip list|grep -E '^httplib2'|awk '{print $2}') |
||||
if [ "$tmp" != '0.18.1' ];then |
||||
# pip uninstall httplib2 -y |
||||
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple |
||||
fi |
||||
else |
||||
pip install -I pyOpenSSL |
||||
pip install -I google-api-python-client==2.39.0 google-auth-httplib2==0.1.0 google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple |
||||
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple |
||||
fi |
||||
echo '正在安装脚本文件...' > $install_tmp |
||||
|
||||
mkdir -p $serverPath/gdrive |
||||
echo "${VERSION}" > $serverPath/gdrive/version.pl |
||||
echo '安装完成' > $install_tmp |
||||
else |
||||
echo '服务器连接不上谷歌云!安装失败!' > $install_tmp |
||||
exit 1 |
||||
fi |
||||
} |
||||
|
||||
Uninstall_App() |
||||
{ |
||||
rm -rf $serverPath/gdrive |
||||
echo '卸载完成' > $install_tmp |
||||
} |
||||
|
||||
|
||||
action=$1 |
||||
type=$2 |
||||
|
||||
echo $action $type |
||||
if [ "${action}" == 'install' ];then |
||||
Install_App |
||||
else |
||||
Uninstall_App |
||||
fi |
@ -0,0 +1,260 @@ |
||||
|
||||
function gdPost(method,args,callback){ |
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){ |
||||
_args = JSON.stringify(toArrayObject(args)); |
||||
} else { |
||||
_args = JSON.stringify(args); |
||||
} |
||||
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); |
||||
$.post('/plugins/run', {name:'gdrive', func:method, args:_args}, function(data) { |
||||
layer.close(loadT); |
||||
if (!data.status){ |
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); |
||||
return; |
||||
} |
||||
|
||||
if(typeof(callback) == 'function'){ |
||||
callback(data); |
||||
} |
||||
},'json');
|
||||
} |
||||
|
||||
|
||||
function createDir(){ |
||||
layer.open({ |
||||
type: 1, |
||||
area: "400px", |
||||
title: "创建目录", |
||||
closeBtn: 1, |
||||
shift: 5, |
||||
shadeClose: false, |
||||
btn: ['确定','取消'], |
||||
content:'<div class="bingfa bt-form c6" style="padding-bottom: 10px;">\ |
||||
<p>\ |
||||
<span class="span_tit">目录名称:</span>\ |
||||
<input style="width: 200px;" type="text" name="newPath" value="">\ |
||||
</p>\ |
||||
</div>', |
||||
success:function(){ |
||||
$("input[name='newPath']").focus().keyup(function(e){ |
||||
if(e.keyCode == 13) $(".layui-layer-btn0").click(); |
||||
}); |
||||
}, |
||||
yes:function(index,layero){ |
||||
var name = $("input[name='newPath']").val(); |
||||
if(name == ''){ |
||||
layer.msg('目录名称不能为空!',{icon:2}); |
||||
return; |
||||
} |
||||
var parents = $("#myPath").val(); |
||||
var cur_file_id = $('#curPath').val(); |
||||
if (cur_file_id!=''){ |
||||
parents = cur_file_id; |
||||
} |
||||
|
||||
var dirname = name; |
||||
var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']}); |
||||
gdPost('create_dir', {parents:parents,name:dirname}, function(data){ |
||||
layer.close(loadT); |
||||
var rdata = $.parseJSON(data.data); |
||||
if(rdata.status) { |
||||
showMsg(rdata.msg, function(){ |
||||
layer.close(index); |
||||
var file_id = $('#myPath').val(); |
||||
if (cur_file_id!=''){ |
||||
file_id = cur_file_id; |
||||
} |
||||
gdList(file_id); |
||||
} ,{icon:1}, 2000); |
||||
} else{ |
||||
layer.msg(rdata.msg,{icon:2}); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
//设置API
|
||||
function authApi(){ |
||||
|
||||
gdPost('conf', {}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
|
||||
// console.log(rdata);
|
||||
// console.log(rdata.data.auth_url);
|
||||
var apicon = ''; |
||||
if (rdata.status){ |
||||
|
||||
var html = ''; |
||||
html += '<button id="clear_auth" onclick="clearAuth();" class="btn btn-default btn-sm">清空配置</button>'; |
||||
|
||||
var loadOpen = layer.open({ |
||||
type: 1, |
||||
title: '已授权', |
||||
area: '240px', |
||||
content:'<div class="change-default pd20">'+html+'</div>', |
||||
success: function(){ |
||||
$('#clear_auth').click(function(){ |
||||
gdPost('clear_auth', {}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
showMsg(rdata.msg,function(){ |
||||
layer.close(loadOpen); |
||||
gdList(''); |
||||
},{icon:rdata.status?1:2},2000); |
||||
});
|
||||
});
|
||||
} |
||||
}); |
||||
return true; |
||||
|
||||
} else{ |
||||
apicon = '<div class="new_form">'+$("#check_api").html()+'</div>'; |
||||
} |
||||
|
||||
var layer_auth = layer.open({ |
||||
type: 1, |
||||
area: "620px", |
||||
title: "Google Drive 授权", |
||||
closeBtn: 1, |
||||
shift: 5, |
||||
shadeClose: false, |
||||
content:apicon, |
||||
success:function(layero,index){ |
||||
// console.log(layero,index);
|
||||
if (!rdata.status){ |
||||
$('.check_api .step_two_url').val(rdata.data['auth_url']); |
||||
$('.check_api .open_btlink').attr('href',rdata.data['auth_url']); |
||||
|
||||
$('.check_api .ico-copy').click(function(){ |
||||
copyPass(rdata.data['auth_url']); |
||||
}); |
||||
|
||||
$('.check_api .set_auth_btn').click(function(){ |
||||
|
||||
var url = $('.check_api .google_drive').val(); |
||||
if ( url == ''){ |
||||
layer.msg("验证URL不能为空",{icon:2}); |
||||
return; |
||||
} |
||||
// console.log(url);
|
||||
gdPost('set_auth_url', {url:url}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
var show_time = 2000; |
||||
if (!rdata.status){ |
||||
show_time = 10000; |
||||
} |
||||
|
||||
showMsg(rdata.msg,function(){ |
||||
if (rdata.status){ |
||||
layer.close(layer_auth); |
||||
gdList(''); |
||||
} |
||||
},{icon:rdata.status?1:2},show_time); |
||||
}); |
||||
}); |
||||
|
||||
|
||||
} |
||||
|
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
//计算当前目录偏移
|
||||
function upPathLeft(){ |
||||
var UlWidth = $(".place-input ul").width(); |
||||
var SpanPathWidth = $(".place-input").width() - 20; |
||||
var Ml = UlWidth - SpanPathWidth; |
||||
if(UlWidth > SpanPathWidth ){ |
||||
$(".place-input ul").css("left",-Ml) |
||||
} |
||||
else{ |
||||
$(".place-input ul").css("left",0) |
||||
} |
||||
} |
||||
|
||||
function getGDTime(a) { |
||||
return new Date(a).format("yyyy/MM/dd hh:mm:ss") |
||||
} |
||||
|
||||
function gdList(file_id){ |
||||
$('#curPath').val(file_id); |
||||
gdPost('get_list', {file_id:file_id}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
console.log(rdata); |
||||
if(rdata.status === false){ |
||||
showMsg(rdata.msg,function(){ |
||||
authApi(); |
||||
},{icon:2},2000); |
||||
return; |
||||
} |
||||
|
||||
var mlist = rdata.data; |
||||
var listBody = ''; |
||||
var listFiles = ''; |
||||
for(var i=0;i<mlist.length;i++){ |
||||
if(mlist[i].size == null){ |
||||
listFiles += '<tr><td class="cursor" onclick="gdList(\''+(mlist[i].id).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist[i].name+'</span></td>\ |
||||
<td>-</td>\ |
||||
<td>-</td>\ |
||||
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist[i].id+'\', true)">删除</a></td></tr>' |
||||
}else{ |
||||
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span><span>'+mlist[i].name+'</span></td>\ |
||||
<td>'+toSize(mlist[i].size)+'</td>\ |
||||
<td>'+getGDTime(mlist[i].createdTime)+'</td>\ |
||||
<td class="text-right"><a target="_blank" href="'+mlist[i].webViewLink+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist[i].name+'\', false)">删除</a></td></tr>' |
||||
} |
||||
} |
||||
listBody += listFiles; |
||||
var pathLi = '<li><a title="根目录" onclick="gdList(\'\')">根目录</a></li>'; |
||||
|
||||
if (mlist.length>0){ |
||||
$('#myPath').val(mlist[0]['parents'][0]); |
||||
} |
||||
|
||||
$(".upyunCon .place-input ul").html(pathLi); |
||||
$(".upyunlist .list-list").html(listBody); |
||||
|
||||
$('#backBtn').unbind().click(function() { |
||||
gdList(''); |
||||
}); |
||||
|
||||
$('.upyunCon .refreshBtn').unbind().click(function(){ |
||||
var file_id = $('#myPath').val(); |
||||
gdList(file_id); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
|
||||
//删除文件
|
||||
function deleteFile(name, is_dir){ |
||||
if (is_dir === false){ |
||||
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){ |
||||
var path = $("#myPath").val(); |
||||
var filename = name; |
||||
gdPost('delete_file', {filename:filename,path:path}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
showMsg(rdata.msg,function(){ |
||||
var file_id = $('#myPath').val(); |
||||
gdList(file_id); |
||||
},{icon:rdata.status?1:2},2000); |
||||
}); |
||||
}); |
||||
} else { |
||||
safeMessage('删除文件夹','删除后将无法恢复,真的要删除文件资源['+name+']吗?',function(){ |
||||
var path = $("#myPath").val(); |
||||
gdPost('delete_dir', {dir_name:name,path:path}, function(rdata){ |
||||
var rdata = $.parseJSON(rdata.data); |
||||
showMsg(rdata.msg,function(){ |
||||
var file_id = $('#myPath').val(); |
||||
gdList(file_id); |
||||
},{icon:rdata.status?1:2},2000); |
||||
}); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,113 @@ |
||||
#!/usr/bin/python |
||||
# coding: utf-8 |
||||
|
||||
# python3 plugins/gdrive/t/test.py |
||||
# https://console.cloud.google.com/apis/credentials/consent?project=plated-inn-369901 |
||||
|
||||
# https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdrive.aapanel.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=I2da4aZUwqgmikrgrqAwwSjyoEHVs1&access_type=offline&prompt=consent&include_granted_scopes=false |
||||
|
||||
|
||||
# https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/08125e6b-6502-4ac9-9548-ad682f00848d/objectId/62b1d655-9828-47ed-be99-65eb18c3a929/isMSAApp~/false/defaultBlade/Overview/appSignInAudience/AzureADandPersonalMicrosoftAccount/servicePrincipalCreated~/true |
||||
|
||||
# 0WA8Q~sZkZFZKv50ryP4ux~.fpVtbHw7BuTZmbQB |
||||
# client_id:d9878fac-8526-4ff6-8036-e1c92dd9dd80 |
||||
|
||||
# 08125e6b-6502-4ac9-9548-ad682f00848d |
||||
|
||||
|
||||
# /drive/v2internal/files?openDrive=false&reason=102&syncType=0&errorRecovery=false&q=trashed = false and '1-z6gUXseXmlxmntvkLzOe_tYFT5tdhM9' in parents&fields=kind,nextPageToken,items(kind,modifiedDate,hasVisitorPermissions,containsUnsubscribedChildren,modifiedByMeDate,lastViewedByMeDate,alternateLink,fileSize,owners(kind,permissionId,emailAddressFromAccount,id),lastModifyingUser(kind,permissionId,emailAddressFromAccount,id),customerId,ancestorHasAugmentedPermissions,hasThumbnail,thumbnailVersion,title,id,resourceKey,abuseIsAppealable,abuseNoticeReason,shared,accessRequestsCount,sharedWithMeDate,userPermission(role),explicitlyTrashed,mimeType,quotaBytesUsed,copyable,subscribed,folderColor,hasChildFolders,fileExtension,primarySyncParentId,sharingUser(kind,permissionId,emailAddressFromAccount,id),flaggedForAbuse,folderFeatures,spaces,sourceAppId,recency,recencyReason,version,actionItems,teamDriveId,hasAugmentedPermissions,createdDate,primaryDomainName,organizationDisplayName,passivelySubscribed,trashingUser(kind,permissionId,emailAddressFromAccount,id),trashedDate,parents(id),capabilities(canMoveItemIntoTeamDrive,canUntrash,canModifyContentRestriction,canMoveItemWithinTeamDrive,canMoveItemOutOfTeamDrive,canDeleteChildren,canTrashChildren,canRequestApproval,canReadCategoryMetadata,canEditCategoryMetadata,canAddMyDriveParent,canRemoveMyDriveParent,canShareChildFiles,canShareChildFolders,canRead,canMoveItemWithinDrive,canMoveChildrenWithinDrive,canAddFolderFromAnotherDrive,canChangeSecurityUpdateEnabled,canBlockOwner,canReportSpamOrAbuse,canCopy,canDownload,canEdit,canAddChildren,canDelete,canRemoveChildren,canShare,canTrash,canRename,canReadTeamDrive,canMoveTeamDriveItem),contentRestrictions(readOnly),approvalMetadata(approvalVersion,approvalSummaries,hasIncomingApproval),shortcutDetails(targetId,targetMimeType,targetLookupStatus,targetFile,canRequestAccessToTarget),spamMetadata(markedAsSpamDate,inSpamView),labels(starred,trashed,restricted,viewed)),incompleteSearch&appDataFilter=NO_APP_DATA&spaces=drive&maxResults=200&supportsTeamDrives=true&includeItemsFromAllDrives=true&corpora=default&orderBy=folder,title_natural asc&retryCount=0&key=AIzaSyD_InbmSFufIEps5UAt2NmB_3LvBH3Sz_8 HTTP/1.1 |
||||
|
||||
# http://localhost/?code=M.C106_BAY.2.3e12c859-6107-0c5b-9ef4-14b3fb8269ba&state=JzHdzHXmA7x6zl7Be6cJ6uOlf9Bg69 |
||||
|
||||
|
||||
# python3 /www/mdserver-web/plugins/gdrive/index.py site zzzvps.com 3 |
||||
# python3 /www/mdserver-web/plugins/gdrive/index.py database t1 3 |
||||
# python3 /www/server/mdserver-web/plugins/msonedrive/index.py path |
||||
# /Users/midoks/Desktop/dev/python 3 |
||||
|
||||
|
||||
import sys |
||||
import io |
||||
import os |
||||
import time |
||||
import re |
||||
import json |
||||
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core") |
||||
import mw |
||||
|
||||
|
||||
def getPluginName(): |
||||
return 'gdrive' |
||||
|
||||
|
||||
def getPluginDir(): |
||||
return mw.getPluginDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getServerDir(): |
||||
return mw.getServerDir() + '/' + getPluginName() |
||||
|
||||
|
||||
# print(getPluginDir()) |
||||
sys.path.append(getPluginDir() + "/class") |
||||
from gdriveclient import gdriveclient |
||||
|
||||
|
||||
gd = gdriveclient(getPluginDir(), getServerDir()) |
||||
gd.setDebug(True) |
||||
# sign_in_url, state = gd.get_sign_in_url() |
||||
# print(sign_in_url) |
||||
|
||||
# url = 'https://localhost/?state=GH2YZ1VeytzVB1BqJJpQZIBk2GGAub&code=4/0Adeu5BXnD2dQvXx8Sg0WPn1XiMpihcRBNaG1yaFKIo86gUiG7q65KU1MaNCxrj_f2bjkwQ&scope=https://www.googleapis.com/auth/drive.file' |
||||
# t = gd.set_auth_url(url) |
||||
# print(t) |
||||
|
||||
# def set_auth_url(url): |
||||
# try: |
||||
# if url.startswith("http://"): |
||||
# url = url.replace("http://", "https://") |
||||
# token = msodc.get_token_from_authorized_url( |
||||
# authorized_url=url) |
||||
# msodc.store_token(token) |
||||
# msodc.store_user() |
||||
# return mw.returnJson(True, "授权成功!") |
||||
# except Exception as e: |
||||
# print(e) |
||||
# return mw.returnJson(False, "授权失败2!:" + str(e)) |
||||
# return mw.returnJson(False, "授权失败!:" + str(e)) |
||||
|
||||
# url = 'http://localhost/?code=M.C106_BAY.2.310112f3-a158-c400-9667-d158cbd1de6c&state=jEJz0ucR9bpZYD9PGxp2GgRDotrzO6' |
||||
# token = set_auth_url(url) |
||||
# print(token) |
||||
|
||||
# token = msodc.get_token() |
||||
# print("token:", token) |
||||
|
||||
# t = gd.get_list('') |
||||
# print(t) |
||||
|
||||
# t = gd.get_id_list('1u7LjXGj1KoN-ltAdTRaib7IZJpsEnPdz') |
||||
# print(t) |
||||
|
||||
# t = gd.create_folder('backup_demo') |
||||
# print(t) |
||||
|
||||
# t = msodc.delete_object('backup') |
||||
# print(t) |
||||
|
||||
|
||||
# t = gd.upload_file('web_t1.cn_20230830_134549.tar.gz', 'site') |
||||
# print(t) |
||||
# print(gd.error_msg) |
||||
|
||||
# /Users/midoks/Desktop/mwdev/server/mdserver-web/paramiko.log |
||||
# backup/site/paramiko.log |
||||
# |-正在上传到 backup/site/paramiko.log... |
||||
# True |
||||
|
||||
|
||||
t = gd.upload_file( |
||||
'db_zzzvps_20230830_210727.sql.gz', 'datebase') |
||||
print(t) |
Loading…
Reference in new issue