Compare commits

..

64 Commits

Author SHA1 Message Date
FoxxMD
a891e2d42b Merge branch 'edge' 2022-11-29 09:54:39 -05:00
FoxxMD
ef372e531e fix(database): Prevent usage of LIMIT in session storage driver when db backend is mysql/mariadb
Related to freshgiammi-lab/connect-typeorm#8

Closes #128
2022-11-29 09:47:55 -05:00
FoxxMD
fde2836208 chore: remove comments about wrong endpoints
At some point maybe this was fixed by reddit silently?
2022-11-28 14:36:33 -05:00
Matt Foxx
021dd5b0c5 Merge pull request #130 from rysie/bug/selecftlair-fix 2022-11-28 14:35:39 -05:00
Marcin Macinski
5bd38d367a assignFlair doesn't work with flair_template_id 2022-11-25 17:13:49 +01:00
FoxxMD
95c65304d4 Merge branch 'edge' 2022-11-15 09:36:42 -05:00
FoxxMD
d765a639dc Merge branch 'edge' 2022-11-14 14:43:40 -05:00
FoxxMD
70a04a0db6 Merge branch 'edge' 2022-11-14 13:29:00 -05:00
FoxxMD
75fcfece84 Merge branch 'edge' 2022-11-14 12:22:27 -05:00
FoxxMD
4b26b7d371 Merge branch 'edge' 2022-11-14 12:10:48 -05:00
FoxxMD
3d26fd2e3b Merge branch 'edge' 2022-11-09 15:30:48 -05:00
FoxxMD
74925fa8d8 Merge branch 'edge' 2022-11-01 09:23:38 -04:00
FoxxMD
d02d70ded3 Merge branch 'edge' 2022-10-17 15:33:15 -04:00
FoxxMD
80f83bf84b Merge branch 'edge' 2022-10-05 08:57:04 -04:00
FoxxMD
7933f77764 Merge branch 'edge' 2022-10-05 08:55:39 -04:00
FoxxMD
3bcc3d78e8 Merge branch 'edge' 2022-09-28 09:28:38 -04:00
FoxxMD
296f1c8dee Merge branch 'edge' 2022-09-14 15:30:27 -04:00
FoxxMD
e32ac60db5 Merge branch 'edge' 2022-09-14 15:29:13 -04:00
FoxxMD
859680dca8 Merge branch 'edge' 2022-09-01 09:03:27 -04:00
FoxxMD
ffa1e423b2 Merge branch 'edge' 2022-08-23 09:49:23 -04:00
FoxxMD
09cb08492c Merge branch 'edge' 2022-08-23 09:47:59 -04:00
FoxxMD
d9ab81ab8c Merge branch 'edge' 2022-07-27 09:19:30 -04:00
FoxxMD
98691bd19c Merge branch 'edge' 2022-07-15 09:27:22 -04:00
FoxxMD
8123c34463 Merge branch 'edge' 2022-06-21 16:13:54 -04:00
FoxxMD
3292d011fa Merge branch 'edge' 2022-06-21 10:03:14 -04:00
FoxxMD
661a0ae440 Merge branch 'edge' 2022-05-26 09:59:32 -04:00
FoxxMD
05f477b67d Merge branch 'edge' 2022-05-12 12:27:51 -04:00
Matt Foxx
1317a5916c Merge pull request #86 from wchristian/example_fix
trying to use names key in authorfilter causes config parse failure
2022-04-05 16:55:56 -04:00
Christian Walde
e9135ec1ef trying to use names key in authorfilter causes config parse failure 2022-04-05 13:49:41 +02:00
FoxxMD
e58a0f8f21 Merge branch 'edge' 2022-03-14 12:39:05 -04:00
FoxxMD
f7cebc013b Merge branch 'edge' 2022-03-08 09:48:06 -05:00
FoxxMD
ae8e11feb4 Merge branch 'edge' 2022-02-22 11:11:46 -05:00
FoxxMD
e07b8cc291 Merge branch 'edge' 2022-02-18 11:58:28 -05:00
FoxxMD
fc51928054 Merge branch 'edge' 2022-02-02 16:59:56 -05:00
FoxxMD
e2590e50f8 Merge branch 'edge' 2022-01-28 17:27:51 -05:00
FoxxMD
aaed0d3419 Merge branch 'edge' 2022-01-21 10:46:11 -05:00
FoxxMD
bc7eff8928 Merge branch 'edge' 2022-01-14 15:27:09 -05:00
FoxxMD
d6954533a0 Merge branch 'edge' 2022-01-10 12:32:14 -05:00
FoxxMD
ba53233640 Merge branch 'edge' 2022-01-07 09:31:14 -05:00
FoxxMD
1ac7ad4724 Merge branch 'edge' 2022-01-03 16:35:01 -05:00
FoxxMD
2a282a0d6f Merge branch 'edge' 2021-12-21 09:35:21 -05:00
FoxxMD
fd5a92758d Merge branch 'edge' 2021-11-28 19:43:20 -05:00
FoxxMD
39daa11f2d Merge branch 'edge' 2021-11-15 12:53:28 -05:00
FoxxMD
dac6541e28 Merge branch 'edge' 2021-11-01 16:12:43 -04:00
FoxxMD
97906281e6 Merge branch 'edge' 2021-11-01 14:55:10 -04:00
FoxxMD
487f13f704 Merge branch 'edge' 2021-10-12 11:56:51 -04:00
FoxxMD
631e21452c Merge branch 'edge' 2021-09-28 16:36:13 -04:00
FoxxMD
4f3685a1f5 Merge branch 'edge' 2021-09-21 15:18:38 -04:00
FoxxMD
d2d945db2c Merge branch 'edge' 2021-09-21 15:08:28 -04:00
FoxxMD
910f7f79ef Merge branch 'edge' 2021-09-20 10:54:32 -04:00
FoxxMD
a11b667d5e Merge branch 'edge' 2021-09-13 16:16:55 -04:00
FoxxMD
885e3fa765 Merge branch 'edge' 2021-08-26 16:04:01 -04:00
FoxxMD
465c3c9acf Merge branch 'edge' 2021-08-20 15:02:24 -04:00
FoxxMD
161251a943 Merge branch 'edge' 2021-08-05 14:40:06 -04:00
FoxxMD
ce4cb96d9a Merge branch 'edge' 2021-08-03 23:39:14 -04:00
FoxxMD
c317f95953 Merge branch 'edge' 2021-08-03 22:43:02 -04:00
FoxxMD
d0e0515990 Merge branch 'edge' 2021-08-02 15:44:57 -04:00
FoxxMD
cdddd8de48 Merge branch 'edge' 2021-07-30 18:17:38 -04:00
FoxxMD
f598215d88 Merge branch 'edge' 2021-07-30 14:46:51 -04:00
FoxxMD
0c7218571c Merge branch 'edge' 2021-07-29 13:25:16 -04:00
FoxxMD
acc7c49e0e Merge branch 'edge' 2021-07-29 11:27:42 -04:00
FoxxMD
01839512d5 Merge branch 'edge' 2021-07-29 11:14:33 -04:00
FoxxMD
4680640b0c Merge branch 'develop' 2021-07-28 16:58:36 -04:00
Matt Foxx
b813ebdd96 Create dockerhub.yml 2021-07-28 11:27:04 -04:00
6 changed files with 60 additions and 154 deletions

View File

@@ -40,7 +40,7 @@
// for this to pass the Author of the Submission must not have the flair "Supreme Memer" and have the name "user1" or "user2"
{
"flairText": ["Supreme Memer"],
"names": ["user1","user2"]
"name": ["user1","user2"]
},
{
// for this to pass the Author of the Submission must not have the flair "Decent Memer"

View File

@@ -30,7 +30,7 @@ runs:
# for this to pass the Author of the Submission must not have the flair "Supreme Memer" and have the name "user1" or "user2"
- flairText:
- Supreme Memer
names:
name:
- user1
- user2
# for this to pass the Author of the Submission must not have the flair "Decent Memer"

View File

@@ -43,11 +43,7 @@ export class FlairAction extends Action {
if (item instanceof Submission) {
if(!this.dryRun) {
if (this.flair_template_id) {
// typings are wrong for this function, flair_template_id should be accepted
// assignFlair uses /api/flair (mod endpoint)
// selectFlair uses /api/selectflair (self endpoint for user to choose their own flair for submission)
// @ts-ignore
await item.assignFlair({flair_template_id: this.flair_template_id}).then(() => {});
await item.selectFlair({flair_template_id: this.flair_template_id}).then(() => {});
item.link_flair_template_id = this.flair_template_id;
} else {
await item.assignFlair({text: renderedText, cssClass: renderedCss}).then(() => {});

View File

@@ -748,10 +748,6 @@ export interface RegExResult {
named: NamedGroup
}
export interface RegExResultWithTest extends RegExResult {
test: RegExp
}
export type StrongCache = {
authorTTL: number | boolean,
userNotesTTL: number | boolean,

View File

@@ -7,7 +7,6 @@ import {
PASS, triggeredIndicator, windowConfigToWindowCriteria
} from "../util";
import {
RegExResultWithTest,
RuleResult,
} from "../Common/interfaces";
import dayjs from 'dayjs';
@@ -15,11 +14,10 @@ import {SimpleError} from "../Utils/Errors";
import {JoinOperands} from "../Common/Infrastructure/Atomic";
import {ActivityWindowConfig} from "../Common/Infrastructure/ActivityWindow";
import {
comparisonTextOp, GenericComparison,
comparisonTextOp,
parseGenericValueComparison,
parseGenericValueOrPercentComparison
} from "../Common/Infrastructure/Comparisons";
import {SnoowrapActivity} from "../Common/Infrastructure/Reddit";
export interface RegexCriteria {
/**
@@ -29,23 +27,13 @@ export interface RegexCriteria {
* */
name?: string
/**
* A valid Regular Expression, or list of expressions, to test content against
* A valid Regular Expression to test content against
*
* If no flags are specified then the **global** flag is used by default
*
* @examples ["/reddit|FoxxMD/ig"]
* */
regex: string | string[],
/**
* Determines if ALL regexes listed are run or if regexes are only run until one is matched.
*
* * `true` => all regexes are always run
* * `false` => regexes are run until one matches
*
* @default false
* */
exhaustive?: boolean
regex: string,
/**
* Which content from an Activity to test the regex against
@@ -169,7 +157,6 @@ export class RegexRule extends Rule {
const {
name = (index + 1),
regex,
exhaustive = false,
testOn: testOnVals = ['title', 'body'],
lookAt = 'all',
matchThreshold = '> 0',
@@ -187,7 +174,13 @@ export class RegexRule extends Rule {
return acc.concat(curr);
}, []);
const regexTests: RegExp[] = await this.convertToRegexArray(name, regex);
// check regex
const regexContent = await this.resources.getContent(regex);
const reg = parseStringToRegex(regexContent, 'g');
if(reg === undefined) {
throw new SimpleError(`Value given for regex on Criteria ${name} was not valid: ${regex}`);
}
// ok cool its a valid regex
const matchComparison = parseGenericValueComparison(matchThreshold);
const activityMatchComparison = activityMatchThreshold === null ? undefined : parseGenericValueOrPercentComparison(activityMatchThreshold);
@@ -205,13 +198,12 @@ export class RegexRule extends Rule {
// first lets see if the activity we are checking satisfies thresholds
// since we may be able to avoid api calls to get history
let actMatches = getMatchesFromActivity(item, testOn, regexTests, exhaustive);
const actMatchSummary = regexResultsSummary(actMatches);
matches = matches.concat(actMatchSummary.matches).slice(0, 100);
matchCount += actMatchSummary.matches.length;
let actMatches = this.getMatchesFromActivity(item, testOn, reg);
matches = matches.concat(actMatches).slice(0, 100);
matchCount += actMatches.length;
activitiesTested++;
const singleMatched = comparisonTextOp(actMatchSummary.matches.length, matchComparison.operator, matchComparison.value);
const singleMatched = comparisonTextOp(actMatches.length, matchComparison.operator, matchComparison.value);
if (singleMatched) {
activitiesMatchedCount++;
}
@@ -241,7 +233,7 @@ export class RegexRule extends Rule {
}
history = await this.resources.getAuthorActivities(item.author, strongWindow);
// remove current activity if it exists in history so we don't count it twice
// remove current activity it exists in history so we don't count it twice
history = history.filter(x => x.id !== item.id);
const historyLength = history.length;
@@ -260,12 +252,10 @@ export class RegexRule extends Rule {
for (const h of history) {
activitiesTested++;
const aMatches = getMatchesFromActivity(h, testOn, regexTests, exhaustive);
actMatches = actMatches.concat(aMatches);
const actHistoryMatchSummary = regexResultsSummary(aMatches);
matches = matches.concat(actHistoryMatchSummary.matches).slice(0, 100);
matchCount += actHistoryMatchSummary.matches.length;
const matched = comparisonTextOp(actHistoryMatchSummary.matches.length, matchComparison.operator, matchComparison.value);
const aMatches = this.getMatchesFromActivity(h, testOn, reg);
matches = matches.concat(aMatches).slice(0, 100);
matchCount += aMatches.length;
const matched = comparisonTextOp(aMatches.length, matchComparison.operator, matchComparison.value);
if (matched) {
activitiesMatchedCount++;
}
@@ -292,19 +282,10 @@ export class RegexRule extends Rule {
humanWindow = '1 Item';
}
// to provide at least one useful regex for this criteria
// use the first regex found by default
let relevantRegex: string = regexTests[0].toString();
// but if more than one regex was listed AND we did have matches
// then use the first regex that actually got a match
if(regexTests.length > 0 && actMatches.length > 0) {
relevantRegex = actMatches[0].test.toString();
}
const critResults = {
criteria: {
name,
regex: relevantRegex,
regex: regex !== regexContent ? `${regex} from ${regexContent}` : regex,
testOn,
matchThreshold,
activityMatchThreshold,
@@ -371,115 +352,42 @@ export class RegexRule extends Rule {
return Promise.resolve([criteriaMet, this.getResult(criteriaMet, {result, data: {results: criteriaResults, matchSample }})]);
}
protected async convertToRegexArray(name: string | number, value: string | string[]): Promise<RegExp[]> {
const regexTests: RegExp[] = [];
const regexStringVals = typeof value === 'string' ? [value] : value;
for(const r of regexStringVals) {
// check regex
const regexContent = await this.resources.getContent(r);
const reg = parseStringToRegex(regexContent, 'ig');
if (reg === undefined) {
throw new SimpleError(`Value given for regex on Criteria ${name} was not valid: ${value}`);
}
// ok cool its a valid regex
regexTests.push(reg);
}
return regexTests;
}
}
export const getMatchResultsFromContent = (contents: string[], reg: RegExp): RegExResultWithTest[] => {
let m: RegExResultWithTest[] = [];
for (const c of contents) {
const results = parseRegex(reg, c);
if(results !== undefined) {
for(const r of results) {
m.push({...r, test: reg});
}
}
}
return m;
}
export const regexResultsSummary = (results: RegExResultWithTest[]) => {
const matchResults: ActivityMatchResults = {
matches: [],
matchesByTest: {},
groups: {}
}
for (const r of results) {
if (matchResults.matchesByTest[r.test.toString()] === undefined) {
matchResults.matchesByTest[r.test.toString()] = [];
}
matchResults.matchesByTest[r.test.toString()].push(r.match);
matchResults.matches.push(r.match);
if (r.named !== undefined) {
Object.entries(r.named).forEach(([key, val]) => {
if (matchResults.groups[key] === undefined) {
matchResults.groups[key] = [];
protected getMatchesFromActivity(a: (Submission | Comment), testOn: string[], reg: RegExp): string[] {
let m: string[] = [];
// determine what content we are testing
let contents: string[] = [];
if (asSubmission(a)) {
for (const l of testOn) {
switch (l) {
case 'title':
contents.push(a.title);
break;
case 'body':
if (a.is_self) {
contents.push(a.selftext);
}
break;
case 'url':
if (isExternalUrlSubmission(a)) {
contents.push(a.url);
}
break;
}
matchResults.groups[key].push(val);
});
}
} else {
contents.push(a.body)
}
}
return matchResults;
}
export const getMatchesFromActivity = (a: (Submission | Comment), testOn: string[], regexes: RegExp[], exhaustive: boolean): RegExResultWithTest[] => {
// determine what content we are testing
let contents: string[] = getMatchableContent(a, testOn);
let results: RegExResultWithTest[] = [];
for (const reg of regexes) {
const res = getMatchResultsFromContent(contents, reg);
if(res.length > 0) {
results = results.concat(res);
// only continue testing if the user wants to exhaustively check all regexes (to get more matches?)
if(!exhaustive) {
return results;
for (const c of contents) {
const results = parseRegex(reg, c);
if(results !== undefined) {
for(const r of results) {
m.push(r.match);
}
}
}
return m;
}
return results;
}
const getMatchableContent = (a: SnoowrapActivity, testOn: string[]) => {
let contents: string[] = [];
if (asSubmission(a)) {
for (const l of testOn) {
switch (l) {
case 'title':
contents.push(a.title);
break;
case 'body':
if (a.is_self) {
contents.push(a.selftext);
}
break;
case 'url':
if (isExternalUrlSubmission(a)) {
contents.push(a.url);
}
break;
}
}
} else {
contents.push(a.body)
}
return contents;
}
interface RegexMatchComparisonOptions {
matchComparison: GenericComparison
activityMatchComparison?: GenericComparison
totalMatchComparison?: GenericComparison
}
interface ActivityMatchResults {
matches: string[]
matchesByTest: Record<string, string[]>
groups: Record<string, string[]>
}
interface RegexConfig {

View File

@@ -12,6 +12,7 @@ import {Logger} from "winston";
import {WebSetting} from "../../Common/WebEntities/WebSetting";
import {ErrorWithCause} from "pony-cause";
import {createCacheManager} from "../../Common/Cache";
import {MysqlDriver} from "typeorm/driver/mysql/MysqlDriver";
export interface CacheManagerStoreOptions {
prefix?: string
@@ -103,7 +104,12 @@ export class DatabaseStorageProvider extends StorageProvider {
}
createSessionStore(options?: TypeormStoreOptions): Store {
return new TypeormStore(options).connect(this.clientSessionRepo)
// https://github.com/freshgiammi-lab/connect-typeorm#implement-the-session-entity
// https://github.com/freshgiammi-lab/connect-typeorm/issues/8
// usage of LIMIT in subquery is not supported by mariadb/mysql
// limitSubquery: false -- turns off LIMIT usage
const realOptions = this.database.driver instanceof MysqlDriver ? {...options, limitSubquery: false} : options;
return new TypeormStore(realOptions).connect(this.clientSessionRepo)
}
async getSessionSecret(): Promise<string | undefined> {