aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVendicated <vendicated@riseup.net>2023-10-06 19:40:53 +0200
committerVendicated <vendicated@riseup.net>2023-10-06 19:43:24 +0200
commitc0f2c974587d75a38e3e753368ef0e2e2be139fd (patch)
treec1e75f84785d10f207f1f142da0cec6ab01d2443
parent664dd0a9920aa697359b1bb07b98795ff0f1beaf (diff)
downloadVencord-c0f2c974587d75a38e3e753368ef0e2e2be139fd.tar.gz
Vencord-c0f2c974587d75a38e3e753368ef0e2e2be139fd.tar.bz2
Vencord-c0f2c974587d75a38e3e753368ef0e2e2be139fd.zip
ReviewDB: proper multi account support
-rw-r--r--src/plugins/reviewDB/auth.tsx78
-rw-r--r--src/plugins/reviewDB/components/ReviewComponent.tsx4
-rw-r--r--src/plugins/reviewDB/components/ReviewModal.tsx5
-rw-r--r--src/plugins/reviewDB/components/ReviewsView.tsx7
-rw-r--r--src/plugins/reviewDB/entities.ts5
-rw-r--r--src/plugins/reviewDB/index.tsx45
-rw-r--r--src/plugins/reviewDB/reviewDbApi.ts18
-rw-r--r--src/plugins/reviewDB/settings.tsx12
-rw-r--r--src/plugins/reviewDB/utils.tsx55
9 files changed, 141 insertions, 88 deletions
diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx
new file mode 100644
index 0000000..1d95e47
--- /dev/null
+++ b/src/plugins/reviewDB/auth.tsx
@@ -0,0 +1,78 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2023 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { DataStore } from "@api/index";
+import { Logger } from "@utils/Logger";
+import { openModal } from "@utils/modal";
+import { findByPropsLazy } from "@webpack";
+import { showToast, Toasts, UserStore } from "@webpack/common";
+
+import { ReviewDBAuth } from "./entities";
+
+const DATA_STORE_KEY = "rdb-auth";
+
+const OAuth = findByPropsLazy("OAuth2AuthorizeModal");
+
+export let Auth: ReviewDBAuth = {};
+
+export async function initAuth() {
+ Auth = await getAuth() ?? {};
+}
+
+export async function getAuth(): Promise<ReviewDBAuth | undefined> {
+ const auth = await DataStore.get(DATA_STORE_KEY);
+ return auth?.[UserStore.getCurrentUser()?.id];
+}
+
+export async function getToken() {
+ const auth = await getAuth();
+ return auth?.token;
+}
+
+export async function updateAuth(newAuth: ReviewDBAuth) {
+ return DataStore.update(DATA_STORE_KEY, auth => {
+ auth ??= {};
+ Auth = auth[UserStore.getCurrentUser().id] ??= {};
+
+ if (newAuth.token) Auth.token = newAuth.token;
+ if (newAuth.user) Auth.user = newAuth.user;
+
+ return auth;
+ });
+}
+
+export function authorize(callback?: any) {
+ openModal(props =>
+ <OAuth.OAuth2AuthorizeModal
+ {...props}
+ scopes={["identify"]}
+ responseType="code"
+ redirectUri="https://manti.vendicated.dev/api/reviewdb/auth"
+ permissions={0n}
+ clientId="915703782174752809"
+ cancelCompletesFlow={false}
+ callback={async (response: any) => {
+ try {
+ const url = new URL(response.location);
+ url.searchParams.append("clientMod", "vencord");
+ const res = await fetch(url, {
+ headers: new Headers({ Accept: "application/json" })
+ });
+ const { token, success } = await res.json();
+ if (success) {
+ updateAuth({ token });
+ showToast("Successfully logged in!");
+ callback?.();
+ } else if (res.status === 1) {
+ showToast("An Error occurred while logging in.", Toasts.Type.FAILURE);
+ }
+ } catch (e) {
+ new Logger("ReviewDB").error("Failed to authorize", e);
+ }
+ }}
+ />
+ );
+}
diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx
index 5792400..1865917 100644
--- a/src/plugins/reviewDB/components/ReviewComponent.tsx
+++ b/src/plugins/reviewDB/components/ReviewComponent.tsx
@@ -20,12 +20,12 @@ import { openUserProfile } from "@utils/discord";
import { classes } from "@utils/misc";
import { LazyComponent } from "@utils/react";
import { filters, findBulk } from "@webpack";
-import { Alerts, moment, Parser, Timestamp } from "@webpack/common";
+import { Alerts, moment, Parser, showToast, Timestamp } from "@webpack/common";
import { Review, ReviewType } from "../entities";
import { deleteReview, reportReview } from "../reviewDbApi";
import { settings } from "../settings";
-import { canDeleteReview, cl, showToast } from "../utils";
+import { canDeleteReview, cl } from "../utils";
import { DeleteButton, ReportButton } from "./MessageButton";
import ReviewBadge from "./ReviewBadge";
diff --git a/src/plugins/reviewDB/components/ReviewModal.tsx b/src/plugins/reviewDB/components/ReviewModal.tsx
index 6e85dc2..9669a2b 100644
--- a/src/plugins/reviewDB/components/ReviewModal.tsx
+++ b/src/plugins/reviewDB/components/ReviewModal.tsx
@@ -21,8 +21,8 @@ import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, Mo
import { useForceUpdater } from "@utils/react";
import { Paginator, Text, useRef, useState } from "@webpack/common";
+import { Auth } from "../auth";
import { Response, REVIEWS_PER_PAGE } from "../reviewDbApi";
-import { settings } from "../settings";
import { cl } from "../utils";
import ReviewComponent from "./ReviewComponent";
import ReviewsView, { ReviewsInputComponent } from "./ReviewsView";
@@ -35,7 +35,7 @@ function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: st
const ref = useRef<HTMLDivElement>(null);
const reviewCount = data?.reviewCount;
- const ownReview = data?.reviews.find(r => r.sender.discordID === settings.store.user?.discordID);
+ const ownReview = data?.reviews.find(r => r.sender.discordID === Auth.user?.discordID);
return (
<ErrorBoundary>
@@ -68,6 +68,7 @@ function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: st
<ReviewComponent
refetch={refetch}
review={ownReview}
+ profileId={discordId}
/>
)}
<ReviewsInputComponent
diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx
index 5eb370f..a87598b 100644
--- a/src/plugins/reviewDB/components/ReviewsView.tsx
+++ b/src/plugins/reviewDB/components/ReviewsView.tsx
@@ -18,12 +18,13 @@
import { LazyComponent, useAwaiter, useForceUpdater } from "@utils/react";
import { find, findByPropsLazy } from "@webpack";
-import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common";
+import { Forms, React, RelationshipStore, showToast, useRef, UserStore } from "@webpack/common";
+import { Auth, authorize } from "../auth";
import { Review } from "../entities";
import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi";
import { settings } from "../settings";
-import { authorize, cl, showToast } from "../utils";
+import { cl } from "../utils";
import ReviewComponent from "./ReviewComponent";
@@ -120,7 +121,7 @@ function ReviewList({ refetch, reviews, hideOwnReview, profileId }: { refetch():
export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; }) {
- const { token } = settings.store;
+ const { token } = Auth;
const editorRef = useRef<any>(null);
const inputType = InputTypes.FORM;
inputType.disableAutoFocus = true;
diff --git a/src/plugins/reviewDB/entities.ts b/src/plugins/reviewDB/entities.ts
index fefb1d3..0a77fef 100644
--- a/src/plugins/reviewDB/entities.ts
+++ b/src/plugins/reviewDB/entities.ts
@@ -36,6 +36,11 @@ export const enum NotificationType {
Warning = 3
}
+export interface ReviewDBAuth {
+ token?: string;
+ user?: ReviewDBUser;
+}
+
export interface Badge {
name: string;
description: string;
diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx
index a519713..b9350ba 100644
--- a/src/plugins/reviewDB/index.tsx
+++ b/src/plugins/reviewDB/index.tsx
@@ -23,16 +23,17 @@ import ErrorBoundary from "@components/ErrorBoundary";
import ExpandableHeader from "@components/ExpandableHeader";
import { OpenExternalIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
+import { Logger } from "@utils/Logger";
import definePlugin from "@utils/types";
-import { Alerts, Menu, Parser, useState } from "@webpack/common";
+import { Alerts, Menu, Parser, showToast, useState } from "@webpack/common";
import { Guild, User } from "discord-types/general";
+import { Auth, initAuth, updateAuth } from "./auth";
import { openReviewsModal } from "./components/ReviewModal";
import ReviewsView from "./components/ReviewsView";
import { NotificationType } from "./entities";
import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
import { settings } from "./settings";
-import { showToast } from "./utils";
const guildPopoutPatch: NavContextMenuPatchCallback = (children, props: { guild: Guild, onClose(): void; }) => () => {
children.push(
@@ -62,31 +63,48 @@ export default definePlugin({
}
],
+ flux: {
+ CONNECTION_OPEN: initAuth,
+ },
+
async start() {
+ addContextMenuPatch("guild-header-popout", guildPopoutPatch);
+
const s = settings.store;
- const { token, lastReviewId, notifyReviews } = s;
+ const { lastReviewId, notifyReviews } = s;
+
+ const legacy = s as any as { token?: string; };
+ if (legacy.token) {
+ await updateAuth({ token: legacy.token });
+ legacy.token = undefined;
+ new Logger("ReviewDB").info("Migrated legacy settings");
+ }
- if (!notifyReviews || !token) return;
+ await initAuth();
setTimeout(async () => {
- const user = await getCurrentUserInfo(token);
- if (lastReviewId && lastReviewId < user.lastReviewID) {
- s.lastReviewId = user.lastReviewID;
- if (user.lastReviewID !== 0)
- showToast("You have new reviews on your profile!");
- }
+ if (!Auth.token) return;
+
+ const user = await getCurrentUserInfo(Auth.token);
+ updateAuth({ user });
- addContextMenuPatch("guild-header-popout", guildPopoutPatch);
+ if (notifyReviews) {
+ if (lastReviewId && lastReviewId < user.lastReviewID) {
+ s.lastReviewId = user.lastReviewID;
+ if (user.lastReviewID !== 0)
+ showToast("You have new reviews on your profile!");
+ }
+ }
if (user.notification) {
const props = user.notification.type === NotificationType.Ban ? {
cancelText: "Appeal",
confirmText: "Ok",
- onCancel: () =>
+ onCancel: async () =>
VencordNative.native.openExternal(
"https://reviewdb.mantikafasi.dev/api/redirect?"
+ new URLSearchParams({
- token: settings.store.token!,
+ token: Auth.token!,
page: "dashboard/appeal"
})
)
@@ -105,7 +123,6 @@ export default definePlugin({
readNotification(user.notification.id);
}
- s.user = user;
}, 4000);
},
diff --git a/src/plugins/reviewDB/reviewDbApi.ts b/src/plugins/reviewDB/reviewDbApi.ts
index 5370a9b..add16dd 100644
--- a/src/plugins/reviewDB/reviewDbApi.ts
+++ b/src/plugins/reviewDB/reviewDbApi.ts
@@ -16,9 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import { showToast, Toasts } from "@webpack/common";
+
+import { authorize, getToken } from "./auth";
import { Review, ReviewDBUser } from "./entities";
import { settings } from "./settings";
-import { authorize, showToast } from "./utils";
const API_URL = "https://manti.vendicated.dev";
@@ -57,7 +59,7 @@ export async function getReviews(id: string, offset = 0): Promise<Response> {
};
if (!res.success) {
- showToast(res.message);
+ showToast(res.message, Toasts.Type.FAILURE);
return {
...res,
reviews: [
@@ -82,7 +84,7 @@ export async function getReviews(id: string, offset = 0): Promise<Response> {
}
export async function addReview(review: any): Promise<Response | null> {
- review.token = settings.store.token;
+ review.token = await getToken();
if (!review.token) {
showToast("Please authorize to add a review.");
@@ -104,7 +106,7 @@ export async function addReview(review: any): Promise<Response | null> {
});
}
-export function deleteReview(id: number): Promise<Response> {
+export async function deleteReview(id: number): Promise<Response> {
return fetch(API_URL + `/api/reviewdb/users/${id}/reviews`, {
method: "DELETE",
headers: new Headers({
@@ -112,7 +114,7 @@ export function deleteReview(id: number): Promise<Response> {
Accept: "application/json",
}),
body: JSON.stringify({
- token: settings.store.token,
+ token: await getToken(),
reviewid: id
})
}).then(r => r.json());
@@ -127,7 +129,7 @@ export async function reportReview(id: number) {
}),
body: JSON.stringify({
reviewid: id,
- token: settings.store.token
+ token: await getToken()
})
}).then(r => r.json()) as Response;
@@ -141,11 +143,11 @@ export function getCurrentUserInfo(token: string): Promise<ReviewDBUser> {
}).then(r => r.json());
}
-export function readNotification(id: number) {
+export async function readNotification(id: number) {
return fetch(API_URL + `/api/reviewdb/notifications?id=${id}`, {
method: "PATCH",
headers: {
- "Authorization": settings.store.token || "",
+ "Authorization": await getToken() || "",
},
});
}
diff --git a/src/plugins/reviewDB/settings.tsx b/src/plugins/reviewDB/settings.tsx
index e318bc7..cf61a38 100644
--- a/src/plugins/reviewDB/settings.tsx
+++ b/src/plugins/reviewDB/settings.tsx
@@ -20,8 +20,7 @@ import { definePluginSettings } from "@api/Settings";
import { OptionType } from "@utils/types";
import { Button } from "@webpack/common";
-import { ReviewDBUser } from "./entities";
-import { authorize } from "./utils";
+import { authorize, getToken } from "./auth";
export const settings = definePluginSettings({
authorize: {
@@ -57,10 +56,11 @@ export const settings = definePluginSettings({
type: OptionType.COMPONENT,
description: "ReviewDB website",
component: () => (
- <Button onClick={() => {
+ <Button onClick={async () => {
let url = "https://reviewdb.mantikafasi.dev/";
- if (settings.store.token)
- url += "/api/redirect?token=" + encodeURIComponent(settings.store.token);
+ const token = await getToken();
+ if (token)
+ url += "/api/redirect?token=" + encodeURIComponent(token);
VencordNative.native.openExternal(url);
}}>
@@ -80,8 +80,6 @@ export const settings = definePluginSettings({
)
}
}).withPrivateSettings<{
- token?: string;
- user?: ReviewDBUser;
lastReviewId?: number;
reviewsDropdownState?: boolean;
}>();
diff --git a/src/plugins/reviewDB/utils.tsx b/src/plugins/reviewDB/utils.tsx
index 63ab84d..ab66d53 100644
--- a/src/plugins/reviewDB/utils.tsx
+++ b/src/plugins/reviewDB/utils.tsx
@@ -17,67 +17,18 @@
*/
import { classNameFactory } from "@api/Styles";
-import { Logger } from "@utils/Logger";
-import { openModal } from "@utils/modal";
-import { findByProps } from "@webpack";
-import { React, Toasts, UserStore } from "@webpack/common";
+import { UserStore } from "@webpack/common";
+import { Auth } from "./auth";
import { Review, UserType } from "./entities";
-import { settings } from "./settings";
export const cl = classNameFactory("vc-rdb-");
-export function authorize(callback?: any) {
- const { OAuth2AuthorizeModal } = findByProps("OAuth2AuthorizeModal");
-
- openModal((props: any) =>
- <OAuth2AuthorizeModal
- {...props}
- scopes={["identify"]}
- responseType="code"
- redirectUri="https://manti.vendicated.dev/api/reviewdb/auth"
- permissions={0n}
- clientId="915703782174752809"
- cancelCompletesFlow={false}
- callback={async (response: any) => {
- try {
- const url = new URL(response.location);
- url.searchParams.append("clientMod", "vencord");
- const res = await fetch(url, {
- headers: new Headers({ Accept: "application/json" })
- });
- const { token, success } = await res.json();
- if (success) {
- settings.store.token = token;
- showToast("Successfully logged in!");
- callback?.();
- } else if (res.status === 1) {
- showToast("An Error occurred while logging in.");
- }
- } catch (e) {
- new Logger("ReviewDB").error("Failed to authorize", e);
- }
- }}
- />
- );
-}
-
-export function showToast(text: string) {
- Toasts.show({
- type: Toasts.Type.MESSAGE,
- message: text,
- id: Toasts.genId(),
- options: {
- position: Toasts.Position.BOTTOM
- },
- });
-}
-
export function canDeleteReview(profileId: string, review: Review) {
const myId = UserStore.getCurrentUser().id;
return (
myId === profileId
|| review.sender.discordID === profileId
- || settings.store.user?.type === UserType.Admin
+ || Auth.user?.type === UserType.Admin
);
}