Skip to content

Commit

Permalink
PostOther is no more!
Browse files Browse the repository at this point in the history
  • Loading branch information
double-beep authored Aug 13, 2023
1 parent d5a90b3 commit cce8b26
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 32 deletions.
21 changes: 16 additions & 5 deletions src/AdvancedFlagging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,18 +174,28 @@ async function flagPost(
flagName: Flags,
flagged: HTMLElement,
flagText: string | null,
targetUrl?: string,
): Promise<void> {
const failedToFlag = 'Failed to flag: ';

const url = `/flags/posts/${postId}/add/${flagName}`;
const data = { fkey, otherText: flagText || '' };
const data = {
fkey,
otherText: flagText || '',
// plagiarism flag: fill "Link(s) to original content"
// note wrt link: site will always be Stack Overflow,
// post will always be an answer.
customData: flagName === FlagNames.Plagiarism
? JSON.stringify({ plagiarizedSource: `https:${targetUrl}` })
: ''
};

if (debugMode) {
console.log(`Flag post as ${flagName} via`, url, data);
return;
}

const flagPost = await fetch(url, {
const flagRequest = await fetch(url, {
method: 'POST',
body: getFormDataFromObject(data)
});
Expand All @@ -195,7 +205,7 @@ async function flagPost(
// for example, if a user flags posts too quickly, they get a text response
// if the post has been flagged successfully, the response is in JSON
const tooFast = /You may only flag a post every \d+ seconds?/;
const responseText = await flagPost.text();
const responseText = await flagRequest.text();

if (tooFast.test(responseText)) { // flagging posts too quickly
const rlCount = /\d+/.exec(responseText)?.[0] || 0;
Expand Down Expand Up @@ -226,6 +236,7 @@ export async function handleActions(
downvoteRequired: boolean,
flagText: string | null,
commentText?: string | null,
targetUrl?: string,
): Promise<void> {
// needed to add the comment and raise the flag
const fkey = StackExchange.options.user.fkey;
Expand All @@ -239,15 +250,15 @@ export async function handleActions(
}
}

if (flagRequired && reportType !== 'NoFlag') {
if (flagRequired && reportType !== FlagNames.NoFlag) {
autoFlagging = true;

// if the flag name is VLQ, then we need to check if the criteria are met.
// If not, switch to NAA
const flagName = getFlagToRaise(reportType, raiseVlq);

try {
await flagPost(postId, fkey, flagName, flagged, flagText);
await flagPost(postId, fkey, flagName, flagged, flagText, targetUrl);
} catch (error) {
displayErrorFlagged('Failed to flag post', error as string);
}
Expand Down
17 changes: 13 additions & 4 deletions src/Configuration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { flagCategories } from './FlagTypes';
import { Store } from './UserscriptTools/Store';
import { CachedFlag } from './shared';
import { CachedFlag, updateFlagTypes } from './shared';
import { Flags } from './FlagTypes';

import {
Expand All @@ -16,11 +16,11 @@ import {
import { buildConfigurationOverlay } from './modals/config';
import { setupCommentsAndFlagsModal } from './modals/comments/main';

export function isModOrNoFlag(flagName: Flags): boolean {
export function isPlagiarismOrNoFlag(flagName: Flags): boolean {
const result =
[
FlagNames.NoFlag,
FlagNames.ModFlag
FlagNames.Plagiarism
]
.some(reportType => reportType === flagName);

Expand All @@ -40,7 +40,7 @@ export function cacheFlags(): void {
return category.FlagTypes.map(flagType => {
return Object.assign(flagType, {
belongsTo: category.name,
downvote: !isModOrNoFlag(flagType.reportType),
downvote: !isPlagiarismOrNoFlag(flagType.reportType),
enabled: true // all flags should be enabled by default
});
});
Expand Down Expand Up @@ -82,6 +82,15 @@ function setupDefaults(): void {
|| !('appliesTo' in cachedCategories[0])) {
cacheCategories();
}

// PostOther is no more!
// Replace with PlagiarizedContent.
cachedFlagTypes.forEach(cachedFlag => {
if (cachedFlag.reportType as Flags | 'PostOther' !== 'PostOther') return;

cachedFlag.reportType = FlagNames.Plagiarism;
});
updateFlagTypes();
}

export function setupConfiguration(): void {
Expand Down
21 changes: 13 additions & 8 deletions src/FlagTypes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { FlagTypeFeedbacks, PostType, FlagNames } from './shared';

export type Flags = 'AnswerNotAnAnswer' | 'PostOffensive' | 'PostSpam' | 'NoFlag' | 'PostOther' | 'PostLowQuality';
export type HumanFlags = 'as NAA' | 'as R/A' | 'as spam' | 'for moderator attention' | 'as VLQ' | '';
export type Flags = 'AnswerNotAnAnswer'
| 'PostOffensive'
| 'PostSpam'
| 'NoFlag'
//| 'PostOther'
| 'PostLowQuality'
| 'PlagiarizedContent';

const deletedAnswers = '/help/deleted-answers';
const commentHelp = '/help/privileges/comment';
Expand Down Expand Up @@ -61,17 +66,17 @@ export const flagCategories: FlagCategory[] = [
{
id: 3,
displayName: 'Plagiarism',
reportType: FlagNames.ModFlag,
flagText: 'Possible plagiarism of another answer $TARGET$, as can be seen here $COPYPASTOR$',
reportType: FlagNames.Plagiarism,
flagText: 'Possible plagiarism of the linked answer, as can be seen here $COPYPASTOR$',
// don't send feedback to Smokey despite https://charcoal-se.org/smokey/Feedback-Guidance.html#plagiarism
feedbacks: { Smokey: '', Natty: '', Guttenberg: 'tp', 'Generic Bot': '' },
sendWhenFlagRaised: false
},
{
id: 4,
displayName: 'Duplicate answer',
reportType: FlagNames.ModFlag,
flagText: 'The answer is a repost of their other answer $TARGET$, but as there are slight differences '
reportType: FlagNames.Plagiarism,
flagText: 'The post is a repost of their other answer, but as there are slight differences '
+ '(see $COPYPASTOR$), an auto flag would not be raised.',
comments: {
low: "Please don't add the [same answer to multiple questions](//meta.stackexchange.com/q/104227)."
Expand All @@ -84,8 +89,8 @@ export const flagCategories: FlagCategory[] = [
{
id: 5,
displayName: 'Bad attribution',
reportType: FlagNames.ModFlag,
flagText: 'This post is copied from [another answer]($TARGET$), as can be seen here $COPYPASTOR$. The author '
reportType: FlagNames.Plagiarism,
flagText: 'This post is copied from the linked answer, as can be seen here $COPYPASTOR$. The author '
+ 'only added a link to the other answer, which is [not the proper way of attribution]'
+ '(//stackoverflow.blog/2009/06/25/attribution-required).',
feedbacks: { Smokey: '', Natty: '', Guttenberg: 'tp', 'Generic Bot': '' },
Expand Down
2 changes: 1 addition & 1 deletion src/modals/comments/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import {
]
Notes:
- The ReportType can't be changed to/from PostOther for default flags.
- The ReportType can't be changed to/from PlagiarizedContent for default flags.
- The Human field is retrieved on runtime when the flag is raised based on ReportType.
- Each s-card div has a data-flag-id attribute based on which we can store the
information on cache again.
Expand Down
9 changes: 5 additions & 4 deletions src/modals/comments/rows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import {
BotNames,
AllFeedbacks,
possibleFeedbacks,
FlagNames,
} from '../../shared';
import { flagCategories } from '../../FlagTypes';
import { wrapInFlexItem, isModOrNoFlag } from '../../Configuration';
import { wrapInFlexItem, isPlagiarismOrNoFlag } from '../../Configuration';
import { toggleHideIfNeeded } from './main';

import {
Expand Down Expand Up @@ -257,7 +258,7 @@ function getFlagSelect(
const select = Select.makeStacksSelect(
`advanced-flagging-select-flag-${id}`,
options,
{ disabled: reportType === 'PostOther' }
{ disabled: reportType === FlagNames.Plagiarism }
);
select.className = 'd-flex ai-center';

Expand All @@ -270,7 +271,7 @@ function getFlagSelect(
flagLabel.classList.add('fw-bold', 'ps-relative', 'z-selected', 'l12', 'fs-body1', 'flex--item');
flagLabel.innerText = 'Flag:';

if (reportType === 'PostOther') {
if (reportType === FlagNames.Plagiarism) {
flagLabel.classList.add('o50');
}

Expand Down Expand Up @@ -318,7 +319,7 @@ export function getSelectRow({
wrapInFlexItem(downvoteBox)
);

if (!isModOrNoFlag(reportType)) {
if (!isPlagiarismOrNoFlag(reportType)) {
container.append(wrapInFlexItem(feedback));
}

Expand Down
5 changes: 3 additions & 2 deletions src/modals/comments/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
FlagTypeFeedbacks,
getFlagTypeFromFlagId,
updateFlagTypes,
FlagNames,
} from '../../shared';
import { Flags } from '../../FlagTypes';

Expand Down Expand Up @@ -47,9 +48,9 @@ function saveReportType(
const select = expandable.querySelector('select');
const newReportType = select?.value as Flags;

// can't select to flag for mod attention
// can't select to flag for plagiarism
// unless it's disabled, meaning it's a Guttenberg flag type
if (newReportType === 'PostOther' && !select?.disabled) {
if (newReportType === FlagNames.Plagiarism && !select?.disabled) {
displayStacksToast(
'This type of flag cannot be raised with this option',
'danger',
Expand Down
7 changes: 4 additions & 3 deletions src/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ async function handleReportLinkClick(
flag,
downvote,
flagText,
comment
comment,
reporters.Guttenberg?.targetUrl
);
}

Expand Down Expand Up @@ -381,8 +382,8 @@ function getReportLinks(
cachedFlagTypes
// exclude disabled and non-SO flag types
.filter(({ reportType, id, belongsTo, enabled }) => {
// only Guttenberg reports (can) have ReportType === 'PostOther' (for now)
const isGuttenbergItem = reportType === FlagNames.ModFlag;
// only Guttenberg reports (can) have ReportType === 'PlagiarizedContent'
const isGuttenbergItem = reportType === FlagNames.Plagiarism;

const showGutReport = Boolean(copypastorId) // a CopyPastor id must exist
// https://github.com/SOBotics/AdvancedFlagging/issues/16
Expand Down
12 changes: 7 additions & 5 deletions src/shared.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Store } from './UserscriptTools/Store';
import { Flags, FlagCategory, HumanFlags, FlagType } from './FlagTypes';
import { Flags, FlagCategory, FlagType } from './FlagTypes';

type BasicPlacement = 'auto' | 'top' | 'right' | 'bottom' | 'left';
// Minimum TypeScript Version: 4.1
Expand Down Expand Up @@ -55,8 +55,8 @@ export enum FlagNames {
Rude = 'PostOffensive',
NAA = 'AnswerNotAnAnswer',
VLQ = 'PostLowQuality',
ModFlag = 'PostOther',
NoFlag = 'NoFlag'
NoFlag = 'NoFlag',
Plagiarism = 'PlagiarizedContent'
}

// Constants
Expand Down Expand Up @@ -236,14 +236,16 @@ export function getFlagTypeFromFlagId(flagId: number): CachedFlag | null {
return cachedFlagTypes.find(({ id }) => id === flagId) || null;
}

export type HumanFlags = 'as NAA' | 'as R/A' | 'as spam' | 'for plagiarism' | 'as VLQ' | '';

export function getHumanFromDisplayName(displayName: Flags): HumanFlags {
const flags = {
[FlagNames.Spam]: 'as spam',
[FlagNames.Rude]: 'as R/A',
[FlagNames.NAA]: 'as NAA',
[FlagNames.VLQ]: 'as VLQ',
[FlagNames.ModFlag]: 'for moderator attention',
[FlagNames.NoFlag]: ''
[FlagNames.NoFlag]: '',
[FlagNames.Plagiarism]: 'for plagiarism'
} as const;

return flags[displayName] || '';
Expand Down

0 comments on commit cce8b26

Please sign in to comment.