fix(modnote): Fix initial implementation bugs

* Improve action criteria to FullCriteria function
  * Don't include undefined properties
  * Iterate entries with switch to simplify property transformations
* Fix mod action test switch case matching to be case-insensitive (same as key)
* Fix missing/bad assignments for filtering mod actions
* Fix typo usage of foundNoteResult in modActions case block
* Throw error if mod action criteria isn't recognized as note/log instead of silently falling back to log
This commit is contained in:
FoxxMD
2022-06-14 12:55:35 -04:00
parent 2ed24eee11
commit 22a8a694a7
2 changed files with 75 additions and 28 deletions

View File

@@ -141,19 +141,43 @@ export interface FullModNoteCriteria extends FullModActionCriteria, Omit<ModNote
note?: RegExp[]
}
const arrayableModNoteProps = ['activityType','noteType','note'];
export const asModNoteCriteria = (val: any): val is ModNoteCriteria => {
return val !== null && typeof val === 'object' && ('noteType' in val || 'note' in val);
}
export const toFullModNoteCriteria = (val: ModNoteCriteria): FullModNoteCriteria => {
return {
type: ['NOTE'],
count: val.count === undefined ? undefined : parseGenericValueComparison(val.count),
search: val.search,
activityType: val.activityType === undefined ? undefined : (Array.isArray(val.activityType) ? val.activityType : [val.activityType]),
noteType: val.noteType === undefined ? undefined : (Array.isArray(val.noteType) ? val.noteType : [val.noteType]),
note: val.note === undefined ? undefined : (Array.isArray(val.note) ? val.note.map(x => parseStringToRegexOrLiteralSearch(x)) : [parseStringToRegexOrLiteralSearch(val.note)]),
}
const result = Object.entries(val).reduce((acc: FullModNoteCriteria, curr) => {
const [k,v] = curr;
if(v === undefined) {
return acc;
}
const rawVal = arrayableModNoteProps.includes(k) && !Array.isArray(v) ? [v] : v;
switch(k) {
case 'search':
acc.search = rawVal;
break;
case 'count':
acc.count = parseGenericValueComparison(rawVal);
break;
case 'activityType':
case 'noteType':
acc[k] = rawVal;
break;
case 'note':
acc[k] = rawVal.map((x: string) => parseStringToRegexOrLiteralSearch(x))
}
return acc;
}, {});
result.type = ['NOTE'];
return result;
}
@@ -169,21 +193,42 @@ export interface FullModLogCriteria extends FullModActionCriteria, Omit<ModLogCr
description?: RegExp[]
}
const arrayableModLogProps = ['type','activityType','action','description','details', 'type'];
export const asModLogCriteria = (val: any): val is ModLogCriteria => {
return val !== null && typeof val === 'object' && ('action' in val || 'details' in val || 'description' in val || 'activityType' in val);
return val !== null && typeof val === 'object' && !asModNoteCriteria(val) && ('action' in val || 'details' in val || 'description' in val || 'activityType' in val || 'search' in val || 'count' in val || 'type' in val);
}
export const toFullModLogCriteria = (val: ModLogCriteria): FullModLogCriteria => {
return {
count: val.count === undefined ? undefined : parseGenericValueComparison(val.count),
search: val.search,
type: val.type === undefined ? undefined : (Array.isArray(val.type) ? val.type : [val.type]).map(x => x.toUpperCase()) as ModActionType[],
activityType: val.activityType === undefined ? undefined : (Array.isArray(val.activityType) ? val.activityType : [val.activityType]),
action: val.action === undefined ? undefined : (Array.isArray(val.action) ? val.action.map(x => parseStringToRegexOrLiteralSearch(x)) : [parseStringToRegexOrLiteralSearch(val.action)]),
description: val.description === undefined ? undefined : (Array.isArray(val.description) ? val.description.map(x => parseStringToRegexOrLiteralSearch(x)) : [parseStringToRegexOrLiteralSearch(val.description)]),
details: val.details === undefined ? undefined : (Array.isArray(val.details) ? val.details.map(x => parseStringToRegexOrLiteralSearch(x)) : [parseStringToRegexOrLiteralSearch(val.details)]),
}
return Object.entries(val).reduce((acc: FullModLogCriteria, curr) => {
const [k,v] = curr;
if(v === undefined) {
return acc;
}
const rawVal = arrayableModLogProps.includes(k) && !Array.isArray(v) ? [v] : v;
switch(k) {
case 'search':
acc.search = rawVal;
break;
case 'count':
acc.count = parseGenericValueComparison(rawVal);
break;
case 'activityType':
case 'type':
acc[k as keyof FullModLogCriteria] = rawVal;
break;
case 'action':
case 'description':
case 'details':
acc[k as keyof FullModLogCriteria] = rawVal.map((x: string) => parseStringToRegexOrLiteralSearch(x))
}
return acc;
}, {});
}
export const authorCriteriaProperties = ['name', 'flairCssClass', 'flairText', 'flairTemplate', 'isMod', 'userNotes', 'modActions', 'age', 'linkKarma', 'commentKarma', 'totalKarma', 'verified', 'shadowBanned', 'description', 'isContributor'];

