ReviewDB: make warning review disableable; add timestamps (#948)
This commit is contained in:
parent
5b485806ea
commit
043381963b
7 changed files with 93 additions and 23 deletions
|
@ -19,6 +19,7 @@
|
||||||
import { Settings } from "@api/settings";
|
import { Settings } from "@api/settings";
|
||||||
|
|
||||||
import { Review } from "../entities/Review";
|
import { Review } from "../entities/Review";
|
||||||
|
import { ReviewDBUser } from "../entities/User";
|
||||||
import { authorize, showToast } from "./Utils";
|
import { authorize, showToast } from "./Utils";
|
||||||
|
|
||||||
const API_URL = "https://manti.vendicated.dev";
|
const API_URL = "https://manti.vendicated.dev";
|
||||||
|
@ -32,8 +33,12 @@ interface Response {
|
||||||
updated: boolean;
|
updated: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WarningFlag = 0b00000010;
|
||||||
|
|
||||||
export async function getReviews(id: string): Promise<Review[]> {
|
export async function getReviews(id: string): Promise<Review[]> {
|
||||||
const req = await fetch(API_URL + `/api/reviewdb/users/${id}/reviews`);
|
var flags = 0;
|
||||||
|
if (!Settings.plugins.ReviewDB.showWarning) flags |= WarningFlag;
|
||||||
|
const req = await fetch(API_URL + `/api/reviewdb/users/${id}/reviews?flags=${flags}`);
|
||||||
|
|
||||||
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 };
|
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 };
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
|
@ -43,6 +48,7 @@ export async function getReviews(id: string): Promise<Review[]> {
|
||||||
id: 0,
|
id: 0,
|
||||||
comment: "An Error occured while fetching reviews. Please try again later.",
|
comment: "An Error occured while fetching reviews. Please try again later.",
|
||||||
star: 0,
|
star: 0,
|
||||||
|
timestamp: 0,
|
||||||
sender: {
|
sender: {
|
||||||
id: 0,
|
id: 0,
|
||||||
username: "Error",
|
username: "Error",
|
||||||
|
@ -108,8 +114,10 @@ export async function reportReview(id: number) {
|
||||||
showToast(await res.message);
|
showToast(await res.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLastReviewID(id: string): Promise<number> {
|
export function getCurrentUserInfo(token: string): Promise<ReviewDBUser> {
|
||||||
return fetch(API_URL + "/getLastReviewID?discordid=" + id)
|
return fetch(API_URL + "/api/reviewdb/users", {
|
||||||
.then(r => r.text())
|
body: JSON.stringify({ token }),
|
||||||
.then(Number);
|
method: "POST",
|
||||||
|
})
|
||||||
|
.then(r => r.json());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings } from "@api/settings";
|
import { Settings } from "@api/settings";
|
||||||
import { Devs } from "@utils/constants";
|
|
||||||
import Logger from "@utils/Logger";
|
import Logger from "@utils/Logger";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { findByProps } from "@webpack";
|
import { findByProps } from "@webpack";
|
||||||
import { FluxDispatcher, React, SelectedChannelStore, Toasts, UserUtils } from "@webpack/common";
|
import { FluxDispatcher, React, SelectedChannelStore, Toasts, UserUtils } from "@webpack/common";
|
||||||
|
|
||||||
import { Review } from "../entities/Review";
|
import { Review } from "../entities/Review";
|
||||||
|
import { UserType } from "../entities/User";
|
||||||
|
|
||||||
export async function openUserProfileModal(userId: string) {
|
export async function openUserProfileModal(userId: string) {
|
||||||
await UserUtils.fetchUser(userId);
|
await UserUtils.fetchUser(userId);
|
||||||
|
@ -86,10 +86,5 @@ export function showToast(text: string) {
|
||||||
export const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
export const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
||||||
|
|
||||||
export function canDeleteReview(review: Review, userId: string) {
|
export function canDeleteReview(review: Review, userId: string) {
|
||||||
if (review.sender.discordID === userId) return true;
|
if (review.sender.discordID === userId || Settings.plugins.ReviewDB.userType === UserType.Admin) return true;
|
||||||
|
|
||||||
const myId = BigInt(userId);
|
|
||||||
return myId === Devs.mantikafasi.id ||
|
|
||||||
myId === Devs.Ven.id ||
|
|
||||||
myId === Devs.rushii.id;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Settings } from "@api/settings";
|
||||||
import { classes, LazyComponent } from "@utils/misc";
|
import { classes, LazyComponent } from "@utils/misc";
|
||||||
import { filters, findBulk } from "@webpack";
|
import { filters, findBulk } from "@webpack";
|
||||||
import { Alerts, UserStore } from "@webpack/common";
|
import { Alerts, moment, Timestamp, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { Review } from "../entities/Review";
|
import { Review } from "../entities/Review";
|
||||||
import { deleteReview, reportReview } from "../Utils/ReviewDBAPI";
|
import { deleteReview, reportReview } from "../Utils/ReviewDBAPI";
|
||||||
|
@ -32,7 +33,7 @@ export default LazyComponent(() => {
|
||||||
const [
|
const [
|
||||||
{ cozyMessage, buttons, message, groupStart },
|
{ cozyMessage, buttons, message, groupStart },
|
||||||
{ container, isHeader },
|
{ container, isHeader },
|
||||||
{ avatar, clickable, username, messageContent, wrapper, cozy },
|
{ avatar, clickable, username, messageContent, wrapper, cozy, timestampInline, timestamp },
|
||||||
{ contents },
|
{ contents },
|
||||||
buttonClasses,
|
buttonClasses,
|
||||||
{ defaultColor }
|
{ defaultColor }
|
||||||
|
@ -102,6 +103,16 @@ export default LazyComponent(() => {
|
||||||
{review.sender.username}
|
{review.sender.username}
|
||||||
</span>
|
</span>
|
||||||
{review.sender.badges.map(badge => <ReviewBadge {...badge} />)}
|
{review.sender.badges.map(badge => <ReviewBadge {...badge} />)}
|
||||||
|
|
||||||
|
{
|
||||||
|
!Settings.plugins.ReviewDB.hideTimestamps && (
|
||||||
|
<Timestamp
|
||||||
|
timestamp={moment(review.timestamp * 1000)}
|
||||||
|
compact={true}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
<p
|
<p
|
||||||
className={classes(messageContent, defaultColor)}
|
className={classes(messageContent, defaultColor)}
|
||||||
style={{ fontSize: 15, marginTop: 4 }}
|
style={{ fontSize: 15, marginTop: 4 }}
|
||||||
|
|
|
@ -16,18 +16,20 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Settings } from "@api/settings";
|
||||||
import { classes, useAwaiter } from "@utils/misc";
|
import { classes, useAwaiter } from "@utils/misc";
|
||||||
import { findLazy } from "@webpack";
|
import { findLazy } from "@webpack";
|
||||||
import { Forms, React, Text, UserStore } from "@webpack/common";
|
import { Forms, React, Text, UserStore } from "@webpack/common";
|
||||||
import type { KeyboardEvent } from "react";
|
import type { KeyboardEvent } from "react";
|
||||||
|
|
||||||
import { addReview, getReviews } from "../Utils/ReviewDBAPI";
|
import { addReview, getReviews } from "../Utils/ReviewDBAPI";
|
||||||
import { showToast } from "../Utils/Utils";
|
import { authorize, showToast } from "../Utils/Utils";
|
||||||
import ReviewComponent from "./ReviewComponent";
|
import ReviewComponent from "./ReviewComponent";
|
||||||
|
|
||||||
const Classes = findLazy(m => typeof m.textarea === "string");
|
const Classes = findLazy(m => typeof m.textarea === "string");
|
||||||
|
|
||||||
export default function ReviewsView({ userId }: { userId: string; }) {
|
export default function ReviewsView({ userId }: { userId: string; }) {
|
||||||
|
const { token } = Settings.plugins.ReviewDB;
|
||||||
const [refetchCount, setRefetchCount] = React.useState(0);
|
const [refetchCount, setRefetchCount] = React.useState(0);
|
||||||
const [reviews, _, isLoading] = useAwaiter(() => getReviews(userId), {
|
const [reviews, _, isLoading] = useAwaiter(() => getReviews(userId), {
|
||||||
fallbackValue: [],
|
fallbackValue: [],
|
||||||
|
@ -83,8 +85,21 @@ export default function ReviewsView({ userId }: { userId: string; }) {
|
||||||
<textarea
|
<textarea
|
||||||
className={classes(Classes.textarea.replace("textarea", ""), "enter-comment")}
|
className={classes(Classes.textarea.replace("textarea", ""), "enter-comment")}
|
||||||
// this produces something like '-_59yqs ...' but since no class exists with that name its fine
|
// this produces something like '-_59yqs ...' but since no class exists with that name its fine
|
||||||
placeholder={reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id) ? `Update review for @${username}` : `Review @${username}`}
|
placeholder={
|
||||||
|
token
|
||||||
|
? (reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id)
|
||||||
|
? `Update review for @${username}`
|
||||||
|
: `Review @${username}`)
|
||||||
|
: "You need to authorize to review users!"
|
||||||
|
}
|
||||||
onKeyDown={onKeyPress}
|
onKeyDown={onKeyPress}
|
||||||
|
onClick={() => {
|
||||||
|
if (!token) {
|
||||||
|
showToast("Opening authorization window...");
|
||||||
|
authorize();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
style={{
|
style={{
|
||||||
marginTop: "6px",
|
marginTop: "6px",
|
||||||
resize: "none",
|
resize: "none",
|
||||||
|
|
|
@ -31,4 +31,5 @@ export interface Review {
|
||||||
id: number,
|
id: number,
|
||||||
star: number,
|
star: number,
|
||||||
sender: Sender,
|
sender: Sender,
|
||||||
|
timestamp: number
|
||||||
}
|
}
|
||||||
|
|
28
src/plugins/reviewDB/entities/User.ts
Normal file
28
src/plugins/reviewDB/entities/User.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 interface ReviewDBUser {
|
||||||
|
lastReviewID: number,
|
||||||
|
type: UserType;
|
||||||
|
}
|
|
@ -22,11 +22,11 @@ import { Settings } from "@api/settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Button, UserStore } from "@webpack/common";
|
import { Button } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
import ReviewsView from "./components/ReviewsView";
|
import ReviewsView from "./components/ReviewsView";
|
||||||
import { getLastReviewID } from "./Utils/ReviewDBAPI";
|
import { getCurrentUserInfo } from "./Utils/ReviewDBAPI";
|
||||||
import { authorize, showToast } from "./Utils/Utils";
|
import { authorize, showToast } from "./Utils/Utils";
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
@ -58,19 +58,31 @@ export default definePlugin({
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
description: "Notify about new reviews on startup",
|
description: "Notify about new reviews on startup",
|
||||||
default: true,
|
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,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
const settings = Settings.plugins.ReviewDB;
|
const settings = Settings.plugins.ReviewDB;
|
||||||
if (!settings.lastReviewId || !settings.notifyReviews) return;
|
if (!settings.notifyReviews || !settings.token) return;
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
const id = await getLastReviewID(UserStore.getCurrentUser().id);
|
const user = await getCurrentUserInfo(settings.token);
|
||||||
if (settings.lastReviewId < id) {
|
if (settings.lastReviewId < user.lastReviewID) {
|
||||||
showToast("You have new reviews on your profile!");
|
settings.lastReviewId = user.lastReviewID;
|
||||||
settings.lastReviewId = id;
|
if (user.lastReviewID !== 0)
|
||||||
|
showToast("You have new reviews on your profile!");
|
||||||
}
|
}
|
||||||
|
settings.userType = user.type;
|
||||||
}, 4000);
|
}, 4000);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue