[ReviewDB] update for new api changes; some fixes (#2120)

Co-authored-by: Vendicated <vendicated@riseup.net>
This commit is contained in:
Manti 2024-01-22 03:18:48 +03:00 committed by GitHub
parent 1670733458
commit e707538b73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 126 additions and 84 deletions

View file

@ -61,14 +61,17 @@ export function authorize(callback?: any) {
const res = await fetch(url, { const res = await fetch(url, {
headers: new Headers({ Accept: "application/json" }) headers: new Headers({ Accept: "application/json" })
}); });
const { token, success } = await res.json();
if (success) { if (!res.ok) {
updateAuth({ token }); const { message } = await res.json();
showToast("Successfully logged in!", Toasts.Type.SUCCESS); showToast(message || "An error occured while authorizing", Toasts.Type.FAILURE);
callback?.(); return;
} else if (res.status === 1) {
showToast("An Error occurred while logging in.", Toasts.Type.FAILURE);
} }
const { token } = await res.json();
updateAuth({ token });
showToast("Successfully logged in!", Toasts.Type.SUCCESS);
callback?.();
} catch (e) { } catch (e) {
new Logger("ReviewDB").error("Failed to authorize", e); new Logger("ReviewDB").error("Failed to authorize", e);
} }

View file

@ -20,13 +20,13 @@ import { openUserProfile } from "@utils/discord";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import { LazyComponent } from "@utils/react"; import { LazyComponent } from "@utils/react";
import { filters, findBulk } from "@webpack"; import { filters, findBulk } from "@webpack";
import { Alerts, moment, Parser, showToast, Timestamp } from "@webpack/common"; import { Alerts, moment, Parser, Timestamp, useState } from "@webpack/common";
import { Auth, getToken } from "../auth"; import { Auth, getToken } from "../auth";
import { Review, ReviewType } from "../entities"; import { Review, ReviewType } from "../entities";
import { blockUser, deleteReview, reportReview, unblockUser } from "../reviewDbApi"; import { blockUser, deleteReview, reportReview, unblockUser } from "../reviewDbApi";
import { settings } from "../settings"; import { settings } from "../settings";
import { canBlockReviewAuthor, canDeleteReview, canReportReview, cl } from "../utils"; import { canBlockReviewAuthor, canDeleteReview, canReportReview, cl, showToast } from "../utils";
import { openBlockModal } from "./BlockedUserModal"; import { openBlockModal } from "./BlockedUserModal";
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton"; import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
import ReviewBadge from "./ReviewBadge"; import ReviewBadge from "./ReviewBadge";
@ -51,6 +51,8 @@ export default LazyComponent(() => {
const dateFormat = new Intl.DateTimeFormat(); const dateFormat = new Intl.DateTimeFormat();
return function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) { return function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) {
const [showAll, setShowAll] = useState(false);
function openModal() { function openModal() {
openUserProfile(review.sender.discordID); openUserProfile(review.sender.discordID);
} }
@ -66,10 +68,9 @@ export default LazyComponent(() => {
return showToast("You must be logged in to delete reviews."); return showToast("You must be logged in to delete reviews.");
} else { } else {
deleteReview(review.id).then(res => { deleteReview(review.id).then(res => {
if (res.success) { if (res) {
refetch(); refetch();
} }
showToast(res.message);
}); });
} }
} }
@ -116,11 +117,11 @@ export default LazyComponent(() => {
} }
return ( return (
<div className={classes(cozyMessage, wrapper, message, groupStart, cozy, cl("review"))} style={ <div className={classes(cl("review"), cozyMessage, wrapper, message, groupStart, cozy)} style={
{ {
marginLeft: "0px", marginLeft: "0px",
paddingLeft: "52px", // wth is this paddingLeft: "52px", // wth is this
paddingRight: "16px" // nobody knows anymore
} }
}> }>
@ -168,7 +169,9 @@ export default LazyComponent(() => {
} }
<div className={cl("review-comment")}> <div className={cl("review-comment")}>
{Parser.parseGuildEventDescription(review.comment)} {(review.comment.length > 200 && !showAll)
? [Parser.parseGuildEventDescription(review.comment.substring(0, 200)), "...", <br />, (<a onClick={() => setShowAll(true)}>Read more</a>)]
: Parser.parseGuildEventDescription(review.comment)}
</div> </div>
{review.id !== 0 && ( {review.id !== 0 && (

View file

@ -18,13 +18,13 @@
import { LazyComponent, useAwaiter, useForceUpdater } from "@utils/react"; import { LazyComponent, useAwaiter, useForceUpdater } from "@utils/react";
import { find, findByPropsLazy } from "@webpack"; import { find, findByPropsLazy } from "@webpack";
import { Forms, React, RelationshipStore, showToast, useRef, UserStore } from "@webpack/common"; import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common";
import { Auth, authorize } from "../auth"; import { Auth, authorize } from "../auth";
import { Review } from "../entities"; import { Review } from "../entities";
import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi"; import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi";
import { settings } from "../settings"; import { settings } from "../settings";
import { cl } from "../utils"; import { cl, showToast } from "../utils";
import ReviewComponent from "./ReviewComponent"; import ReviewComponent from "./ReviewComponent";
@ -168,7 +168,7 @@ export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: {
comment: res.value, comment: res.value,
}); });
if (response?.success) { if (response) {
refetch(); refetch();
const slateEditor = editorRef.current.ref.current.getSlateEditor(); const slateEditor = editorRef.current.ref.current.getSlateEditor();
@ -180,8 +180,6 @@ export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: {
focus: Editor.end(slateEditor, []), focus: Editor.end(slateEditor, []),
} }
}); });
} else if (response?.message) {
showToast(response.message);
} }
// even tho we need to return this, it doesnt do anything // even tho we need to return this, it doesnt do anything

