Merge branch 'main' into coolbot/moderation-improvements
This commit is contained in:
commit
473fe52865
@ -8,7 +8,7 @@
|
|||||||
<div v-if="!modPackData">Loading data...</div>
|
<div v-if="!modPackData">Loading data...</div>
|
||||||
|
|
||||||
<div v-else-if="modPackData.length === 0">
|
<div v-else-if="modPackData.length === 0">
|
||||||
<p>All permissions obtained. You may skip this step!</p>
|
<p>All permissions already obtained.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!modPackData[currentIndex]">
|
<div v-else-if="!modPackData[currentIndex]">
|
||||||
@ -157,7 +157,7 @@ import type {
|
|||||||
} from "@modrinth/utils";
|
} from "@modrinth/utils";
|
||||||
import { ButtonStyled } from "@modrinth/ui";
|
import { ButtonStyled } from "@modrinth/ui";
|
||||||
import { ref, computed, watch, onMounted } from "vue";
|
import { ref, computed, watch, onMounted } from "vue";
|
||||||
import { useLocalStorage } from "@vueuse/core";
|
import { useLocalStorage, useSessionStorage } from "@vueuse/core";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -182,7 +182,26 @@ const persistedModPackData = useLocalStorage<ModerationModpackItem[] | null>(
|
|||||||
|
|
||||||
const persistedIndex = useLocalStorage<number>(`modpack-permissions-index-${props.projectId}`, 0);
|
const persistedIndex = useLocalStorage<number>(`modpack-permissions-index-${props.projectId}`, 0);
|
||||||
|
|
||||||
const modPackData = ref<ModerationModpackItem[] | null>(null);
|
const modPackData = useSessionStorage<ModerationModpackItem[] | null>(
|
||||||
|
`modpack-permissions-data-${props.projectId}`,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
serializer: {
|
||||||
|
read: (v: any) => (v ? JSON.parse(v) : null),
|
||||||
|
write: (v: any) => JSON.stringify(v),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const permanentNoFiles = useSessionStorage<ModerationModpackItem[]>(
|
||||||
|
`modpack-permissions-permanent-no-${props.projectId}`,
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
serializer: {
|
||||||
|
read: (v: any) => (v ? JSON.parse(v) : []),
|
||||||
|
write: (v: any) => JSON.stringify(v),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
const currentIndex = ref(0);
|
const currentIndex = ref(0);
|
||||||
|
|
||||||
const fileApprovalTypes: ModerationModpackPermissionApprovalType[] = [
|
const fileApprovalTypes: ModerationModpackPermissionApprovalType[] = [
|
||||||
@ -251,7 +270,45 @@ async function fetchModPackData(): Promise<void> {
|
|||||||
const data = (await useBaseFetch(`moderation/project/${props.projectId}`, {
|
const data = (await useBaseFetch(`moderation/project/${props.projectId}`, {
|
||||||
internal: true,
|
internal: true,
|
||||||
})) as ModerationModpackResponse;
|
})) as ModerationModpackResponse;
|
||||||
|
|
||||||
|
const permanentNoItems: ModerationModpackItem[] = Object.entries(data.identified || {})
|
||||||
|
.filter(([_, file]) => file.status === "permanent-no")
|
||||||
|
.map(
|
||||||
|
([sha1, file]): ModerationModpackItem => ({
|
||||||
|
sha1,
|
||||||
|
file_name: file.file_name,
|
||||||
|
type: "identified",
|
||||||
|
status: file.status,
|
||||||
|
approved: null,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.sort((a, b) => a.file_name.localeCompare(b.file_name));
|
||||||
|
|
||||||
|
permanentNoFiles.value = permanentNoItems;
|
||||||
|
|
||||||
const sortedData: ModerationModpackItem[] = [
|
const sortedData: ModerationModpackItem[] = [
|
||||||
|
...Object.entries(data.identified || {})
|
||||||
|
.filter(
|
||||||
|
([_, file]) =>
|
||||||
|
file.status !== "yes" &&
|
||||||
|
file.status !== "with-attribution-and-source" &&
|
||||||
|
file.status !== "permanent-no",
|
||||||
|
)
|
||||||
|
.map(
|
||||||
|
([sha1, file]): ModerationModpackItem => ({
|
||||||
|
sha1,
|
||||||
|
file_name: file.file_name,
|
||||||
|
type: "identified",
|
||||||
|
status: file.status,
|
||||||
|
approved: null,
|
||||||
|
...(file.status === "unidentified" && {
|
||||||
|
proof: "",
|
||||||
|
url: "",
|
||||||
|
title: "",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.sort((a, b) => a.file_name.localeCompare(b.file_name)),
|
||||||
...Object.entries(data.unknown_files || {})
|
...Object.entries(data.unknown_files || {})
|
||||||
.map(
|
.map(
|
||||||
([sha1, fileName]): ModerationUnknownModpackItem => ({
|
([sha1, fileName]): ModerationUnknownModpackItem => ({
|
||||||
@ -310,6 +367,7 @@ async function fetchModPackData(): Promise<void> {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch modpack data:", error);
|
console.error("Failed to fetch modpack data:", error);
|
||||||
modPackData.value = [];
|
modPackData.value = [];
|
||||||
|
permanentNoFiles.value = [];
|
||||||
persistAll();
|
persistAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,6 +379,14 @@ function goToPrevious(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
modPackData,
|
||||||
|
(newValue) => {
|
||||||
|
persistedModPackData.value = newValue;
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
function goToNext(): void {
|
function goToNext(): void {
|
||||||
if (modPackData.value && currentIndex.value < modPackData.value.length) {
|
if (modPackData.value && currentIndex.value < modPackData.value.length) {
|
||||||
currentIndex.value++;
|
currentIndex.value++;
|
||||||
@ -396,6 +462,17 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
modPackData,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue && newValue.length === 0) {
|
||||||
|
emit("complete");
|
||||||
|
clearPersistedData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.projectId,
|
() => props.projectId,
|
||||||
() => {
|
() => {
|
||||||
@ -406,6 +483,20 @@ watch(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function getModpackFiles(): {
|
||||||
|
interactive: ModerationModpackItem[];
|
||||||
|
permanentNo: ModerationModpackItem[];
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
interactive: modPackData.value || [],
|
||||||
|
permanentNo: permanentNoFiles.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getModpackFiles,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@ -240,24 +240,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="generatedMessage" class="flex items-center gap-2">
|
<div v-else-if="generatedMessage" class="flex items-center gap-2">
|
||||||
<OverflowMenu :options="stageOptions" class="bg-transparent p-0">
|
|
||||||
<ButtonStyled circular>
|
|
||||||
<button v-tooltip="`Stages`">
|
|
||||||
<ListBulletedIcon />
|
|
||||||
</button>
|
|
||||||
</ButtonStyled>
|
|
||||||
|
|
||||||
<template
|
|
||||||
v-for="opt in stageOptions.filter(
|
|
||||||
(opt) => 'id' in opt && 'text' in opt && 'icon' in opt,
|
|
||||||
)"
|
|
||||||
#[opt.id]
|
|
||||||
:key="opt.id"
|
|
||||||
>
|
|
||||||
<component :is="opt.icon" v-if="opt.icon" class="mr-2" />
|
|
||||||
{{ opt.text }}
|
|
||||||
</template>
|
|
||||||
</OverflowMenu>
|
|
||||||
<ButtonStyled>
|
<ButtonStyled>
|
||||||
<button @click="goBackToStages">
|
<button @click="goBackToStages">
|
||||||
<LeftArrowIcon aria-hidden="true" />
|
<LeftArrowIcon aria-hidden="true" />
|
||||||
@ -368,21 +350,26 @@ import {
|
|||||||
DropdownSelect,
|
DropdownSelect,
|
||||||
MarkdownEditor,
|
MarkdownEditor,
|
||||||
} from "@modrinth/ui";
|
} from "@modrinth/ui";
|
||||||
import { type Project, renderHighlightedString, type ModerationJudgements } from "@modrinth/utils";
|
import {
|
||||||
|
type Project,
|
||||||
|
renderHighlightedString,
|
||||||
|
type ModerationJudgements,
|
||||||
|
type ModerationModpackItem,
|
||||||
|
} from "@modrinth/utils";
|
||||||
import { computedAsync, useLocalStorage } from "@vueuse/core";
|
import { computedAsync, useLocalStorage } from "@vueuse/core";
|
||||||
import type {
|
import {
|
||||||
Action,
|
type Action,
|
||||||
MultiSelectChipsAction,
|
type MultiSelectChipsAction,
|
||||||
DropdownAction,
|
type DropdownAction,
|
||||||
ButtonAction,
|
type ButtonAction,
|
||||||
ToggleAction,
|
type ToggleAction,
|
||||||
ConditionalButtonAction,
|
type ConditionalButtonAction,
|
||||||
Stage,
|
type Stage,
|
||||||
|
finalPermissionMessages,
|
||||||
} from "@modrinth/moderation";
|
} from "@modrinth/moderation";
|
||||||
|
import * as prettier from "prettier";
|
||||||
import ModpackPermissionsFlow from "./ModpackPermissionsFlow.vue";
|
import ModpackPermissionsFlow from "./ModpackPermissionsFlow.vue";
|
||||||
import KeybindsModal from "./ChecklistKeybindsModal.vue";
|
import KeybindsModal from "./ChecklistKeybindsModal.vue";
|
||||||
import { finalPermissionMessages } from "@modrinth/moderation/data/modpack-permissions-stage";
|
|
||||||
import prettier from "prettier";
|
|
||||||
|
|
||||||
const keybindsModal = ref<InstanceType<typeof KeybindsModal>>();
|
const keybindsModal = ref<InstanceType<typeof KeybindsModal>>();
|
||||||
|
|
||||||
@ -419,7 +406,6 @@ const done = ref(false);
|
|||||||
|
|
||||||
function handleModpackPermissionsComplete() {
|
function handleModpackPermissionsComplete() {
|
||||||
modpackPermissionsComplete.value = true;
|
modpackPermissionsComplete.value = true;
|
||||||
nextStage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@ -823,6 +809,31 @@ const isAnyVisibleInputs = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getModpackFilesFromStorage(): {
|
||||||
|
interactive: ModerationModpackItem[];
|
||||||
|
permanentNo: ModerationModpackItem[];
|
||||||
|
} {
|
||||||
|
try {
|
||||||
|
const sessionData = sessionStorage.getItem(`modpack-permissions-data-${props.project.id}`);
|
||||||
|
const interactive = sessionData ? (JSON.parse(sessionData) as ModerationModpackItem[]) : [];
|
||||||
|
|
||||||
|
const permanentNoData = sessionStorage.getItem(
|
||||||
|
`modpack-permissions-permanent-no-${props.project.id}`,
|
||||||
|
);
|
||||||
|
const permanentNo = permanentNoData
|
||||||
|
? (JSON.parse(permanentNoData) as ModerationModpackItem[])
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
interactive: interactive || [],
|
||||||
|
permanentNo: permanentNo || [],
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to parse session storage modpack data:", error);
|
||||||
|
return { interactive: [], permanentNo: [] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function assembleFullMessage() {
|
async function assembleFullMessage() {
|
||||||
const messageParts: MessagePart[] = [];
|
const messageParts: MessagePart[] = [];
|
||||||
|
|
||||||
@ -1092,13 +1103,14 @@ async function generateMessage() {
|
|||||||
const baseMessage = await assembleFullMessage();
|
const baseMessage = await assembleFullMessage();
|
||||||
let fullMessage = baseMessage;
|
let fullMessage = baseMessage;
|
||||||
|
|
||||||
if (
|
if (props.project.project_type === "modpack") {
|
||||||
props.project.project_type === "modpack" &&
|
const modpackFilesData = getModpackFilesFromStorage();
|
||||||
Object.keys(modpackJudgements.value).length > 0
|
|
||||||
) {
|
if (modpackFilesData.interactive.length > 0 || modpackFilesData.permanentNo.length > 0) {
|
||||||
const modpackMessage = generateModpackMessage(modpackJudgements.value);
|
const modpackMessage = generateModpackMessage(modpackFilesData);
|
||||||
if (modpackMessage) {
|
if (modpackMessage) {
|
||||||
fullMessage = baseMessage ? `${baseMessage}\n\n${modpackMessage}` : modpackMessage;
|
fullMessage = baseMessage ? `${baseMessage}\n\n${modpackMessage}` : modpackMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1129,25 +1141,32 @@ async function generateMessage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateModpackMessage(judgements: ModerationJudgements) {
|
function generateModpackMessage(allFiles: {
|
||||||
|
interactive: ModerationModpackItem[];
|
||||||
|
permanentNo: ModerationModpackItem[];
|
||||||
|
}) {
|
||||||
const issues = [];
|
const issues = [];
|
||||||
|
|
||||||
const attributeMods = [];
|
const attributeMods: string[] = [];
|
||||||
const noMods = [];
|
const noMods: string[] = [];
|
||||||
const permanentNoMods = [];
|
const permanentNoMods: string[] = [];
|
||||||
const unidentifiedMods = [];
|
const unidentifiedMods: string[] = [];
|
||||||
|
|
||||||
for (const [, judgement] of Object.entries(judgements)) {
|
allFiles.interactive.forEach((file) => {
|
||||||
if (judgement.status === "with-attribution") {
|
if (file.status === "unidentified") {
|
||||||
attributeMods.push(judgement.file_name);
|
if (file.approved === "no") {
|
||||||
} else if (judgement.status === "no") {
|
unidentifiedMods.push(file.file_name);
|
||||||
noMods.push(judgement.file_name);
|
}
|
||||||
} else if (judgement.status === "permanent-no") {
|
} else if (file.status === "with-attribution" && file.approved === "no") {
|
||||||
permanentNoMods.push(judgement.file_name);
|
attributeMods.push(file.file_name);
|
||||||
} else if (judgement.status === "unidentified") {
|
} else if (file.status === "no" && file.approved === "no") {
|
||||||
unidentifiedMods.push(judgement.file_name);
|
noMods.push(file.file_name);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
allFiles.permanentNo.forEach((file) => {
|
||||||
|
permanentNoMods.push(file.file_name);
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
attributeMods.length > 0 ||
|
attributeMods.length > 0 ||
|
||||||
@ -1157,6 +1176,12 @@ function generateModpackMessage(judgements: ModerationJudgements) {
|
|||||||
) {
|
) {
|
||||||
issues.push("## Copyrighted content");
|
issues.push("## Copyrighted content");
|
||||||
|
|
||||||
|
if (unidentifiedMods.length > 0) {
|
||||||
|
issues.push(
|
||||||
|
`${finalPermissionMessages.unidentified}\n${unidentifiedMods.map((mod) => `- ${mod}`).join("\n")}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (attributeMods.length > 0) {
|
if (attributeMods.length > 0) {
|
||||||
issues.push(
|
issues.push(
|
||||||
`${finalPermissionMessages["with-attribution"]}\n${attributeMods.map((mod) => `- ${mod}`).join("\n")}`,
|
`${finalPermissionMessages["with-attribution"]}\n${attributeMods.map((mod) => `- ${mod}`).join("\n")}`,
|
||||||
@ -1172,12 +1197,6 @@ function generateModpackMessage(judgements: ModerationJudgements) {
|
|||||||
`${finalPermissionMessages["permanent-no"]}\n${permanentNoMods.map((mod) => `- ${mod}`).join("\n")}`,
|
`${finalPermissionMessages["permanent-no"]}\n${permanentNoMods.map((mod) => `- ${mod}`).join("\n")}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unidentifiedMods.length > 0) {
|
|
||||||
issues.push(
|
|
||||||
`${finalPermissionMessages["unidentified"]}\n${unidentifiedMods.map((mod) => `- ${mod}`).join("\n")}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return issues.join("\n\n");
|
return issues.join("\n\n");
|
||||||
|
|||||||
@ -1,13 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<template v-if="moderation">
|
||||||
|
<Chips v-model="reasonFilter" :items="reasons" />
|
||||||
|
<p v-if="reports.length === MAX_REPORTS" class="text-red">
|
||||||
|
There are at least {{ MAX_REPORTS }} open reports. This page is at its max reports and will
|
||||||
|
not show any more recent ones.
|
||||||
|
</p>
|
||||||
|
<p v-else-if="reasonFilter === 'All'">There are {{ filteredReports.length }} open reports.</p>
|
||||||
|
<p v-else>
|
||||||
|
There are {{ filteredReports.length }}/{{ reports.length }} open '{{ reasonFilter }}' reports.
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
<ReportInfo
|
<ReportInfo
|
||||||
v-for="report in reports.filter(
|
v-for="report in filteredReports"
|
||||||
(x) =>
|
|
||||||
(moderation || x.reporterUser.id === auth.user.id) &&
|
|
||||||
(viewMode === 'open' ? x.open : !x.open),
|
|
||||||
)"
|
|
||||||
:key="report.id"
|
:key="report.id"
|
||||||
:report="report"
|
:report="report"
|
||||||
:thread="report.thread"
|
:thread="report.thread"
|
||||||
|
:show-message="false"
|
||||||
:moderation="moderation"
|
:moderation="moderation"
|
||||||
raised
|
raised
|
||||||
:auth="auth"
|
:auth="auth"
|
||||||
@ -16,11 +24,12 @@
|
|||||||
<p v-if="reports.length === 0">You don't have any active reports.</p>
|
<p v-if="reports.length === 0">You don't have any active reports.</p>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { Chips } from "@modrinth/ui";
|
||||||
import ReportInfo from "~/components/ui/report/ReportInfo.vue";
|
import ReportInfo from "~/components/ui/report/ReportInfo.vue";
|
||||||
import { addReportMessage } from "~/helpers/threads.js";
|
import { addReportMessage } from "~/helpers/threads.js";
|
||||||
import { asEncodedJsonArray, fetchSegmented } from "~/utils/fetch-helpers.ts";
|
import { asEncodedJsonArray, fetchSegmented } from "~/utils/fetch-helpers.ts";
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
moderation: {
|
moderation: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@ -32,9 +41,14 @@ defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const viewMode = ref("open");
|
const viewMode = ref("open");
|
||||||
|
const reasonFilter = ref("All");
|
||||||
const reports = ref([]);
|
const reports = ref([]);
|
||||||
|
|
||||||
let { data: rawReports } = await useAsyncData("report", () => useBaseFetch("report?count=1000"));
|
const MAX_REPORTS = 1500;
|
||||||
|
|
||||||
|
let { data: rawReports } = await useAsyncData("report", () =>
|
||||||
|
useBaseFetch(`report?count=${MAX_REPORTS}`),
|
||||||
|
);
|
||||||
|
|
||||||
rawReports = rawReports.value.map((report) => {
|
rawReports = rawReports.value.map((report) => {
|
||||||
report.item_id = report.item_id.replace(/"/g, "");
|
report.item_id = report.item_id.replace(/"/g, "");
|
||||||
@ -51,6 +65,7 @@ const userIds = [...new Set(reporterUsers.concat(reportedUsers))];
|
|||||||
const threadIds = [
|
const threadIds = [
|
||||||
...new Set(rawReports.filter((report) => report.thread_id).map((report) => report.thread_id)),
|
...new Set(rawReports.filter((report) => report.thread_id).map((report) => report.thread_id)),
|
||||||
];
|
];
|
||||||
|
const reasons = ["All", ...new Set(rawReports.map((report) => report.report_type))];
|
||||||
|
|
||||||
const [{ data: users }, { data: versions }, { data: threads }] = await Promise.all([
|
const [{ data: users }, { data: versions }, { data: threads }] = await Promise.all([
|
||||||
await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
|
await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
|
||||||
@ -93,4 +108,13 @@ reports.value = rawReports.map((report) => {
|
|||||||
report.open = true;
|
report.open = true;
|
||||||
return report;
|
return report;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filteredReports = computed(() =>
|
||||||
|
reports.value?.filter(
|
||||||
|
(x) =>
|
||||||
|
(props.moderation || x.reporterUser.id === props.auth.user.id) &&
|
||||||
|
(viewMode.value === "open" ? x.open : !x.open) &&
|
||||||
|
(reasonFilter.value === "All" || reasonFilter.value === x.report_type),
|
||||||
|
),
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,6 +3,7 @@ export * from './types/messages'
|
|||||||
export * from './types/stage'
|
export * from './types/stage'
|
||||||
export * from './types/keybinds'
|
export * from './types/keybinds'
|
||||||
export * from './utils'
|
export * from './utils'
|
||||||
|
export { finalPermissionMessages } from './data/modpack-permissions-stage'
|
||||||
|
|
||||||
export { default as checklist } from './data/checklist'
|
export { default as checklist } from './data/checklist'
|
||||||
export { default as keybinds } from './data/keybinds'
|
export { default as keybinds } from './data/keybinds'
|
||||||
|
|||||||
@ -315,7 +315,7 @@ export interface ModerationPermissionType {
|
|||||||
export interface ModerationBaseModpackItem {
|
export interface ModerationBaseModpackItem {
|
||||||
sha1: string
|
sha1: string
|
||||||
file_name: string
|
file_name: string
|
||||||
type: 'unknown' | 'flame'
|
type: 'unknown' | 'flame' | 'identified'
|
||||||
status: ModerationModpackPermissionApprovalType['id'] | null
|
status: ModerationModpackPermissionApprovalType['id'] | null
|
||||||
approved: ModerationPermissionType['id'] | null
|
approved: ModerationPermissionType['id'] | null
|
||||||
}
|
}
|
||||||
@ -334,9 +334,26 @@ export interface ModerationFlameModpackItem extends ModerationBaseModpackItem {
|
|||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ModerationModpackItem = ModerationUnknownModpackItem | ModerationFlameModpackItem
|
export interface ModerationIdentifiedModpackItem extends ModerationBaseModpackItem {
|
||||||
|
type: 'identified'
|
||||||
|
proof?: string
|
||||||
|
url?: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ModerationModpackItem =
|
||||||
|
| ModerationUnknownModpackItem
|
||||||
|
| ModerationFlameModpackItem
|
||||||
|
| ModerationIdentifiedModpackItem
|
||||||
|
|
||||||
export interface ModerationModpackResponse {
|
export interface ModerationModpackResponse {
|
||||||
|
identified?: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
file_name: string
|
||||||
|
status: ModerationModpackPermissionApprovalType['id']
|
||||||
|
}
|
||||||
|
>
|
||||||
unknown_files?: Record<string, string>
|
unknown_files?: Record<string, string>
|
||||||
flame_files?: Record<
|
flame_files?: Record<
|
||||||
string,
|
string,
|
||||||
@ -350,8 +367,8 @@ export interface ModerationModpackResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ModerationJudgement {
|
export interface ModerationJudgement {
|
||||||
type: 'flame' | 'unknown'
|
type: 'flame' | 'unknown' | 'identified'
|
||||||
status: string
|
status: string | null
|
||||||
id?: string
|
id?: string
|
||||||
link?: string
|
link?: string
|
||||||
title?: string
|
title?: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user