Skip to content

Commit

Permalink
Merge pull request #45 from juni-b-queer/validator-factory-methods
Browse files Browse the repository at this point in the history
Validator factory methods
  • Loading branch information
juni-b-queer authored May 8, 2024
2 parents 1ecb0fd + cc6de7a commit 3e44a26
Show file tree
Hide file tree
Showing 32 changed files with 237 additions and 171 deletions.
2 changes: 1 addition & 1 deletion src/handlers/AbstractMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ export class MessageHandler extends AbstractMessageHandler {
}
}
}
}
}
60 changes: 31 additions & 29 deletions src/handlers/TestHandler.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import { AbstractValidator } from "../validations/AbstractValidator";
import { AbstractMessageAction } from "../actions/AbstractMessageAction";
import { HandlerAgent } from "../agent/HandlerAgent";
import { JetstreamMessage } from "../types/JetstreamTypes";
import { DebugLog } from "../utils/DebugLog";
import { AbstractMessageHandler, MessageHandler } from "./AbstractMessageHandler";

export class TestHandler extends AbstractMessageHandler {
constructor(
validators: Array<AbstractValidator>,
actions: Array<AbstractMessageAction | MessageHandler>,
handlerAgent: HandlerAgent
) {
super(validators, actions, handlerAgent);
return this;
}

async handle(message: JetstreamMessage): Promise<void> {
const shouldTrigger = await this.shouldTrigger(message);
if (shouldTrigger) {
try {
await this.runActions(message);
} catch (exception) {
DebugLog.error('Message Handler', exception as string);
}
}
}
}

import { AbstractValidator } from '../validations/AbstractValidator';
import { AbstractMessageAction } from '../actions/AbstractMessageAction';
import { HandlerAgent } from '../agent/HandlerAgent';
import { JetstreamMessage } from '../types/JetstreamTypes';
import { DebugLog } from '../utils/DebugLog';
import {
AbstractMessageHandler,
MessageHandler,
} from './AbstractMessageHandler';

export class TestHandler extends AbstractMessageHandler {
constructor(
validators: Array<AbstractValidator>,
actions: Array<AbstractMessageAction | MessageHandler>,
handlerAgent: HandlerAgent
) {
super(validators, actions, handlerAgent);
return this;
}

async handle(message: JetstreamMessage): Promise<void> {
const shouldTrigger = await this.shouldTrigger(message);
if (shouldTrigger) {
try {
await this.runActions(message);
} catch (exception) {
DebugLog.error('Message Handler', exception as string);
}
}
}
}
7 changes: 5 additions & 2 deletions src/handlers/premade-handlers/BadBotHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ export class BadBotHandler extends CreateSkeetHandler {
);
}

