Skip to content

Commit

Permalink
solve #3
Browse files Browse the repository at this point in the history
  • Loading branch information
gaowanliang committed Sep 5, 2021
1 parent 42a6b8d commit a8dd447
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 17 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[简体中文](docs/Readme_zh-cn.md)

# OneDriveShareLinkPushAria2
Extract download URLs from OneDrive or SharePoint share links and push them to aria2, even on systems without a GUI.
Extract download URLs from OneDrive or SharePoint share links and push them to aria2, even on systems without a GUI (such as Linux).

从OneDrive或SharePoint共享链接提取下载URL并将其推送到aria2,即使在无图形界面的系统中依然可以使用
从OneDrive或SharePoint共享链接提取下载URL并将其推送到aria2,即使在无图形界面的系统中(如Linux)依然可以使用

# Dependent

Expand All @@ -20,7 +20,7 @@ At present, this program supports the following download methods:
* Downloading multiple files with password for shared links
* Download of files in nested folders
* Download any file of your choice
* Viewing of more than 30 file lists (download mode planning)
* Viewing of more than 30 file lists
* xxx.sharepoint.com Downloads with share links
* xxx-my.sharepoint.cn Download of share links (theoretically supported)

Expand Down Expand Up @@ -63,3 +63,5 @@ Usage is similar to the above.

# Note
Before you use it, clone the whole project with `git clone https://github.com/gaowanliang/OneDriveShareLinkPushAria2.git` to use it. havepassword.py depends on main.py, if you want to use the version that requires a password If you want to use a version that requires a password, you need to `pip install pyppeteer`

The basic functions of this program have been realized. For a long time, if the software is not unusable, it will not be maintained. If there is a running problem, please bring a download link when raising the issue. The bug type issue that does not provide a download link will not be solved.
4 changes: 3 additions & 1 deletion docs/Readme_zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ pyppeteer==0.2.5
使用方法和上面类似。

# 注意
使用前,使用 `git clone https://github.com/gaowanliang/OneDriveShareLinkPushAria2.git` 将项目整个克隆,才能使用,havepassword.py依赖于main.py,如果要使用需要密码的版本,需要 `pip install pyppeteer`
使用前,使用 `git clone https://github.com/gaowanliang/OneDriveShareLinkPushAria2.git` 将项目整个克隆,才能使用,havepassword.py依赖于main.py,如果要使用需要密码的版本,需要 `pip install pyppeteer`

此程序基本功能都已实现,之后很长的一段时间内,如果不是软件无法使用了,则不再维护,如有运行问题,请在提出issue时带上下载链接,不提供下载链接的bug类型的issue将不会解决。
92 changes: 79 additions & 13 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import os
import copy

OneDriveShareURL = "https://gw6-my.sharepoint.com/:f:/g/personal/admin_gwliang_com/EuVr3Xt3csJMhnBmmK1Yw7wBUH9VQ3UFHHPxkdFJhHRpVQ?e=CAQLWc"
OneDriveShareURL = "https://acgmi-my.sharepoint.com/:f:/g/personal/support_acgmi_club/EpSr_7JeS85CipoL4p0A_tgBe-mWXj3SCnWV1qihc29IpQ?e=8DpGN6"

aria2Link = "http://localhost:6800/jsonrpc"
aria2Secret = "123456"
Expand Down Expand Up @@ -61,29 +61,34 @@ def getFiles(originalPath, req, layers, _id=0):
urllib.parse.urlsplit(redirectURL).query))
redirectSplitURL = redirectURL.split("/")

relativeUrl = ""
relativeFolder = ""
rootFolder = query["id"]
for i in rootFolder.split("/"):
if i != "Documents":
relativeUrl += i+"/"
relativeFolder += i+"/"
else:
relativeUrl += i
relativeFolder += i
break
relativeUrl = parse.quote(relativeUrl).replace("/", "%2F")
rootFolderUrl = parse.quote(rootFolder).replace("/", "%2F")
relativeUrl = parse.quote(relativeFolder).replace(
"/", "%2F").replace("_", "%5F").replace("-", "%2D")
rootFolderUrl = parse.quote(rootFolder).replace(
"/", "%2F").replace("_", "%5F").replace("-", "%2D")

