You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			173 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
| import { OpenGroupV2Request } from '../opengroup/opengroupV2/ApiUtil';
 | |
| import { sendApiV2Request } from '../opengroup/opengroupV2/OpenGroupAPIV2';
 | |
| import { parseStatusCodeFromOnionRequest } from '../opengroup/opengroupV2/OpenGroupAPIV2Parser';
 | |
| 
 | |
| // tslint:disable-next-line: no-http-string
 | |
| export const fileServerV2URL = 'http://filev2.getsession.org';
 | |
| 
 | |
| export const fileServerV2PubKey =
 | |
|   'da21e1d886c6fbaea313f75298bd64aab03a97ce985b46bb2dad9f2089c8ee59';
 | |
| 
 | |
| export type FileServerV2Request = {
 | |
|   method: 'GET' | 'POST' | 'DELETE' | 'PUT';
 | |
|   endpoint: string;
 | |
|   // queryParams are used for post or get, but not the same way
 | |
|   queryParams?: Record<string, any>;
 | |
|   headers?: Record<string, string>;
 | |
| };
 | |
| 
 | |
| const FILES_ENDPOINT = 'files';
 | |
| const RELEASE_VERSION_ENDPOINT = 'session_version';
 | |
| 
 | |
| // Disable this if you don't want to use the file server v2 for sending
 | |
| // Receiving is always enabled if the attachments url matches a fsv2 url
 | |
| export const useFileServerAPIV2Sending = true;
 | |
| 
 | |
| /**
 | |
|  * Upload a file to the file server v2
 | |
|  * @param fileContent the data to send
 | |
|  * @returns null or the fileID and complete URL to share this file
 | |
|  */
 | |
| export const uploadFileToFsV2 = async (
 | |
|   fileContent: ArrayBuffer
 | |
| ): Promise<{ fileId: number; fileUrl: string } | null> => {
 | |
|   if (!fileContent || !fileContent.byteLength) {
 | |
|     return null;
 | |
|   }
 | |
|   const queryParams = {
 | |
|     file: await window.callWorker('arrayBufferToStringBase64', fileContent),
 | |
|   };
 | |
| 
 | |
|   const request: FileServerV2Request = {
 | |
|     method: 'POST',
 | |
|     endpoint: FILES_ENDPOINT,
 | |
|     queryParams,
 | |
|   };
 | |
| 
 | |
|   const result = await sendApiV2Request(request);
 | |
|   const statusCode = parseStatusCodeFromOnionRequest(result);
 | |
|   if (statusCode !== 200) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   // we should probably change the logic of sendOnionRequest to not have all those levels
 | |
|   const fileId = (result as any)?.result?.result as number | undefined;
 | |
|   if (!fileId) {
 | |
|     return null;
 | |
|   }
 | |
|   const fileUrl = `${fileServerV2URL}/${FILES_ENDPOINT}/${fileId}`;
 | |
|   return {
 | |
|     fileId: fileId,
 | |
|     fileUrl,
 | |
|   };
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Download a file given the fileId from the fileserver v2
 | |
|  * @param fileIdOrCompleteUrl the fileId to download or the completeUrl to the fileitself
 | |
|  * @returns the data as an Uint8Array or null
 | |
|  */
 | |
| export const downloadFileFromFSv2 = async (
 | |
|   fileIdOrCompleteUrl: string
 | |
| ): Promise<ArrayBuffer | null> => {
 | |
|   let fileId = fileIdOrCompleteUrl;
 | |
|   if (!fileIdOrCompleteUrl) {
 | |
|     window?.log?.warn('Empty url to download for file v2');
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   const newCompleteUrlPrefix = `${fileServerV2URL}/${FILES_ENDPOINT}/`;
 | |
| 
 | |
|   if (fileIdOrCompleteUrl.startsWith(newCompleteUrlPrefix)) {
 | |
|     fileId = fileId.substr(newCompleteUrlPrefix.length);
 | |
|   }
 | |
| 
 | |
|   const request: FileServerV2Request = {
 | |
|     method: 'GET',
 | |
|     endpoint: `${FILES_ENDPOINT}/${fileId}`,
 | |
|   };
 | |
| 
 | |
|   const result = await sendApiV2Request(request);
 | |
|   const statusCode = parseStatusCodeFromOnionRequest(result);
 | |
|   if (statusCode !== 200) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   // we should probably change the logic of sendOnionRequest to not have all those levels
 | |
|   const base64Data = (result as any)?.result?.result as string | undefined;
 | |
| 
 | |
|   if (!base64Data) {
 | |
|     return null;
 | |
|   }
 | |
|   return window.callWorker('fromBase64ToArrayBuffer', base64Data);
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * This is a typescript type guard
 | |
|  * request.isAuthRequired Must be set for an OpenGroupV2Request
 | |
|  * @returns true if request.isAuthRequired is not undefined
 | |
|  */
 | |
| export function isOpenGroupV2Request(
 | |
|   request: FileServerV2Request | OpenGroupV2Request
 | |
| ): request is OpenGroupV2Request {
 | |
|   return (request as OpenGroupV2Request).isAuthRequired !== undefined;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Try to build an full url and check it for validity.
 | |
|  * @returns null if the check failed. the built URL otherwise
 | |
|  */
 | |
| export const buildUrl = (request: FileServerV2Request | OpenGroupV2Request): URL | null => {
 | |
|   let rawURL: string;
 | |
|   if (isOpenGroupV2Request(request)) {
 | |
|     rawURL = `${request.server}/${request.endpoint}`;
 | |
|   } else {
 | |
|     rawURL = `${fileServerV2URL}/${request.endpoint}`;
 | |
|   }
 | |
| 
 | |
|   if (request.method === 'GET') {
 | |
|     const entries = Object.entries(request.queryParams || {});
 | |
| 
 | |
|     if (entries.length) {
 | |
|       const queryString = entries.map(([key, value]) => `${key}=${value}`).join('&');
 | |
|       rawURL += `?${queryString}`;
 | |
|     }
 | |
|   }
 | |
|   // this just check that the URL is valid
 | |
|   try {
 | |
|     return new URL(`${rawURL}`);
 | |
|   } catch (error) {
 | |
|     return null;
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Upload a file to the file server v2
 | |
|  * @param fileContent the data to send
 | |
|  * @returns null or the fileID and complete URL to share this file
 | |
|  */
 | |
| export const getLatestDesktopReleaseFileToFsV2 = async (): Promise<string | null> => {
 | |
|   const queryParams = {
 | |
|     platform: 'desktop',
 | |
|   };
 | |
| 
 | |
|   const request: FileServerV2Request = {
 | |
|     method: 'GET',
 | |
|     endpoint: RELEASE_VERSION_ENDPOINT,
 | |
|     queryParams,
 | |
|   };
 | |
| 
 | |
|   const result = await sendApiV2Request(request);
 | |
|   const statusCode = parseStatusCodeFromOnionRequest(result);
 | |
|   if (statusCode !== 200) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   // we should probably change the logic of sendOnionRequest to not have all those levels
 | |
|   const latestVersionWithV = (result as any)?.result?.result as string | undefined;
 | |
|   if (!latestVersionWithV) {
 | |
|     return null;
 | |
|   }
 | |
|   return latestVersionWithV;
 | |
| };
 |