static make(handlerAgent: HandlerAgent, response: string|undefined = undefined): BadBotHandler{
return new BadBotHandler(handlerAgent, response)
static make(
handlerAgent: HandlerAgent,
response: string | undefined = undefined
): BadBotHandler {
return new BadBotHandler(handlerAgent, response);
}

async handle(message: CreateSkeetMessage): Promise<void> {
Expand Down
7 changes: 5 additions & 2 deletions src/handlers/premade-handlers/GoodBotHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ export class GoodBotHandler extends CreateSkeetHandler {
);
}

static make(handlerAgent: HandlerAgent, response: string|undefined = undefined): GoodBotHandler{
return new GoodBotHandler(handlerAgent, response)
static make(
handlerAgent: HandlerAgent,
response: string | undefined = undefined
): GoodBotHandler {
return new GoodBotHandler(handlerAgent, response);
}

async handle(message: CreateSkeetMessage): Promise<void> {
Expand Down
8 changes: 6 additions & 2 deletions src/handlers/premade-handlers/OfflineHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ export class OfflineHandler extends CreateSkeetHandler {
);
}

static make(handlerAgent: HandlerAgent, command: string, response: string|undefined = undefined): OfflineHandler{
return new OfflineHandler(handlerAgent,command, response)
static make(
handlerAgent: HandlerAgent,
command: string,
response: string | undefined = undefined
): OfflineHandler {
return new OfflineHandler(handlerAgent, command, response);
}

async handle(message: CreateSkeetMessage): Promise<void> {
Expand Down
21 changes: 20 additions & 1 deletion src/validations/AbstractValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,36 @@ import { HandlerAgent } from '../agent/HandlerAgent';
import { CreateSkeetMessage, JetstreamMessage } from '../types/JetstreamTypes';

export abstract class AbstractValidator {
private negate: boolean = false;
constructor() {}

static make(...args: any): AbstractValidator {
throw new Error('Method Not Implemented! Use constructor.');
}

not(): AbstractValidator {
this.negate = true;
return this;
}

getTextFromPost(message: JetstreamMessage): string {
const createSkeetMessage = message as CreateSkeetMessage;
const text = createSkeetMessage.record.text;
return <string>text;
}

// @ts-ignore
abstract async shouldTrigger(
abstract async handle(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean>;

// @ts-ignore
async shouldTrigger(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
const valid: boolean = await this.handle(message, handlerAgent);
return this.negate ? !valid : valid;
}
}
12 changes: 10 additions & 2 deletions src/validations/BotValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ export class IsGoodBotValidator extends AbstractValidator {
super();
}

async shouldTrigger(
static make(): IsGoodBotValidator {
return new IsGoodBotValidator();
}

async handle(
message: CreateSkeetMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand All @@ -31,7 +35,11 @@ export class IsBadBotValidator extends AbstractValidator {
super();
}

async shouldTrigger(
static make(): IsBadBotValidator {
return new IsBadBotValidator();
}

async handle(
message: CreateSkeetMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand Down
6 changes: 5 additions & 1 deletion src/validations/GenericValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ export class ActionTakenByUserValidator extends AbstractValidator {
super();
}

async shouldTrigger(
static make(userDid: string): ActionTakenByUserValidator {
return new ActionTakenByUserValidator(userDid);
}

async handle(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand Down
39 changes: 15 additions & 24 deletions src/validations/LogicalValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ export class SimpleFunctionValidator extends AbstractValidator {
super();
}

async shouldTrigger(
static make(
triggerValidator: (
arg0: JetstreamMessage,
arg1: HandlerAgent
) => boolean | PromiseLike<boolean>
): SimpleFunctionValidator {
return new SimpleFunctionValidator(triggerValidator);
}

async handle(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand All @@ -33,7 +42,11 @@ export class OrValidator extends AbstractValidator {
super();
}

async shouldTrigger(
static make(validators: Array<AbstractValidator>): OrValidator {
return new OrValidator(validators);
}

async handle(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand All @@ -50,25 +63,3 @@ export class OrValidator extends AbstractValidator {
return willTrigger;
}
}

/**
* @class NotValidator
* @extends AbstractValidator
* @description A class that represents a validator that negates the result of another validator.
*/
export class NotValidator extends AbstractValidator {
constructor(private validator: AbstractValidator) {
super();
}

async shouldTrigger(
message: JetstreamMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
const willTrigger = await this.validator.shouldTrigger(
message,
handlerAgent
);
return !willTrigger;
}
}
36 changes: 18 additions & 18 deletions src/validations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class ExampleValidator extends AbstractValidator {
super();
}

async shouldTrigger(
async handle(
message: CreateSkeetMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand All @@ -67,7 +67,7 @@ export class ExampleValidator extends AbstractValidator {
super();
}

async shouldTrigger(
async handle(
message: CreateSkeetMessage,
handlerAgent: HandlerAgent
): Promise<boolean> {
Expand All @@ -83,73 +83,73 @@ export class ExampleValidator extends AbstractValidator {

The `SimpleFunctionValidator` class provides a way to create a validator by passing a single function that accepts the JetstreamMessage and HandlerAgent and returns a boolean indicating whether to trigger the action or not.

`new SimpleFunctionValidator((message, handlerAgent) => { return true; }); // replace function with specific condition`
`SimpleFunctionValidator.make((message, handlerAgent) => { return true; }); // replace function with specific condition`

### OrValidator

The `OrValidator` class allows you to pass in multiple validators. If any of these validators return `true`, it will trigger the action.

`new OrValidator([validator1, validator2, validator3]); // replace with actual validator instances`
`OrValidator.make([validator1, validator2, validator3]); // replace with actual validator instances`

### NotValidator

The `NotValidator` class allows you to negate the original output from the given validator. The NotValidator will return the opposite of the validator passed into it

`new NotValidator(validator1, validator2, validator3); // replace with actual validator instances`
`NotValidator.make(validator1, validator2, validator3); // replace with actual validator instances`

## Generic Validators

### ActionTakenByUserValidator

The `ActionTakenByUserValidator` class checks if the action (post, repost, like, follow) was done by a given user

`new ActionTakenByUserValidator('did:plc:123');`
`ActionTakenByUserValidator.make('did:plc:123');`

## Post validators

### PostedByUserValidator

The `PostedByUserValidator` class checks if the post was made by a specific user, identified by their DID (Decentralized Identifier).

`new PostedByUserValidator('did:plc:123');`
`PostedByUserValidator.make('did:plc:123');`

### ReplyingToBotValidator

The `ReplyingToBotValidator` class verifies if the post is a reply to the bot/handlerAgent.

`new ReplyingToBotValidator();`
`ReplyingToBotValidator.make();`

### IsReplyValidator

The `IsReplyValidator` class checks if the post is a reply to another post.

`new IsReplyValidator();`
`IsReplyValidator.make();`

## String Validators

### InputIsCommandValidator

The `InputIsCommandValidator` class validates if the input is a command triggered by a specific key. The `strict` argument enforces case sensitivity when set to `true`.

`new InputIsCommandValidator('myTriggerKey', true); // enabling strict mode`
`InputIsCommandValidator.make('myTriggerKey', true); // enabling strict mode`

### InputStartsWithValidator

The `InputStartsWithValidator` class checks if the input starts with a specific key. The `strict` argument, when set to `true`, enforces case sensitivity.

`new InputStartsWithValidator('myTriggerKey', false);`
`InputStartsWithValidator.make('myTriggerKey', false);`

### InputContainsValidator

The `InputContainsValidator` class verifies if the input contains a specific key. The `strict` argument, when set to `true`, enforces case sensitivity.

`new InputContainsValidator('myTriggerKey', false);`
`InputContainsValidator.make('myTriggerKey', false);`

### InputEqualsValidator

The `InputEqualsValidator` class checks if the input exactly matches a specific key.

`new InputEqualsValidator('myTriggerKey');`
`InputEqualsValidator.make('myTriggerKey');`

## Bot Validators

Expand All @@ -159,15 +159,15 @@ The `IsGoodBotValidator` class checks if the input is replying to the bot and th

It will also accept "thank you" (for full list of accepted inputs, see `isGoodBotResponse` in `utils/text-utils`)

`new IsGoodBotValidator();`
`IsGoodBotValidator.make();`

### IsBadBotValidator

The `IsBadBotValidator` class checks if the input is replying to the bot and the text is "{negative word} bot" (ex. bad bot).

(for full list of accepted inputs, see `isBadBotResponse` in `utils/text-utils`)

`new IsBadBotValidator();`
`IsBadBotValidator.make();`

## Follow Validators

Expand All @@ -176,14 +176,14 @@ The `IsBadBotValidator` class checks if the input is replying to the bot and the
The `NewFollowerForUserValidator` will return true if the follow action was a new follower for the given user
If no did is provided, it will default to the bot/handlerAgent did

`new NewFollowerForUserValidator('did:plc:123');`
`NewFollowerForUserValidator.make('did:plc:123');`

### NewFollowFromUserValidator

The `NewFollowFromUserValidator` will return true if the follow action was the given user following someone
If no did is provided, it will default to the bot/handlerAgent did

`new NewFollowFromUserValidator('did:plc:123');`
`NewFollowFromUserValidator.make('did:plc:123');`

**Was previously `UserFollowedValidator` (which still works for now) but has been renamed to fit with the other follow validators**

Expand All @@ -193,4 +193,4 @@ If no did is provided, it will default to the bot/handlerAgent did

The `TestValidator` class accepts a boolean in the constructor, and then returns that boolean when validated. Mostly used for testing

`new TestValidator(true|false);`
`TestValidator.make(true|false);`
Loading

0 comments on commit 3e44a26

Please sign in to comment.