graphqlVar = '{"query":"query (\n $listServerRelativeUrl: String!,$renderListDataAsStreamParameters: RenderListDataAsStreamParameters!,$renderListDataAsStreamQueryString: String!\n )\n {\n \n legacy {\n \n renderListDataAsStream(\n listServerRelativeUrl: $listServerRelativeUrl,\n parameters: $renderListDataAsStreamParameters,\n queryString: $renderListDataAsStreamQueryString\n )\n }\n \n \n perf {\n executionTime\n overheadTime\n parsingTime\n queryCount\n validationTime\n resolvers {\n name\n queryCount\n resolveTime\n waitTime\n }\n }\n }","variables":{"listServerRelativeUrl":"/personal/admin_gwliang_com/Documents","renderListDataAsStreamParameters":{"renderOptions":5707527,"allowMultipleValueFilterForTaxonomyFields":true,"addRequiredFields":true,"folderServerRelativeUrl":"%s"},"renderListDataAsStreamQueryString":"@a1=\'%s}\'&RootFolder=%s}&TryNewExperienceSingle=TRUE"}}' % (rootFolder, relativeUrl, rootFolderUrl)
graphqlVar = '{"query":"query (\n $listServerRelativeUrl: String!,$renderListDataAsStreamParameters: RenderListDataAsStreamParameters!,$renderListDataAsStreamQueryString: String!\n )\n {\n \n legacy {\n \n renderListDataAsStream(\n listServerRelativeUrl: $listServerRelativeUrl,\n parameters: $renderListDataAsStreamParameters,\n queryString: $renderListDataAsStreamQueryString\n )\n }\n \n \n perf {\n executionTime\n overheadTime\n parsingTime\n queryCount\n validationTime\n resolvers {\n name\n queryCount\n resolveTime\n waitTime\n }\n }\n }","variables":{"listServerRelativeUrl":"%s","renderListDataAsStreamParameters":{"renderOptions":5707527,"allowMultipleValueFilterForTaxonomyFields":true,"addRequiredFields":true,"folderServerRelativeUrl":"%s"},"renderListDataAsStreamQueryString":"@a1=\'%s\'&RootFolder=%s&TryNewExperienceSingle=TRUE"}}' % (relativeFolder, rootFolder, relativeUrl, rootFolderUrl)

# print(graphqlVar)
s2 = urllib.parse.urlparse(redirectURL)
tempHeader = copy.deepcopy(header)
tempHeader["referer"] = redirectURL
tempHeader["cookie"] = reqf.headers["set-cookie"]
tempHeader["authority"] = s2.netloc
tempHeader["content-type"] = "application/json;odata=verbose"
# print(redirectSplitURL)

