diff options
author | V <vendicated@riseup.net> | 2023-10-09 03:09:56 +0200 |
---|---|---|
committer | V <vendicated@riseup.net> | 2023-10-09 03:09:56 +0200 |
commit | 390987e4a9d58c4c0eb9d4f6b4101ecf1203ccba (patch) | |
tree | 00d9d5464ebea2114fb882266b186ec812659191 | |
parent | 377cf600550da9c1b49924bd996fc86be9011048 (diff) | |
download | Vencord-390987e4a9d58c4c0eb9d4f6b4101ecf1203ccba.tar.gz Vencord-390987e4a9d58c4c0eb9d4f6b4101ecf1203ccba.tar.bz2 Vencord-390987e4a9d58c4c0eb9d4f6b4101ecf1203ccba.zip |
Remove ReviewDB
abuse / harassment has gotten pretty bad.
i proposed the ability to allow users to delete comments from their own
profile, but there seems to be no interest among the reviewdb owners.
i don't want vencord to harbour harassment, so i'm removing the plugin
for now
-rw-r--r-- | src/plugins/reviewDB/auth.tsx | 78 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/MessageButton.tsx | 61 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewBadge.tsx | 46 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewComponent.tsx | 147 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewModal.tsx | 105 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewsView.tsx | 200 | ||||
-rw-r--r-- | src/plugins/reviewDB/entities.ts | 96 | ||||
-rw-r--r-- | src/plugins/reviewDB/index.tsx | 157 | ||||
-rw-r--r-- | src/plugins/reviewDB/reviewDbApi.ts | 153 | ||||
-rw-r--r-- | src/plugins/reviewDB/settings.tsx | 85 | ||||
-rw-r--r-- | src/plugins/reviewDB/style.css | 76 | ||||
-rw-r--r-- | src/plugins/reviewDB/utils.tsx | 34 |
12 files changed, 0 insertions, 1238 deletions
diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx deleted file mode 100644 index 1d95e47..0000000 --- a/src/plugins/reviewDB/auth.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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/MessageButton.tsx b/src/plugins/reviewDB/components/MessageButton.tsx deleted file mode 100644 index 965fd1c..0000000 --- a/src/plugins/reviewDB/components/MessageButton.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { DeleteIcon } from "@components/Icons"; -import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; -import { Tooltip } from "@webpack/common"; - -const iconClasses = findByPropsLazy("button", "wrapper", "disabled", "separator"); - -export function DeleteButton({ onClick }: { onClick(): void; }) { - return ( - <Tooltip text="Delete Review"> - {props => ( - <div - {...props} - className={classes(iconClasses.button, iconClasses.dangerous)} - onClick={onClick} - > - <DeleteIcon width="20" height="20" /> - </div> - )} - </Tooltip> - ); -} - -export function ReportButton({ onClick }: { onClick(): void; }) { - return ( - <Tooltip text="Report Review"> - {props => ( - <div - {...props} - className={iconClasses.button} - onClick={onClick} - > - <svg width="20" height="20" viewBox="0 0 24 24"> - <path - fill="currentColor" - d="M20,6.002H14V3.002C14,2.45 13.553,2.002 13,2.002H4C3.447,2.002 3,2.45 3,3.002V22.002H5V14.002H10.586L8.293,16.295C8.007,16.581 7.922,17.011 8.076,17.385C8.23,17.759 8.596,18.002 9,18.002H20C20.553,18.002 21,17.554 21,17.002V7.002C21,6.45 20.553,6.002 20,6.002Z" - /> - </svg> - </div> - )} - </Tooltip> - ); -} diff --git a/src/plugins/reviewDB/components/ReviewBadge.tsx b/src/plugins/reviewDB/components/ReviewBadge.tsx deleted file mode 100644 index 3c02c35..0000000 --- a/src/plugins/reviewDB/components/ReviewBadge.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { MaskedLinkStore, Tooltip } from "@webpack/common"; - -import { Badge } from "../entities"; -import { cl } from "../utils"; - -export default function ReviewBadge(badge: Badge) { - return ( - <Tooltip - text={badge.name}> - {({ onMouseEnter, onMouseLeave }) => ( - <img - className={cl("badge")} - width="22px" - height="22px" - onMouseEnter={onMouseEnter} - onMouseLeave={onMouseLeave} - src={badge.icon} - alt={badge.description} - onClick={() => - MaskedLinkStore.openUntrustedLink({ - href: badge.redirectURL, - }) - } - /> - )} - </Tooltip> - ); -} diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx deleted file mode 100644 index 1865917..0000000 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { openUserProfile } from "@utils/discord"; -import { classes } from "@utils/misc"; -import { LazyComponent } from "@utils/react"; -import { filters, findBulk } from "@webpack"; -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 } from "../utils"; -import { DeleteButton, ReportButton } from "./MessageButton"; -import ReviewBadge from "./ReviewBadge"; - -export default LazyComponent(() => { - // this is terrible, blame mantika - const p = filters.byProps; - const [ - { cozyMessage, buttons, message, buttonsInner, groupStart }, - { container, isHeader }, - { avatar, clickable, username, wrapper, cozy }, - buttonClasses, - botTag - ] = findBulk( - p("cozyMessage"), - p("container", "isHeader"), - p("avatar", "zalgo"), - p("button", "wrapper", "selected"), - p("botTag", "botTagRegular") - ); - - const dateFormat = new Intl.DateTimeFormat(); - - return function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) { - function openModal() { - openUserProfile(review.sender.discordID); - } - - function delReview() { - Alerts.show({ - title: "Are you sure?", - body: "Do you really want to delete this review?", - confirmText: "Delete", - cancelText: "Nevermind", - onConfirm: () => { - deleteReview(review.id).then(res => { - if (res.success) { - refetch(); - } - showToast(res.message); - }); - } - }); - } - - function reportRev() { - Alerts.show({ - title: "Are you sure?", - body: "Do you really you want to report this review?", - confirmText: "Report", - cancelText: "Nevermind", - // confirmColor: "red", this just adds a class name and breaks the submit button guh - onConfirm: () => reportReview(review.id) - }); - } - - return ( - <div className={classes(cozyMessage, wrapper, message, groupStart, cozy, cl("review"))} style={ - { - marginLeft: "0px", - paddingLeft: "52px", // wth is this - paddingRight: "16px" - } - }> - - <img - className={classes(avatar, clickable)} - onClick={openModal} - src={review.sender.profilePhoto || "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"} - style={{ left: "0px", zIndex: 0 }} - /> - <div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}> - <span - className={classes(clickable, username)} - style={{ color: "var(--channels-default)", fontSize: "14px" }} - onClick={() => openModal()} - > - {review.sender.username} - </span> - - {review.type === ReviewType.System && ( - <span - className={classes(botTag.botTagVerified, botTag.botTagRegular, botTag.botTag, botTag.px, botTag.rem)} - style={{ marginLeft: "4px" }}> - <span className={botTag.botText}> - System - </span> - </span> - )} - </div> - {review.sender.badges.map(badge => <ReviewBadge {...badge} />)} - - { - !settings.store.hideTimestamps && review.type !== ReviewType.System && ( - <Timestamp timestamp={moment(review.timestamp * 1000)} > - {dateFormat.format(review.timestamp * 1000)} - </Timestamp>) - } - - <div className={cl("review-comment")}> - {Parser.parseGuildEventDescription(review.comment)} - </div> - - {review.id !== 0 && ( - <div className={classes(container, isHeader, buttons)} style={{ - padding: "0px", - }}> - <div className={classes(buttonClasses.wrapper, buttonsInner)} > - <ReportButton onClick={reportRev} /> - - {canDeleteReview(profileId, review) && ( - <DeleteButton onClick={delReview} /> - )} - </div> - </div> - )} - </div> - ); - }; -}); diff --git a/src/plugins/reviewDB/components/ReviewModal.tsx b/src/plugins/reviewDB/components/ReviewModal.tsx deleted file mode 100644 index 9669a2b..0000000 --- a/src/plugins/reviewDB/components/ReviewModal.tsx +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import ErrorBoundary from "@components/ErrorBoundary"; -import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; -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 { cl } from "../utils"; -import ReviewComponent from "./ReviewComponent"; -import ReviewsView, { ReviewsInputComponent } from "./ReviewsView"; - -function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: string; name: string; }) { - const [data, setData] = useState<Response>(); - const [signal, refetch] = useForceUpdater(true); - const [page, setPage] = useState(1); - - const ref = useRef<HTMLDivElement>(null); - - const reviewCount = data?.reviewCount; - const ownReview = data?.reviews.find(r => r.sender.discordID === Auth.user?.discordID); - - return ( - <ErrorBoundary> - <ModalRoot {...modalProps} size={ModalSize.MEDIUM}> - <ModalHeader> - <Text variant="heading-lg/semibold" className={cl("modal-header")}> - {name}'s Reviews - {!!reviewCount && <span> ({reviewCount} Reviews)</span>} - </Text> - <ModalCloseButton onClick={modalProps.onClose} /> - </ModalHeader> - - <ModalContent scrollerRef={ref}> - <div className={cl("modal-reviews")}> - <ReviewsView - discordId={discordId} - name={name} - page={page} - refetchSignal={signal} - onFetchReviews={setData} - scrollToTop={() => ref.current?.scrollTo({ top: 0, behavior: "smooth" })} - hideOwnReview - /> - </div> - </ModalContent> - - <ModalFooter className={cl("modal-footer")}> - <div> - {ownReview && ( - <ReviewComponent - refetch={refetch} - review={ownReview} - profileId={discordId} - /> - )} - <ReviewsInputComponent - isAuthor={ownReview != null} - discordId={discordId} - name={name} - refetch={refetch} - /> - - {!!reviewCount && ( - <Paginator - currentPage={page} - maxVisiblePages={5} - pageSize={REVIEWS_PER_PAGE} - totalCount={reviewCount} - onPageChange={setPage} - /> - )} - </div> - </ModalFooter> - </ModalRoot> - </ErrorBoundary> - ); -} - -export function openReviewsModal(discordId: string, name: string) { - openModal(props => ( - <Modal - modalProps={props} - discordId={discordId} - name={name} - /> - )); -} diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx deleted file mode 100644 index a87598b..0000000 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { LazyComponent, useAwaiter, useForceUpdater } from "@utils/react"; -import { find, findByPropsLazy } from "@webpack"; -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 { cl } from "../utils"; -import ReviewComponent from "./ReviewComponent"; - - -const Editor = findByPropsLazy("start", "end", "addMark"); -const Transform = findByPropsLazy("unwrapNodes"); -const InputTypes = findByPropsLazy("VOICE_CHANNEL_STATUS", "SIDEBAR"); - -const InputComponent = LazyComponent(() => find(m => m?.type?.render?.toString().includes("CHANNEL_TEXT_AREA).AnalyticsLocationProvider"))); - -interface UserProps { - discordId: string; - name: string; -} - -interface Props extends UserProps { - onFetchReviews(data: Response): void; - refetchSignal?: unknown; - showInput?: boolean; - page?: number; - scrollToTop?(): void; - hideOwnReview?: boolean; -} - -export default function ReviewsView({ - discordId, - name, - onFetchReviews, - refetchSignal, - scrollToTop, - page = 1, - showInput = false, - hideOwnReview = false, -}: Props) { - const [signal, refetch] = useForceUpdater(true); - - const [reviewData] = useAwaiter(() => getReviews(discordId, (page - 1) * REVIEWS_PER_PAGE), { - fallbackValue: null, - deps: [refetchSignal, signal, page], - onSuccess: data => { - if (settings.store.hideBlockedUsers) - data!.reviews = data!.reviews?.filter(r => !RelationshipStore.isBlocked(r.sender.discordID)); - - scrollToTop?.(); - onFetchReviews(data!); - } - }); - - if (!reviewData) return null; - - return ( - <> - <ReviewList - refetch={refetch} - reviews={reviewData!.reviews} - hideOwnReview={hideOwnReview} - profileId={discordId} - /> - - {showInput && ( - <ReviewsInputComponent - name={name} - discordId={discordId} - refetch={refetch} - isAuthor={reviewData!.reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id)} - /> - )} - </> - ); -} - -function ReviewList({ refetch, reviews, hideOwnReview, profileId }: { refetch(): void; reviews: Review[]; hideOwnReview: boolean; profileId: string; }) { - const myId = UserStore.getCurrentUser().id; - - return ( - <div className={cl("view")}> - {reviews?.map(review => - (review.sender.discordID !== myId || !hideOwnReview) && - <ReviewComponent - key={review.id} - review={review} - refetch={refetch} - profileId={profileId} - /> - )} - - {reviews?.length === 0 && ( - <Forms.FormText className={cl("placeholder")}> - Looks like nobody reviewed this user yet. You could be the first! - </Forms.FormText> - )} - </div> - ); -} - - -export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; }) { - const { token } = Auth; - const editorRef = useRef<any>(null); - const inputType = InputTypes.FORM; - inputType.disableAutoFocus = true; - - const channel = { - flags_: 256, - guild_id_: null, - id: "0", - getGuildId: () => null, - isPrivate: () => true, - isActiveThread: () => false, - isArchivedLockedThread: () => false, - isDM: () => true, - roles: { "0": { permissions: 0n } }, - getRecipientId: () => "0", - hasFlag: () => false, - }; - - return ( - <> - <div onClick={() => { - if (!token) { - showToast("Opening authorization window..."); - authorize(); - } - }}> - <InputComponent - className={cl("input")} - channel={channel} - placeholder={ - !token - ? "You need to authorize to review users!" - : isAuthor - ? `Update review for @${name}` - : `Review @${name}` - } - type={inputType} - disableThemedBackground={true} - setEditorRef={ref => editorRef.current = ref} - textValue="" - onSubmit={ - async res => { - const response = await addReview({ - userid: discordId, - comment: res.value, - }); - - if (response?.success) { - refetch(); - - const slateEditor = editorRef.current.ref.current.getSlateEditor(); - - // clear editor - Transform.delete(slateEditor, { - at: { - anchor: Editor.start(slateEditor, []), - focus: Editor.end(slateEditor, []), - } - }); - } else if (response?.message) { - showToast(response.message); - } - - // even tho we need to return this, it doesnt do anything - return { - shouldClear: false, - shouldRefocus: true, - }; - } - } - /> - </div> - - </> - ); -} diff --git a/src/plugins/reviewDB/entities.ts b/src/plugins/reviewDB/entities.ts deleted file mode 100644 index 0a77fef..0000000 --- a/src/plugins/reviewDB/entities.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -export const enum UserType { - Banned = -1, - Normal = 0, - Admin = 1 -} - -export const enum ReviewType { - User = 0, - Server = 1, - Support = 2, - System = 3 -} - -export const enum NotificationType { - Info = 0, - Ban = 1, - Unban = 2, - Warning = 3 -} - -export interface ReviewDBAuth { - token?: string; - user?: ReviewDBUser; -} - -export interface Badge { - name: string; - description: string; - icon: string; - redirectURL: string; - type: number; -} - -export interface BanInfo { - id: string; - discordID: string; - reviewID: number; - reviewContent: string; - banEndDate: number; -} - -export interface Notification { - id: number; - title: string; - content: string; - type: NotificationType; -} - -export interface ReviewDBUser { - ID: number; - discordID: string; - username: string; - profilePhoto: string; - clientMod: string; - warningCount: number; - badges: any[]; - banInfo: BanInfo | null; - notification: Notification | null; - lastReviewID: number; - type: UserType; -} - -export interface ReviewAuthor { - id: number, - discordID: string, - username: string, - profilePhoto: string, - badges: Badge[]; -} - -export interface Review { - comment: string, - id: number, - star: number, - sender: ReviewAuthor, - timestamp: number; - type?: ReviewType; -} diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx deleted file mode 100644 index b9350ba..0000000 --- a/src/plugins/reviewDB/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import "./style.css"; - -import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; -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, 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"; - -const guildPopoutPatch: NavContextMenuPatchCallback = (children, props: { guild: Guild, onClose(): void; }) => () => { - children.push( - <Menu.MenuItem - label="View Reviews" - id="vc-rdb-server-reviews" - icon={OpenExternalIcon} - action={() => openReviewsModal(props.guild.id, props.guild.name)} - /> - ); -}; - -export default definePlugin({ - name: "ReviewDB", - description: "Review other users (Adds a new settings to profiles)", - authors: [Devs.mantikafasi, Devs.Ven], - - settings, - - patches: [ - { - find: "disableBorderColor:!0", - replacement: { - match: /\(.{0,10}\{user:(.),setNote:.,canDM:.,.+?\}\)/, - replace: "$&,$self.getReviewsComponent($1)" - } - } - ], - - flux: { - CONNECTION_OPEN: initAuth, - }, - - async start() { - addContextMenuPatch("guild-header-popout", guildPopoutPatch); - - const s = settings.store; - 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"); - } - - await initAuth(); - - setTimeout(async () => { - if (!Auth.token) return; - - const user = await getCurrentUserInfo(Auth.token); - updateAuth({ user }); - - 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: async () => - VencordNative.native.openExternal( - "https://reviewdb.mantikafasi.dev/api/redirect?" - + new URLSearchParams({ - token: Auth.token!, - page: "dashboard/appeal" - }) - ) - } : {}; - - Alerts.show({ - title: user.notification.title, - body: ( - Parser.parse( - user.notification.content, - false - ) - ), - ...props - }); - - readNotification(user.notification.id); - } - }, 4000); - }, - - stop() { - removeContextMenuPatch("guild-header-popout", guildPopoutPatch); - }, - - getReviewsComponent: ErrorBoundary.wrap((user: User) => { - const [reviewCount, setReviewCount] = useState<number>(); - - return ( - <ExpandableHeader - headerText="User Reviews" - onMoreClick={() => openReviewsModal(user.id, user.username)} - moreTooltipText={ - reviewCount && reviewCount > 50 - ? `View all ${reviewCount} reviews` - : "Open Review Modal" - } - onDropDownClick={state => settings.store.reviewsDropdownState = !state} - defaultState={settings.store.reviewsDropdownState} - > - <ReviewsView - discordId={user.id} - name={user.username} - onFetchReviews={r => setReviewCount(r.reviewCount)} - showInput - /> - </ExpandableHeader> - ); - }, { message: "Failed to render Reviews" }) -}); diff --git a/src/plugins/reviewDB/reviewDbApi.ts b/src/plugins/reviewDB/reviewDbApi.ts deleted file mode 100644 index add16dd..0000000 --- a/src/plugins/reviewDB/reviewDbApi.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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"; - -const API_URL = "https://manti.vendicated.dev"; - -export const REVIEWS_PER_PAGE = 50; - -export interface Response { - success: boolean, - message: string; - reviews: Review[]; - updated: boolean; - hasNextPage: boolean; - reviewCount: number; -} - -const WarningFlag = 0b00000010; - -export async function getReviews(id: string, offset = 0): Promise<Response> { - let flags = 0; - if (!settings.store.showWarning) flags |= WarningFlag; - - const params = new URLSearchParams({ - flags: String(flags), - offset: String(offset) - }); - const req = await fetch(`${API_URL}/api/reviewdb/users/${id}/reviews?${params}`); - - const res = (req.status === 200) - ? await req.json() as Response - : { - success: false, - message: "An Error occured while fetching reviews. Please try again later.", - reviews: [], - updated: false, - hasNextPage: false, - reviewCount: 0 - }; - - if (!res.success) { - showToast(res.message, Toasts.Type.FAILURE); - return { - ...res, - reviews: [ - { - id: 0, - comment: "An Error occured while fetching reviews. Please try again later.", - star: 0, - timestamp: 0, - sender: { - id: 0, - username: "Error", - profilePhoto: "https://cdn.discordapp.com/attachments/1045394533384462377/1084900598035513447/646808599204593683.png?size=128", - discordID: "0", - badges: [] - } - } - ] - }; - } - - return res; -} - -export async function addReview(review: any): Promise<Response | null> { - review.token = await getToken(); - - if (!review.token) { - showToast("Please authorize to add a review."); - authorize(); - return null; - } - - return fetch(API_URL + `/api/reviewdb/users/${review.userid}/reviews`, { - method: "PUT", - body: JSON.stringify(review), - headers: { - "Content-Type": "application/json", - } - }) - .then(r => r.json()) - .then(res => { - showToast(res.message); - return res ?? null; - }); -} - -export async function deleteReview(id: number): Promise<Response> { - return fetch(API_URL + `/api/reviewdb/users/${id}/reviews`, { - method: "DELETE", - headers: new Headers({ - "Content-Type": "application/json", - Accept: "application/json", - }), - body: JSON.stringify({ - token: await getToken(), - reviewid: id - }) - }).then(r => r.json()); -} - -export async function reportReview(id: number) { - const res = await fetch(API_URL + "/api/reviewdb/reports", { - method: "PUT", - headers: new Headers({ - "Content-Type": "application/json", - Accept: "application/json", - }), - body: JSON.stringify({ - reviewid: id, - token: await getToken() - }) - }).then(r => r.json()) as Response; - - showToast(res.message); -} - -export function getCurrentUserInfo(token: string): Promise<ReviewDBUser> { - return fetch(API_URL + "/api/reviewdb/users", { - body: JSON.stringify({ token }), - method: "POST", - }).then(r => r.json()); -} - -export async function readNotification(id: number) { - return fetch(API_URL + `/api/reviewdb/notifications?id=${id}`, { - method: "PATCH", - headers: { - "Authorization": await getToken() || "", - }, - }); -} diff --git a/src/plugins/reviewDB/settings.tsx b/src/plugins/reviewDB/settings.tsx deleted file mode 100644 index cf61a38..0000000 --- a/src/plugins/reviewDB/settings.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { definePluginSettings } from "@api/Settings"; -import { OptionType } from "@utils/types"; -import { Button } from "@webpack/common"; - -import { authorize, getToken } from "./auth"; - -export const settings = definePluginSettings({ - authorize: { - type: OptionType.COMPONENT, - description: "Authorize with ReviewDB", - component: () => ( - <Button onClick={authorize}> - Authorize with ReviewDB - </Button> - ) - }, - notifyReviews: { - type: OptionType.BOOLEAN, - description: "Notify about new reviews on startup", - default: true, - }, - showWarning: { - type: OptionType.BOOLEAN, - description: "Display warning to be respectful at the top of the reviews list", - default: true, - }, - hideTimestamps: { - type: OptionType.BOOLEAN, - description: "Hide timestamps on reviews", - default: false, - }, - hideBlockedUsers: { - type: OptionType.BOOLEAN, - description: "Hide reviews from blocked users", - default: true, - }, - website: { - type: OptionType.COMPONENT, - description: "ReviewDB website", - component: () => ( - <Button onClick={async () => { - let url = "https://reviewdb.mantikafasi.dev/"; - const token = await getToken(); - if (token) - url += "/api/redirect?token=" + encodeURIComponent(token); - - VencordNative.native.openExternal(url); - }}> - ReviewDB website - </Button> - ) - }, - supportServer: { - type: OptionType.COMPONENT, - description: "ReviewDB Support Server", - component: () => ( - <Button onClick={() => { - VencordNative.native.openExternal("https://discord.gg/eWPBSbvznt"); - }}> - ReviewDB Support Server - </Button> - ) - } -}).withPrivateSettings<{ - lastReviewId?: number; - reviewsDropdownState?: boolean; -}>(); diff --git a/src/plugins/reviewDB/style.css b/src/plugins/reviewDB/style.css deleted file mode 100644 index f4d890f..0000000 --- a/src/plugins/reviewDB/style.css +++ /dev/null @@ -1,76 +0,0 @@ -[class|="section"]:not([class|="lastSection"]) + .vc-rdb-view { - margin-top: 12px; -} - -.vc-rdb-badge { - vertical-align: middle; - margin-left: 4px; -} - -.vc-rdb-input { - margin-top: 6px; - margin-bottom: 12px; - resize: none; - overflow: hidden; - background: transparent; - border: 1px solid var(--profile-message-input-border-color); -} - -.vc-rdb-modal-footer > div { - width: 100%; - margin: 6px 16px; -} - -/* When input becomes disabled(while sending review), input adds unneccesary padding to left, this prevents it */ -.vc-rdb-input > div > div { - padding-left: 0 !important; -} - -.vc-rdb-placeholder { - margin-bottom: 4px; - font-weight: bold; - font-style: italic; - color: var(--text-muted); -} - -.vc-rdb-input * { - font-size: 14px; -} - -.vc-rdb-modal-footer { - padding: 0; -} - -.vc-rdb-modal-footer .vc-rdb-input { - margin-bottom: 0; - background: var(--input-background); -} - -.vc-rdb-modal-footer [class|="pageControlContainer"] { - margin-top: 0; -} - -.vc-rdb-modal-header { - flex-grow: 1; -} - -.vc-rdb-modal-reviews { - margin-top: 16px; -} - -.vc-rdb-review { - margin-top: 8px; - margin-bottom: 8px; -} - -.vc-rdb-review-comment img { - vertical-align: text-top; -} - -.vc-rdb-review-comment { - overflow-y: hidden; - margin-top: 1px; - margin-bottom: 8px; - color: var(--text-normal); - font-size: 15px; -} diff --git a/src/plugins/reviewDB/utils.tsx b/src/plugins/reviewDB/utils.tsx deleted file mode 100644 index ab66d53..0000000 --- a/src/plugins/reviewDB/utils.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import { classNameFactory } from "@api/Styles"; -import { UserStore } from "@webpack/common"; - -import { Auth } from "./auth"; -import { Review, UserType } from "./entities"; - -export const cl = classNameFactory("vc-rdb-"); - -export function canDeleteReview(profileId: string, review: Review) { - const myId = UserStore.getCurrentUser().id; - return ( - myId === profileId - || review.sender.discordID === profileId - || Auth.user?.type === UserType.Admin - ); -} |