View File

@@ -2874,7 +2874,7 @@ export class SubredditResources {
let actionsToUse: ModNote[] = [];
if(asModNoteCriteria(actionCriteria)) {
actionsToUse.filter(x => x.type === 'NOTE');
actionsToUse = actionsToUse.filter(x => x.type === 'NOTE');
} else {
actionsToUse = modActions;
}
@@ -2905,7 +2905,7 @@ export class SubredditResources {
return false
}
break;
case 'activityType':
case 'activitytype':
const anyMatch = v.some((a: ActivityType) => {
switch (a) {
case 'submission':
@@ -2941,10 +2941,10 @@ export class SubredditResources {
return true;
}); // filter end
} else {
} else if(asModNoteCriteria(actionCriteria)) {
const fullCrit = toFullModNoteCriteria(actionCriteria as ModNoteCriteria);
const fullCritEntries = Object.entries(fullCrit);
validActions = modActions.filter(x => {
validActions = actionsToUse.filter(x => {
// filter out any notes that occur before time range
if(cutoffDate !== undefined && x.createdAt.isBefore(cutoffDate)) {
@@ -2957,7 +2957,7 @@ export class SubredditResources {
continue;
}
switch (key) {
case 'noteType':
case 'notetype':
if (!v.map((x: ModUserNoteLabel) => x.toUpperCase()).includes((x.note.label as ModUserNoteLabel))) {
return false
}
@@ -2972,7 +2972,7 @@ export class SubredditResources {
return false;
}
break;
case 'activityType':
case 'activitytype':
const anyMatch = v.some((a: ActivityType) => {
switch (a) {
case 'submission':
@@ -2997,11 +2997,13 @@ export class SubredditResources {
return true;
}); // filter end
} else {
throw new SimpleError(`Could not determine if a modActions criteria was for Mod Log or Mod Note. Given: ${JSON.stringify(actionCriteria)}`);
}
switch (search) {
case 'current':
if (modActions.length === 0) {
if (validActions.length === 0) {
actionResult.push('No Mod Actions present');
} else {
actionResult.push('Current Action matches criteria');
@@ -3038,12 +3040,12 @@ export class SubredditResources {
if (isPercent) {
// avoid divide by zero
const percent = notes.length === 0 ? 0 : validActions.length / actionsToUse.length;
foundNoteResult.push(`${formatNumber(percent)}% of ${actionsToUse.length} matched criteria`);
actionResult.push(`${formatNumber(percent)}% of ${actionsToUse.length} matched criteria`);
if (comparisonTextOp(percent, operator, value / 100)) {
return true;
}
} else {
foundNoteResult.push(`${validActions.length} matched criteria`);
actionResult.push(`${validActions.length} matched criteria`);
if (comparisonTextOp(validActions.length, operator, value)) {
return true;
}