Require permission for filler submissions

This commit is contained in:
Ajay
2022-07-28 12:22:49 -04:00
parent 954c3db649
commit 46805f4830
8 changed files with 54 additions and 16 deletions

View File

@@ -44,6 +44,7 @@ addDefaults(config, {
discordReportChannelWebhookURL: null,
discordMaliciousReportWebhookURL: null,
minReputationToSubmitChapter: 0,
minReputationToSubmitFiller: 0,
getTopUsersCacheTimeMinutes: 240,
globalSalt: null,
mode: "",

View File

@@ -18,10 +18,12 @@ interface AddFeatureRequest extends Request {
const allowedFeatures = {
vip: [
Feature.ChapterSubmitter
Feature.ChapterSubmitter,
Feature.FillerSubmitter
],
admin: [
Feature.ChapterSubmitter
Feature.ChapterSubmitter,
Feature.FillerSubmitter
]
}

View File

@@ -5,9 +5,9 @@ import { Request, Response } from "express";
import { Logger } from "../utils/logger";
import { HashedUserID, UserID } from "../types/user.model";
import { getReputation } from "../utils/reputation";
import { SegmentUUID } from "../types/segments.model";
import { Category, SegmentUUID } from "../types/segments.model";
import { config } from "../config";
import { canSubmitChapter } from "../utils/permissions";
import { canSubmit } from "../utils/permissions";
const maxRewardTime = config.maxRewardTimePerSegmentInSeconds;
async function dbGetSubmittedSegmentSummary(userID: HashedUserID): Promise<{ minutesSaved: number, segmentCount: number }> {
@@ -106,6 +106,15 @@ async function dbGetBanned(userID: HashedUserID): Promise<boolean> {
}
}
async function getPermissions(userID: HashedUserID): Promise<Record<string, boolean>> {
const result: Record<string, boolean> = {};
for (const category of config.categoryList) {
result[category] = (await canSubmit(userID, category as Category)).canSubmit;
}
return result;
}
type cases = Record<string, any>
const executeIfFunction = (f: any) =>
@@ -130,7 +139,7 @@ const dbGetValue = (userID: HashedUserID, property: string): Promise<string|Segm
reputation: () => getReputation(userID),
vip: () => isUserVIP(userID),
lastSegmentID: () => dbGetLastSegmentForUser(userID),
canSubmitChapter: () => canSubmitChapter(userID)
permissions: () => getPermissions(userID)
})("")(property);
};
@@ -140,7 +149,7 @@ async function getUserInfo(req: Request, res: Response): Promise<Response> {
const defaultProperties: string[] = ["userID", "userName", "minutesSaved", "segmentCount", "ignoredSegmentCount",
"viewCount", "ignoredViewCount", "warnings", "warningReason", "reputation",
"vip", "lastSegmentID"];
const allProperties: string[] = [...defaultProperties, "banned", "canSubmitChapter"];
const allProperties: string[] = [...defaultProperties, "banned", "permissions"];
let paramValues: string[] = req.query.values
? JSON.parse(req.query.values as string)
: req.query.value

View File

@@ -21,7 +21,7 @@ import { parseUserAgent } from "../utils/userAgent";
import { getService } from "../utils/getService";
import axios from "axios";
import { vote } from "./voteOnSponsorTime";
import { canSubmitChapter } from "../utils/permissions";
import { canSubmit } from "../utils/permissions";
type CheckResult = {
pass: boolean,
@@ -230,8 +230,10 @@ async function checkInvalidFields(videoID: VideoID, userID: UserID, hashedUserID
invalidFields.push("segment description");
}
if (segmentPair.actionType === ActionType.Chapter && !(await canSubmitChapter(hashedUserID))) {
invalidFields.push("permission to submit chapters");
const permission = await canSubmit(hashedUserID, segmentPair.category);
if (!permission.canSubmit) {
invalidFields.push(`permission to submit ${segmentPair.category}`);
errors.push(permission.reason);
}
}
@@ -241,7 +243,7 @@ async function checkInvalidFields(videoID: VideoID, userID: UserID, hashedUserID
const formattedErrors = errors.reduce((p, c, i) => p + (i !== 0 ? ". " : " ") + c, "");
return {
pass: false,
errorMessage: `No valid ${formattedFields} field(s) provided.${formattedErrors}`,
errorMessage: `No valid ${formattedFields}.${formattedErrors}`,
errorCode: 400
};
}

View File

@@ -28,6 +28,7 @@ export interface SBSConfig {
neuralBlockURL?: string;
discordNeuralBlockRejectWebhookURL?: string;
minReputationToSubmitChapter: number;
minReputationToSubmitFiller: number;
userCounterURL?: string;
proxySubmission?: string;
behindProxy: string | boolean;

View File

@@ -5,7 +5,7 @@ import { HashedUserID, UserID } from "./user.model";
export type SegmentUUID = string & { __segmentUUIDBrand: unknown };
export type VideoID = string & { __videoIDBrand: unknown };
export type VideoDuration = number & { __videoDurationBrand: unknown };
export type Category = ("sponsor" | "selfpromo" | "interaction" | "intro" | "outro" | "preview" | "music_offtopic" | "poi_highlight" | "chapter") & { __categoryBrand: unknown };
export type Category = ("sponsor" | "selfpromo" | "interaction" | "intro" | "outro" | "preview" | "music_offtopic" | "filler" | "poi_highlight" | "chapter") & { __categoryBrand: unknown };
export type VideoIDHash = VideoID & HashedValue;
export type IPAddress = string & { __ipAddressBrand: unknown };
export type HashedIP = IPAddress & HashedValue;

View File

@@ -4,5 +4,6 @@ export type UserID = string & { __userIDBrand: unknown };
export type HashedUserID = UserID & HashedValue;
export enum Feature {
ChapterSubmitter = 0
ChapterSubmitter = 0,
FillerSubmitter = 1
}

View File

@@ -1,11 +1,33 @@
import { config } from "../config";
import { Category } from "../types/segments.model";
import { Feature, HashedUserID } from "../types/user.model";
import { hasFeature } from "./features";
import { isUserVIP } from "./isUserVIP";
import { getReputation } from "./reputation";
export async function canSubmitChapter(userID: HashedUserID): Promise<boolean> {
return (await isUserVIP(userID))
|| (await getReputation(userID)) > config.minReputationToSubmitChapter
|| (await hasFeature(userID, Feature.ChapterSubmitter));
interface CanSubmitResult {
canSubmit: boolean;
reason?: string;
}
export async function canSubmit(userID: HashedUserID, category: Category): Promise<CanSubmitResult> {
switch (category) {
case "chapter":
return {
canSubmit: (await isUserVIP(userID))
|| (await getReputation(userID)) > config.minReputationToSubmitChapter
|| (await hasFeature(userID, Feature.ChapterSubmitter))
};
case "filler":
return {
canSubmit: (await isUserVIP(userID))
|| (await getReputation(userID)) > config.minReputationToSubmitFiller
|| (await hasFeature(userID, Feature.FillerSubmitter)),
reason: "Someone is submitting over 180,000 spam filler submissions and refuses to stop even after talking with them, so we have to restrict it for now. You can request submission access on chat.sponsor.ajay.app, discord.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app"
};
}
return {
canSubmit: true
};
}