View file

@ -25,7 +25,7 @@ import { OpenExternalIcon } from "@components/Icons";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { Alerts, Menu, Parser, showToast, useState } from "@webpack/common"; import { Alerts, Menu, Parser, useState } from "@webpack/common";
import { Guild, User } from "discord-types/general"; import { Guild, User } from "discord-types/general";
import { Auth, initAuth, updateAuth } from "./auth"; import { Auth, initAuth, updateAuth } from "./auth";
@ -34,6 +34,7 @@ import ReviewsView from "./components/ReviewsView";
import { NotificationType } from "./entities"; import { NotificationType } from "./entities";
import { getCurrentUserInfo, readNotification } from "./reviewDbApi"; import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
import { settings } from "./settings"; import { settings } from "./settings";
import { showToast } from "./utils";
const guildPopoutPatch: NavContextMenuPatchCallback = (children, props: { guild: Guild, onClose(): void; }) => () => { const guildPopoutPatch: NavContextMenuPatchCallback = (children, props: { guild: Guild, onClose(): void; }) => () => {
children.push( children.push(

View file

@ -16,18 +16,18 @@
* 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 { showToast, Toasts } from "@webpack/common"; import { Toasts } from "@webpack/common";
import { Auth, authorize, getToken, updateAuth } from "./auth"; import { Auth, authorize, getToken, updateAuth } from "./auth";
import { Review, ReviewDBCurrentUser, ReviewDBUser, ReviewType } from "./entities"; import { Review, ReviewDBCurrentUser, ReviewDBUser, ReviewType } from "./entities";
import { settings } from "./settings"; import { settings } from "./settings";
import { showToast } from "./utils";
const API_URL = "https://manti.vendicated.dev/api/reviewdb"; const API_URL = "https://manti.vendicated.dev/api/reviewdb";
export const REVIEWS_PER_PAGE = 50; export const REVIEWS_PER_PAGE = 50;
export interface Response { export interface Response {
success: boolean,
message: string; message: string;
reviews: Review[]; reviews: Review[];
updated: boolean; updated: boolean;
@ -37,6 +37,16 @@ export interface Response {
const WarningFlag = 0b00000010; const WarningFlag = 0b00000010;
async function rdbRequest(path: string, options: RequestInit = {}) {
return fetch(API_URL + path, {
...options,
headers: {
...options.headers,
Authorization: await getToken() || "",
}
});
}
export async function getReviews(id: string, offset = 0): Promise<Response> { export async function getReviews(id: string, offset = 0): Promise<Response> {
let flags = 0; let flags = 0;
if (!settings.store.showWarning) flags |= WarningFlag; if (!settings.store.showWarning) flags |= WarningFlag;
@ -47,10 +57,9 @@ export async function getReviews(id: string, offset = 0): Promise<Response> {
}); });
const req = await fetch(`${API_URL}/users/${id}/reviews?${params}`); const req = await fetch(`${API_URL}/users/${id}/reviews?${params}`);
const res = (req.status === 200) const res = (req.ok)
? await req.json() as Response ? await req.json() as Response
: { : {
success: false,
message: req.status === 429 ? "You are sending requests too fast. Wait a few seconds and try again." : "An Error occured while fetching reviews. Please try again later.", message: req.status === 429 ? "You are sending requests too fast. Wait a few seconds and try again." : "An Error occured while fetching reviews. Please try again later.",
reviews: [], reviews: [],
updated: false, updated: false,
@ -58,7 +67,7 @@ export async function getReviews(id: string, offset = 0): Promise<Response> {
reviewCount: 0 reviewCount: 0
}; };
if (!res.success) { if (!req.ok) {
showToast(res.message, Toasts.Type.FAILURE); showToast(res.message, Toasts.Type.FAILURE);
return { return {
...res, ...res,
@ -85,44 +94,46 @@ export async function getReviews(id: string, offset = 0): Promise<Response> {
} }
export async function addReview(review: any): Promise<Response | null> { export async function addReview(review: any): Promise<Response | null> {
review.token = await getToken();
if (!review.token) { const token = await getToken();
if (!token) {
showToast("Please authorize to add a review."); showToast("Please authorize to add a review.");
authorize(); authorize();
return null; return null;
} }
return fetch(API_URL + `/users/${review.userid}/reviews`, { return await rdbRequest(`/users/${review.userid}/reviews`, {
method: "PUT", method: "PUT",
body: JSON.stringify(review), body: JSON.stringify(review),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
} }
}) }).then(async r => {
.then(r => r.json()) const data = await r.json() as Response;
.then(res => { showToast(data.message);
showToast(res.message); return r.ok ? data : null;
return res ?? null; });
});
} }
export async function deleteReview(id: number): Promise<Response> { export async function deleteReview(id: number): Promise<Response | null> {
return fetch(API_URL + `/users/${id}/reviews`, { return await rdbRequest(`/users/${id}/reviews`, {
method: "DELETE", method: "DELETE",
headers: new Headers({ headers: new Headers({
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}), }),
body: JSON.stringify({ body: JSON.stringify({
token: await getToken(),
reviewid: id reviewid: id
}) })
}).then(r => r.json()); }).then(async r => {
const data = await r.json() as Response;
showToast(data.message);
return r.ok ? data : null;
});
} }
export async function reportReview(id: number) { export async function reportReview(id: number) {
const res = await fetch(API_URL + "/reports", { const res = await rdbRequest("/reports", {
method: "PUT", method: "PUT",
headers: new Headers({ headers: new Headers({
"Content-Type": "application/json", "Content-Type": "application/json",
@ -130,7 +141,6 @@ export async function reportReview(id: number) {
}), }),
body: JSON.stringify({ body: JSON.stringify({
reviewid: id, reviewid: id,
token: await getToken()
}) })
}).then(r => r.json()) as Response; }).then(r => r.json()) as Response;
@ -138,12 +148,11 @@ export async function reportReview(id: number) {
} }
async function patchBlock(action: "block" | "unblock", userId: string) { async function patchBlock(action: "block" | "unblock", userId: string) {
const res = await fetch(API_URL + "/blocks", { const res = await rdbRequest("/blocks", {
method: "PATCH", method: "PATCH",
headers: new Headers({ headers: new Headers({
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
Authorization: await getToken() || ""
}), }),
body: JSON.stringify({ body: JSON.stringify({
action: action, action: action,
@ -169,11 +178,10 @@ export const blockUser = (userId: string) => patchBlock("block", userId);
export const unblockUser = (userId: string) => patchBlock("unblock", userId); export const unblockUser = (userId: string) => patchBlock("unblock", userId);
export async function fetchBlocks(): Promise<ReviewDBUser[]> { export async function fetchBlocks(): Promise<ReviewDBUser[]> {
const res = await fetch(API_URL + "/blocks", { const res = await rdbRequest("/blocks", {
method: "GET", method: "GET",
headers: new Headers({ headers: new Headers({
Accept: "application/json", Accept: "application/json",
Authorization: await getToken() || ""
}) })
}); });
@ -182,17 +190,13 @@ export async function fetchBlocks(): Promise<ReviewDBUser[]> {
} }
export function getCurrentUserInfo(token: string): Promise<ReviewDBCurrentUser> { export function getCurrentUserInfo(token: string): Promise<ReviewDBCurrentUser> {
return fetch(API_URL + "/users", { return rdbRequest("/users", {
body: JSON.stringify({ token }),
method: "POST", method: "POST",
}).then(r => r.json()); }).then(r => r.json());
} }
export async function readNotification(id: number) { export async function readNotification(id: number) {
return fetch(API_URL + `/notifications?id=${id}`, { return rdbRequest(`/notifications?id=${id}`, {
method: "PATCH", method: "PATCH"
headers: {
"Authorization": await getToken() || "",
},
}); });
} }

View file

@ -22,13 +22,14 @@ import { Button } from "@webpack/common";
import { authorize, getToken } from "./auth"; import { authorize, getToken } from "./auth";
import { openBlockModal } from "./components/BlockedUserModal"; import { openBlockModal } from "./components/BlockedUserModal";
import { cl } from "./utils";
export const settings = definePluginSettings({ export const settings = definePluginSettings({
authorize: { authorize: {
type: OptionType.COMPONENT, type: OptionType.COMPONENT,
description: "Authorize with ReviewDB", description: "Authorize with ReviewDB",
component: () => ( component: () => (
<Button onClick={authorize}> <Button onClick={() => authorize()}>
Authorize with ReviewDB Authorize with ReviewDB
</Button> </Button>
) )
@ -53,38 +54,40 @@ export const settings = definePluginSettings({
description: "Hide reviews from blocked users", description: "Hide reviews from blocked users",
default: true, default: true,
}, },
manageBlocks: { buttons: {
type: OptionType.COMPONENT, type: OptionType.COMPONENT,
description: "Manage Blocked Users", description: "ReviewDB buttons",
component: () => ( component: () => (
<Button onClick={openBlockModal}>Manage Blocked Users</Button> <div className={cl("button-grid")} >
) <Button onClick={openBlockModal}>Manage Blocked Users</Button>
},
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); <Button
}}> color={Button.Colors.GREEN}
ReviewDB website onClick={() => {
</Button> VencordNative.native.openExternal("https://github.com/sponsors/mantikafasi");
) }}
}, >
supportServer: { Support ReviewDB development
type: OptionType.COMPONENT, </Button>
description: "ReviewDB Support Server",
component: () => ( <Button onClick={async () => {
<Button onClick={() => { let url = "https://reviewdb.mantikafasi.dev/";
VencordNative.native.openExternal("https://discord.gg/eWPBSbvznt"); const token = await getToken();
}}> if (token)
ReviewDB Support Server url += "/api/redirect?token=" + encodeURIComponent(token);
</Button>
VencordNative.native.openExternal(url);
}}>
ReviewDB website
</Button>
<Button onClick={() => {
VencordNative.native.openExternal("https://discord.gg/eWPBSbvznt");
}}>
ReviewDB Support Server
</Button>
</div >
) )
} }
}).withPrivateSettings<{ }).withPrivateSettings<{

View file

@ -59,8 +59,14 @@
} }
.vc-rdb-review { .vc-rdb-review {
margin-top: 8px; padding-top: 8px !important;
margin-bottom: 8px; padding-bottom: 8px !important;
padding-right: 32px !important;
}
.vc-rdb-review:hover {
background: var(--background-message-hover) !important;
border-radius: 8px;
} }
.vc-rdb-review-comment img { .vc-rdb-review-comment img {
@ -91,6 +97,19 @@
gap: 0.75em; gap: 0.75em;
} }
.vc-rdb-button-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
/* stylelint-disable-next-line media-feature-range-notation */
@media (max-width: 600px) {
.vc-rdb-button-grid {
grid-template-columns: 1fr;
}
}
.vc-rdb-block-modal-row { .vc-rdb-block-modal-row {
display: flex; display: flex;
height: 2em; height: 2em;

View file

@ -17,7 +17,7 @@
*/ */
import { classNameFactory } from "@api/Styles"; import { classNameFactory } from "@api/Styles";
import { UserStore } from "@webpack/common"; import { Toasts, UserStore } from "@webpack/common";
import { Auth } from "./auth"; import { Auth } from "./auth";
import { Review, UserType } from "./entities"; import { Review, UserType } from "./entities";
@ -41,3 +41,14 @@ export function canBlockReviewAuthor(profileId: string, review: Review) {
export function canReportReview(review: Review) { export function canReportReview(review: Review) {
return review.sender.discordID !== UserStore.getCurrentUser().id; return review.sender.discordID !== UserStore.getCurrentUser().id;
} }
export function showToast(message: string, type = Toasts.Type.MESSAGE) {
Toasts.show({
id: Toasts.genId(),
message,
type,
options: {
position: Toasts.Position.BOTTOM, // NOBODY LIKES TOASTS AT THE TOP
},
});
}