Skip to content

Commit

Permalink
feat(entity/context): redirect to source, target, or specific service
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Oct 28, 2019
1 parent 3d2adb2 commit 83e899f
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/controller/BaseController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export abstract class BaseController<TData extends ControllerData> extends BotSe
}

protected async reply(sourceCtx: Context, body: string): Promise<void> {
const context = redirectContext(sourceCtx, this.data.redirect);
const context = redirectContext(sourceCtx, this.data.redirect, this.services);
const msg = new Message({
body,
context,
Expand Down
2 changes: 1 addition & 1 deletion src/controller/CompletionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class CompletionController extends BaseController<CompletionControllerDat

protected async createContext(maybeCtx?: Context) {
const ctx = mustExist(maybeCtx);
return redirectContext(ctx, this.data.redirect);
return redirectContext(ctx, this.data.redirect, this.services);
}

protected async getFragment(ctx: Context, id: string): Promise<Fragment> {
Expand Down
2 changes: 1 addition & 1 deletion src/controller/EchoController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class EchoController extends BaseController<EchoControllerData> implement
@Handler(NOUN_ECHO, CommandVerb.Create)
@CheckRBAC()
public async createEcho(cmd: Command, ctx: Context): Promise<void> {
const targetCtx = redirectContext(ctx, this.data.redirect);
const targetCtx = redirectContext(ctx, this.data.redirect, this.services);

this.logger.debug({ cmd, ctx, targetCtx }, 'echoing command');

Expand Down
66 changes: 56 additions & 10 deletions src/entity/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { MissingValueError } from 'noicejs';
import { newTrie, ShiroTrie } from 'shiro-trie';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

import { NotFoundError } from '../error/NotFoundError';
import { Listener } from '../listener';
import { ServiceModule } from '../module/ServiceModule';
import { Parser } from '../parser';
import { ServiceMetadata } from '../Service';
import { doesExist, mustCoalesce, Optional } from '../utils';
import { doesExist, mustCoalesce, mustExist, Optional } from '../utils';
import { Token } from './auth/Token';
import { GRAPH_OUTPUT_USER, User } from './auth/User';
import { BaseEntity, BaseEntityOptions } from './base/BaseEntity';
Expand All @@ -31,12 +33,13 @@ export interface ContextData {
uid: string;
}

export interface ContextOptions extends BaseEntityOptions, ContextData {
parser?: Parser;

export interface ContextRoute {
source?: Listener;

target?: Listener;
}

export interface ContextOptions extends BaseEntityOptions, ContextData, ContextRoute {
parser?: Parser;

token?: Token;

Expand All @@ -47,8 +50,9 @@ export interface ContextOptions extends BaseEntityOptions, ContextData {
}

export interface ListenerRedirect {
source: boolean;
source?: boolean;
service?: ServiceMetadata;
target?: boolean;
}

export interface ContextRedirectStage extends ContextData {
Expand All @@ -64,7 +68,7 @@ export interface ContextRedirect {
export const TABLE_CONTEXT = 'context';

@Entity(TABLE_CONTEXT)
export class Context extends BaseEntity implements ContextOptions {
export class Context extends BaseEntity implements ContextOptions, ContextRoute {
@Column('simple-json')
public channel: ChannelData;

Expand Down Expand Up @@ -192,13 +196,55 @@ export function extractRedirect(stage: Optional<Partial<ContextRedirectStage>>):
};
}

export function redirectContext(original: Context, redirect: ContextRedirect): Context {
export function redirectService(original: Context, redirect: ContextRedirect, services: ServiceModule, key: 'source' | 'target'): Listener {
// check forces
const forces = redirect.forces[key];
if (doesExist(forces)) {
if (forces.source === true) {
return mustExist(original.source);
}

if (forces.target === true) {
return mustExist(original.target);
}

if (doesExist(forces.service)) {
return services.getService(forces.service);
}
}

// check original
const originalListener = original[key];
if (doesExist(originalListener)) {
return originalListener;
}

// check defaults
const defaults = redirect.defaults[key];
if (doesExist(defaults)) {
if (defaults.source === true) {
return mustExist(original.source);
}

if (defaults.target === true) {
return mustExist(original.target);
}

if (doesExist(defaults.service)) {
return services.getService(defaults.service);
}
}

throw new NotFoundError();
}

export function redirectContext(original: Context, redirect: ContextRedirect, services: ServiceModule): Context {
const channel = mustCoalesce(redirect.defaults.channel, original.channel, redirect.forces.channel);
const name = mustCoalesce(redirect.defaults.name, original.name, redirect.forces.name);
const uid = mustCoalesce(redirect.defaults.uid, original.uid, redirect.forces.uid);
// loop up source and target services, user
const source = original.source;
const target = original.target;
const source = redirectService(original, redirect, services, 'source');
const target = redirectService(original, redirect, services, 'target');

return new Context({
channel,
Expand Down
2 changes: 1 addition & 1 deletion src/generator/BaseGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export abstract class BaseGenerator<TData extends GeneratorData> extends BotServ
*/
protected async createContext(): Promise<Context> {
const base = new Context(this.data.context);
const ctx = redirectContext(base, this.data.redirect);
const ctx = redirectContext(base, this.data.redirect, this.services);
return this.contextRepository.save(ctx);
}
}
2 changes: 1 addition & 1 deletion src/listener/LoopbackListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class LoopbackListener extends BaseListener<LoopbackListenerData> impleme

const outCtx = await this.createContext(ctx);
const outMsg = new Message(msg);
outMsg.context = redirectContext(outCtx, this.data.redirect);
outMsg.context = redirectContext(outCtx, this.data.redirect, this.services);

await this.bot.receive(outMsg);
}
Expand Down
29 changes: 29 additions & 0 deletions src/schema/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,45 @@ definitions:
target:
$ref: "#/definitions/service-metadata"

entity-context-route:
oneOf:
- type: object
additionalProperties: false
required: [service]
properties:
service:
$ref: "#/definitions/service-metadata"
- type: object
additionalProperties: false
required: [source]
properties:
source:
type: boolean
- type: object
additionalProperties: false
required: [target]
properties:
target:
type: boolean

entity-context-redirect:
type: object
additionalProperties: false
properties:
defaults:
allOf:
- $ref: "#/definitions/entity-context-data"
- source:
$ref: "#/definitions/entity-context-route"
- target:
$ref: "#/definitions/entity-context-route"
forces:
allOf:
- $ref: "#/definitions/entity-context-data"
- source:
$ref: "#/definitions/entity-context-route"
- target:
$ref: "#/definitions/entity-context-route"

entity-message:
type: object
Expand Down

0 comments on commit 83e899f

Please sign in to comment.