1 | import { createClient } from "webdav"; |
2 |
|
3 | |
4 | * Resolves a Nextcloud file path from its fileid. |
5 | */ |
6 | export async function main( |
7 | ncResource: RT.Nextcloud, |
8 | fileid: string |
9 | ): Promise<string> { |
10 |
|
11 | const baseUrl = ncResource.baseUrl; |
12 | const davBaseUrl = `${baseUrl}/remote.php/dav`; |
13 | const client = createClient(davBaseUrl, { |
14 | username: ncResource.userId, |
15 | password: ncResource.token, |
16 | }); |
17 |
|
18 | const searchXml = buildSearchRequestXml(ncResource.userId, fileid); |
19 | const rawResponse = await client.customRequest("/", { |
20 | method: "SEARCH", |
21 | data: searchXml, |
22 | headers: { |
23 | "Content-Type": "text/xml; charset=utf-8", |
24 | Accept: "application/xml, text/xml", |
25 | }, |
26 | responseType: "text", |
27 | }); |
28 | const responseXml = await rawResponse.text(); |
29 | const path = extractPathFromSearchResponse(responseXml, ncResource.userId); |
30 | if (!path) { |
31 | throw new Error(`Could not resolve path for fileid "${fileid}"`); |
32 | } |
33 |
|
34 | return path; |
35 | } |
36 |
|
37 | function buildSearchRequestXml(userId: string, fileId: string): string { |
38 | return `<?xml version="1.0" encoding="UTF-8"?> |
39 | <d:searchrequest xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns"> |
40 | <d:basicsearch> |
41 | <d:select> |
42 | <d:prop> |
43 | <d:displayname/> |
44 | <oc:fileid/> |
45 | </d:prop> |
46 | </d:select> |
47 | <d:from> |
48 | <d:scope> |
49 | <d:href>/files/${encodeURIComponent(userId)}</d:href> |
50 | <d:depth>infinity</d:depth> |
51 | </d:scope> |
52 | </d:from> |
53 | <d:where> |
54 | <d:eq> |
55 | <d:prop><oc:fileid/></d:prop> |
56 | <d:literal>${encodeURIComponent(fileId)}</d:literal> |
57 | </d:eq> |
58 | </d:where> |
59 | </d:basicsearch> |
60 | </d:searchrequest>`; |
61 | } |
62 |
|
63 | function extractPathFromSearchResponse(xml: string, userId: string): string | null { |
64 | const hrefRegex = /<d:href>(.*?)<\/d:href>/g; |
65 | let match: RegExpExecArray | null = null; |
66 | while ((match = hrefRegex.exec(xml)) !== null) { |
67 | console.log(match[1]); |
68 | const href = decodeURIComponent(match[1] || "").trim(); |
69 | if (!href) continue; |
70 |
|
71 | |
72 | const marker = `/files/${userId}/`; |
73 | const markerIndex = href.indexOf(marker); |
74 | if (markerIndex !== -1) { |
75 | return `/${href.slice(markerIndex + marker.length)}`; |
76 | } |
77 | } |
78 | return null; |
79 | } |