| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | /* | 
					
						
							|  |  |  | 	GoToSocial | 
					
						
							|  |  |  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 	SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | 	it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | 	the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | 	(at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | 	GNU Affero General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  | 	BaseQueryFn, | 
					
						
							|  |  |  | 	FetchArgs, | 
					
						
							|  |  |  | 	FetchBaseQueryError, | 
					
						
							|  |  |  | } from '@reduxjs/toolkit/query/react'; | 
					
						
							|  |  |  | import { serialize as serializeForm } from "object-to-formdata"; | 
					
						
							| 
									
										
										
										
											2024-05-01 15:11:22 +02:00
										 |  |  | import type { FetchBaseQueryMeta } from "@reduxjs/toolkit/dist/query/fetchBaseQuery"; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | import type { RootState } from '../../redux/store'; | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import { InstanceV1 } from '../types/instance'; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * GTSFetchArgs extends standard FetchArgs used by | 
					
						
							|  |  |  |  * RTK Query with a couple helpers of our own. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export interface GTSFetchArgs extends FetchArgs { | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * If provided, will be used as base URL. Else, | 
					
						
							|  |  |  | 	 * will fall back to authorized instance as baseUrl. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	baseUrl?: string; | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * If true, and no args.body is set, or args.body is empty, | 
					
						
							|  |  |  | 	 * then a null response will be returned from the API call.   | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	discardEmpty?: boolean; | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * If true, then args.body will be serialized | 
					
						
							|  |  |  | 	 * as FormData before submission.  | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	asForm?: boolean; | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * If set, then Accept header will | 
					
						
							|  |  |  | 	 * be set to the provided contentType. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	acceptContentType?: string; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * gtsBaseQuery wraps the redux toolkit fetchBaseQuery with some helper functionality. | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * For an explainer of what's happening in this function, see: | 
					
						
							|  |  |  |  * - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-queries-with-basequery
 | 
					
						
							|  |  |  |  * - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#constructing-a-dynamic-base-url-using-redux-state
 | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * @param args  | 
					
						
							|  |  |  |  * @param api  | 
					
						
							|  |  |  |  * @param extraOptions  | 
					
						
							|  |  |  |  * @returns  | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const gtsBaseQuery: BaseQueryFn< | 
					
						
							|  |  |  | 	string | GTSFetchArgs, | 
					
						
							|  |  |  | 	any, | 
					
						
							| 
									
										
										
										
											2024-05-01 15:11:22 +02:00
										 |  |  | 	FetchBaseQueryError, | 
					
						
							|  |  |  | 	{}, | 
					
						
							|  |  |  | 	FetchBaseQueryMeta | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | > = async (args, api, extraOptions) => { | 
					
						
							|  |  |  | 	// Retrieve state at the moment
 | 
					
						
							|  |  |  | 	// this function was called.
 | 
					
						
							|  |  |  | 	const state = api.getState() as RootState; | 
					
						
							| 
									
										
										
										
											2025-03-17 15:06:17 +01:00
										 |  |  | 	const { instanceUrl, token } = state.login; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Derive baseUrl dynamically.
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	let baseUrl: string | undefined; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 	// Assume Accept value of
 | 
					
						
							|  |  |  | 	// "application/json" by default.
 | 
					
						
							|  |  |  | 	let accept = "application/json"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 	// Check if simple string baseUrl provided
 | 
					
						
							|  |  |  | 	// as args, or if more complex args provided.
 | 
					
						
							|  |  |  | 	if (typeof args === "string") { | 
					
						
							|  |  |  | 		baseUrl = args; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (args.baseUrl != undefined) { | 
					
						
							|  |  |  | 			baseUrl = args.baseUrl; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			baseUrl = instanceUrl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (args.discardEmpty) { | 
					
						
							|  |  |  | 			if (args.body == undefined || Object.keys(args.body).length == 0) { | 
					
						
							|  |  |  | 				return { data: null }; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (args.asForm) { | 
					
						
							|  |  |  | 			args.body = serializeForm(args.body, { | 
					
						
							|  |  |  | 				// Array indices, for profile fields.
 | 
					
						
							|  |  |  | 				indices: true, | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 		if (args.acceptContentType !== undefined) { | 
					
						
							|  |  |  | 			accept = args.acceptContentType; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 		// Delete any of our extended arguments
 | 
					
						
							|  |  |  | 		// to avoid confusing fetchBaseQuery.
 | 
					
						
							|  |  |  | 		delete args.baseUrl; | 
					
						
							|  |  |  | 		delete args.discardEmpty; | 
					
						
							|  |  |  | 		delete args.asForm; | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 		delete args.acceptContentType; | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!baseUrl) { | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			error: { | 
					
						
							|  |  |  | 				status: 400, | 
					
						
							|  |  |  | 				statusText: 'Bad Request', | 
					
						
							|  |  |  | 				data: {"error":"No baseUrl set for request"}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fetchBaseQuery({ | 
					
						
							|  |  |  | 		baseUrl: baseUrl, | 
					
						
							|  |  |  | 		prepareHeaders: (headers) => { | 
					
						
							|  |  |  | 			if (token != undefined) { | 
					
						
							|  |  |  | 				headers.set('Authorization', token); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			headers.set("Accept", accept); | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 			return headers; | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 		responseHandler: (response) => { | 
					
						
							| 
									
										
										
										
											2025-04-07 16:14:41 +02:00
										 |  |  | 			switch (true) { | 
					
						
							|  |  |  | 				case (accept === "application/json"): | 
					
						
							|  |  |  | 					// return good old
 | 
					
						
							|  |  |  | 					// fashioned JSON baby!
 | 
					
						
							|  |  |  | 					return response.json(); | 
					
						
							|  |  |  | 				case (accept.startsWith("image/")): | 
					
						
							|  |  |  | 					// It's an image,
 | 
					
						
							|  |  |  | 					// return the blob.
 | 
					
						
							|  |  |  | 					return response.blob(); | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					// God knows what it
 | 
					
						
							|  |  |  | 					// is, just return text.
 | 
					
						
							|  |  |  | 					return response.text(); | 
					
						
							| 
									
										
										
										
											2024-07-31 16:03:34 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 	})(args, api, extraOptions); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const gtsApi = createApi({ | 
					
						
							|  |  |  | 	reducerPath: "api", | 
					
						
							|  |  |  | 	baseQuery: gtsBaseQuery, | 
					
						
							|  |  |  | 	tagTypes: [ | 
					
						
							| 
									
										
										
										
											2025-03-17 15:06:17 +01:00
										 |  |  | 		"Application", | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 		"Auth", | 
					
						
							|  |  |  | 		"Emoji", | 
					
						
							| 
									
										
										
										
											2024-06-18 18:18:00 +02:00
										 |  |  | 		"Report", | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 		"Account", | 
					
						
							|  |  |  | 		"InstanceRules", | 
					
						
							| 
									
										
										
										
											2024-05-05 13:47:22 +02:00
										 |  |  | 		"HTTPHeaderAllows", | 
					
						
							|  |  |  | 		"HTTPHeaderBlocks", | 
					
						
							| 
									
										
										
										
											2024-07-17 16:46:52 +02:00
										 |  |  | 		"DefaultInteractionPolicies", | 
					
						
							| 
									
										
										
										
											2024-08-24 11:49:37 +02:00
										 |  |  | 		"InteractionRequest", | 
					
						
							| 
									
										
										
										
											2024-11-21 14:09:58 +01:00
										 |  |  | 		"DomainPermissionDraft", | 
					
						
							| 
									
										
										
										
											2025-01-05 13:20:33 +01:00
										 |  |  | 		"DomainPermissionExclude", | 
					
						
							| 
									
										
										
										
											2025-03-04 11:01:25 +01:00
										 |  |  | 		"DomainPermissionSubscription", | 
					
						
							|  |  |  | 		"TokenInfo", | 
					
						
							| 
									
										
										
										
											2025-04-07 16:14:41 +02:00
										 |  |  | 		"User", | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	endpoints: (build) => ({ | 
					
						
							|  |  |  | 		instanceV1: build.query<InstanceV1, void>({ | 
					
						
							| 
									
										
										
										
											2023-10-05 16:06:19 +02:00
										 |  |  | 			query: () => ({ | 
					
						
							|  |  |  | 				url: `/api/v1/instance` | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Query /api/v1/instance to retrieve basic instance information. | 
					
						
							|  |  |  |  * This endpoint does not require authentication/authorization. | 
					
						
							|  |  |  |  * TODO: move this to ./instance. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const useInstanceV1Query = gtsApi.useInstanceV1Query; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export { useInstanceV1Query }; |