graphqlReq = req.post(
"/".join(redirectSplitURL[:-3])+"/_api/v2.1/graphql", data=graphqlVar.encode('utf-8'), headers=tempHeader)
graphqlReq = json.loads(graphqlReq.text)
# print(graphqlReq)
if "NextHref" in graphqlReq["data"]["legacy"]["renderListDataAsStream"]["ListData"]:
nextHref = graphqlReq[
"data"]["legacy"]["renderListDataAsStream"]["ListData"]["NextHref"]+"&@a1=%s&TryNewExperienceSingle=TRUE" % (
Expand Down Expand Up @@ -156,9 +161,7 @@ def downloadFiles(originalPath, req, layers, aria2URL, token, num=-1, _id=0, ori
print("\t"*layers, "这个文件夹没有文件")
return 0

pat = re.search(
'g_listData = {"wpq":"","Templates":{},"ListData":{ "Row" : ([\s\S]*?),"FirstRow"', reqf.text)
jsonData = json.loads(pat.group(1))
filesData = []
redirectURL = reqf.url
redirectSplitURL = redirectURL.split("/")
query = dict(urllib.parse.parse_qsl(
Expand All @@ -173,7 +176,7 @@ def downloadFiles(originalPath, req, layers, aria2URL, token, num=-1, _id=0, ori
downloadURL.netloc, downloadURL.path).split("/")
downloadURL = "/".join(downloadURL[:-1]) + \
"/download.aspx?UniqueId="
print(downloadURL)
# print(downloadURL)

# print(reqf.headers)

Expand All @@ -190,9 +193,72 @@ def downloadFiles(originalPath, req, layers, aria2URL, token, num=-1, _id=0, ori
# print(key+':'+str(value))
headerStr += key+':'+str(value)+"\n"


relativeFolder = ""
rootFolder = query["id"]
for i in rootFolder.split("/"):
if i != "Documents":
relativeFolder += i+"/"
else:
relativeFolder += i
break
relativeUrl = parse.quote(relativeFolder).replace(
"/", "%2F").replace("_", "%5F").replace("-", "%2D")
rootFolderUrl = parse.quote(rootFolder).replace(
"/", "%2F").replace("_", "%5F").replace("-", "%2D")

graphqlVar = '{"query":"query (\n $listServerRelativeUrl: String!,$renderListDataAsStreamParameters: RenderListDataAsStreamParameters!,$renderListDataAsStreamQueryString: String!\n )\n {\n \n legacy {\n \n renderListDataAsStream(\n listServerRelativeUrl: $listServerRelativeUrl,\n parameters: $renderListDataAsStreamParameters,\n queryString: $renderListDataAsStreamQueryString\n )\n }\n \n \n perf {\n executionTime\n overheadTime\n parsingTime\n queryCount\n validationTime\n resolvers {\n name\n queryCount\n resolveTime\n waitTime\n }\n }\n }","variables":{"listServerRelativeUrl":"%s","renderListDataAsStreamParameters":{"renderOptions":5707527,"allowMultipleValueFilterForTaxonomyFields":true,"addRequiredFields":true,"folderServerRelativeUrl":"%s"},"renderListDataAsStreamQueryString":"@a1=\'%s\'&RootFolder=%s&TryNewExperienceSingle=TRUE"}}' % (relativeFolder, rootFolder, relativeUrl, rootFolderUrl)

# print(graphqlVar)
s2 = urllib.parse.urlparse(redirectURL)
tempHeader = copy.deepcopy(header)
tempHeader["referer"] = redirectURL
tempHeader["cookie"] = reqf.headers["set-cookie"]
tempHeader["authority"] = s2.netloc
tempHeader["content-type"] = "application/json;odata=verbose"
# print(redirectSplitURL)

graphqlReq = req.post(
"/".join(redirectSplitURL[:-3])+"/_api/v2.1/graphql", data=graphqlVar.encode('utf-8'), headers=tempHeader)
graphqlReq = json.loads(graphqlReq.text)
# print(graphqlReq)
if "NextHref" in graphqlReq["data"]["legacy"]["renderListDataAsStream"]["ListData"]:
nextHref = graphqlReq[
"data"]["legacy"]["renderListDataAsStream"]["ListData"]["NextHref"]+"&@a1=%s&TryNewExperienceSingle=TRUE" % (
"%27"+relativeUrl+"%27")
filesData.extend(graphqlReq[
"data"]["legacy"]["renderListDataAsStream"]["ListData"]["Row"])
# print(filesData)

listViewXml = graphqlReq[
"data"]["legacy"]["renderListDataAsStream"]["ViewMetadata"]["ListViewXml"]
renderListDataAsStreamVar = '{"parameters":{"__metadata":{"type":"SP.RenderListDataParameters"},"RenderOptions":1216519,"ViewXml":"%s","AllowMultipleValueFilterForTaxonomyFields":true,"AddRequiredFields":true}}' % (
listViewXml).replace('"', '\\"')
# print(renderListDataAsStreamVar, nextHref,1)

# print(listViewXml)

graphqlReq = req.post(
"/".join(redirectSplitURL[:-3])+"/_api/web/GetListUsingPath(DecodedUrl=@a1)/RenderListDataAsStream"+nextHref, data=renderListDataAsStreamVar.encode('utf-8'), headers=tempHeader)
graphqlReq = json.loads(graphqlReq.text)
# print(graphqlReq)

while "NextHref" in graphqlReq["ListData"]:
nextHref = graphqlReq["ListData"]["NextHref"]+"&@a1=%s&TryNewExperienceSingle=TRUE" % (
"%27"+relativeUrl+"%27")
filesData.extend(graphqlReq["ListData"]["Row"])
graphqlReq = req.post(
"/".join(redirectSplitURL[:-3])+"/_api/web/GetListUsingPath(DecodedUrl=@a1)/RenderListDataAsStream"+nextHref, data=renderListDataAsStreamVar.encode('utf-8'), headers=tempHeader)
# print(graphqlReq.text)
graphqlReq = json.loads(graphqlReq.text)
# print(graphqlReq)
filesData.extend(graphqlReq["ListData"]["Row"])
else:
filesData = filesData.extend(graphqlReq[
"data"]["legacy"]["renderListDataAsStream"]["ListData"]["Row"])

fileCount = 0
# print(headerStr)
for i in jsonData:
for i in filesData:
if i['FSObjType'] == "1":
print("\t"*layers, "文件夹:",
i['FileLeafRef'], "\t独特ID:", i["UniqueId"], "正在进入")
Expand Down

0 comments on commit a8dd447

Please sign in to comment.