Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplementing bots #119

Merged
merged 23 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
"aaron-bond.better-comments",
"streetsidesoftware.code-spell-checker",
"coenraads.bracket-pair-colorizer-2",
"docsmsft.docs-markdown",
"oouo-diogo-perdigao.docthis",
"octref.vetur",
"benjaminadk.emojis4git",
"fabiospampinato.vscode-todo-plus"
]

// Uncomment the next line if you want start specific services in your Docker Compose config.
Expand Down
11 changes: 5 additions & 6 deletions packages/backend/src/configuration/__mocks__/environment.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
export const config = {
admin: {
id: '1234567890123456789',
name: 'testuser#00000',
},
connectorLogLifetime: 1,
discordToken: 'xxxxxxxxxxxxxx',
discordChannel: 'xxxxxxxxxxxxxx',
env: 'test',
jwt: {
secret: 'secret',
expiresIn: '6h',
},
mongo: {
host: 'mongodb://localhost:27017/fmdb',
port: 27017
},
mongooseDebug: true,
port: 4040,
moodle: {
baseURL: 'https://moodle.example.com',
fetchInterval: '12',
reminderTimeLeft: 86400,
token: 'MOODLETOKEN123',
useCourseShortname: true,
userId: 123456
},
port: 8080,
registrationTokenLifetime: 123,
rp: {
name: 'Unit Test',
id: 'localhost',
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/configuration/logger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import log4js from 'log4js';
import {config} from './environment';
import { config } from './environment';

const configLogger = {
appenders: {
Expand Down
2 changes: 0 additions & 2 deletions packages/backend/src/controllers/connectors/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export { connectorService } from './service';

export enum ConnectorLogType {
Info = 'info',
Warning = 'warning',
Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/controllers/connectors/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ConnectorLogger {
}

/**
* Prints and stores a info message
* Prints and stores an info message
*
* @param message message that needs to be stored
* @param objectId objectId of the connector
Expand Down Expand Up @@ -53,7 +53,7 @@ class ConnectorLogger {
}

/**
* Prints and stores a error message
* Prints and stores an error message
*
* @param message message that needs to be stored
* @param objectId objectId of the connector
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
import { IConnectorDocument } from '../schemas/connector.schema';
import { IConnectorLogItemDocument } from '../schemas/connectorLogItem.schema';
import { ConnectorLogItem, IConnectorLogItemDocument } from '../schemas/connectorLogItem.schema';

export abstract class ConnectorPlugin {

protected abstract document: IConnectorDocument;

public abstract send(message: string): void;
public abstract getLogs(limit: number): Promise<IConnectorLogItemDocument[]>;
public abstract update(body: { [key: string]: any }): Promise<IConnectorDocument>;
public abstract get objectId(): string;
public abstract get courses(): number[];
public abstract get isDefault(): boolean;

/**
* Returns an array of the newest log items of this connector.
* The amount of items can be limited by parameter. Default is 50.
*
* @param {number} [limit=50] Set a limit to the amount of items
* @return {Promise<IConnectorLogItemDocument[]>} Array of ConnectorLogItemDocuments
* @memberof ConnectorPlugin
*/
public async getLogs(limit: number = 50): Promise<IConnectorLogItemDocument[]> {
const query = {
connector: this.objectId
};
return await ConnectorLogItem.find(query).sort({ createdAt: -1 }).limit(limit);
}

/**
* Returns the mongoDb objectId, this connector is build on.
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
*
* @readonly
* @type {string}
* @memberof ConnectorPlugin
*/
public get objectId(): string { return this.document.id; }

/**
* Returns all courses, that are assigned to this bot.
*
* @readonly
* @type {{ [key: string]: string; }[]}
* @memberof ConnectorPlugin
*/
public get courses(): number[] {
return this.document.courses;
}

/**
* Returns true, if this plugin is an default handler for not
* assigned courses.
*
* @readonly
* @type {boolean}
* @memberof ConnectorPlugin
*/
public get isDefault(): boolean {
return this.document.default;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Discord, { TextChannel } from 'discord.js';
import { config } from '../../../configuration/environment';
import { IConnectorDocument } from '../schemas/connector.schema';
import { ConnectorLogItem, IConnectorLogItemDocument } from '../schemas/connectorLogItem.schema';
import { connectorLogger } from '../logger';
import { ConnectorPlugin } from './connectorPlugin.class';
import { object, ObjectSchema, string } from '@hapi/joi';
Expand All @@ -19,7 +18,7 @@ export class DiscordBotConnectorPlugin extends ConnectorPlugin {
* @param {IConnectorDocument} document mongoose document
* @memberof DiscordBotConnectorPlugin
*/
constructor(private document: IConnectorDocument) {
constructor(protected document: IConnectorDocument) {
super();

this.setUpListeners();
Expand All @@ -46,21 +45,6 @@ export class DiscordBotConnectorPlugin extends ConnectorPlugin {
});
}

/**
* Returns an array of the newest log items of this bot.
* The amount of items can be limited by parameter. Default is 50.
*
* @param {number} [limit=50] Set a limit to the amount of items
* @return {Promise<IConnectorLogItemDocument[]>} Array of ConnectorLogItemDocuments
* @memberof DiscordBotConnectorPlugin
*/
public async getLogs(limit: number = 50): Promise<IConnectorLogItemDocument[]> {
const query = {
connector: this.objectId
};
return await ConnectorLogItem.find(query).sort({ createdAt: -1 }).limit(limit);
}

/**
* Sends the given message to the discord channel
*
Expand Down Expand Up @@ -100,35 +84,4 @@ export class DiscordBotConnectorPlugin extends ConnectorPlugin {

return result;
}

/**
* Returns the mongoDb objectId, this plugin is build on.
*
* @readonly
* @type {string}
* @memberof DiscordBotConnectorPlugin
*/
public get objectId(): string { return this.document.id; }

/**
* Returns all courses, that are assigned to this bot.
*
* @readonly
* @type {{ [key: string]: string; }[]}
* @memberof DiscordBotConnectorPlugin
*/
public get courses(): number[] {
return this.document.courses;
}

/**
* Returns true, if the bot is a default handler for unassigned courses.
*
* @readonly
* @type {boolean}
* @memberof DiscordBotConnectorPlugin
*/
public get isDefault(): boolean {
return this.document.default;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ export interface IConnectorLogItemDocument extends Document {
type: ConnectorType;
}

// TODO: Add expire date to envvar!
const connectorLogSchema = new Schema({
const connectorLogItemSchema = new Schema({
connector: { type: Schema.Types.ObjectId, ref: 'Connector', required: true },
createdAt: { type: Date, default: Date.now, expires: config.connectorLogLifetime, },
message: { type: String, required: true },
type: { type: ConnectorLogType, required: true },
});

export const ConnectorLogItem: Model<IConnectorLogItemDocument> = model<IConnectorLogItemDocument>('connectorlog', connectorLogSchema);
export const ConnectorLogItem: Model<IConnectorLogItemDocument> = model<IConnectorLogItemDocument>('connectorlog', connectorLogItemSchema);
2 changes: 1 addition & 1 deletion packages/backend/src/controllers/connectors/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class ConnectorService {

/**
* Updates a selected connector
*
*
* @throws ApiError
* @param {string} connectorId objectId of the connector
* @param {[key: string]: any} body body of http request
Expand Down
81 changes: 81 additions & 0 deletions packages/backend/tests/connectors/logger.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { loggerFile } from '../../src/configuration/logger';
import { connectorLogger } from '../../src/controllers/connectors/logger';
import { ConnectorLogItem } from '../../src/controllers/connectors/schemas/connectorLogItem.schema';

jest.mock('../../src/configuration/environment.ts');
jest.mock('../../src/controllers/connectors/schemas/connectorLogItem.schema');

describe('connectors/logger.ts info()', () => {
let spyLogger: jest.SpyInstance;
const message = "Test";

beforeEach(() => {
spyLogger = jest.spyOn(loggerFile,'info');
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
});

afterEach(() => {
jest.clearAllMocks();
});

it('should save message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.info(message, "123");
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).toHaveBeenCalled();
});

it('should skip to save the message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.info(message, "123", true);
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).not.toHaveBeenCalled();
});
});

describe('connectors/logger.ts warn()', () => {
let spyLogger: jest.SpyInstance;
const message = "Test";

beforeEach(() => {
spyLogger = jest.spyOn(loggerFile,'warn');
});

afterEach(() => {
jest.clearAllMocks();
});

it('should save message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.warn(message, "123");
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).toHaveBeenCalled();
});

it('should skip to save the message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.warn(message, "123", true);
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).not.toHaveBeenCalled();
});
});

describe('connectors/logger.ts error()', () => {
let spyLogger: jest.SpyInstance;
const message = "Test";

beforeEach(() => {
spyLogger = jest.spyOn(loggerFile,'error');
});

afterEach(() => {
jest.clearAllMocks();
});

it('should save message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.error(message, "123");
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).toHaveBeenCalled();
});

it('should skip to save the message to logs', () => {
antonplagemann marked this conversation as resolved.
Show resolved Hide resolved
connectorLogger.error(message, "123", true);
expect(spyLogger).toHaveBeenCalledWith(message);
expect(ConnectorLogItem).not.toHaveBeenCalled();
});
});
2 changes: 2 additions & 0 deletions packages/backend/tests/moodle.handle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('moodle/handle.ts handleAssignments', () => {
it('should only print assignments newer than the last fetch timestamp', async () => {
// expected are the Courses with course.assignments[0].timemodified > 1000
const expectedParameters = [
undefined,
new AssignmentMessage(),
{
"course": "C2",
Expand Down Expand Up @@ -82,6 +83,7 @@ describe('moodle/handle.ts handleResources', () => {

it('should only print resources newer than the last fetch timestamp', async () => {
const expectedParameters = [
undefined,
new ResourceMessage(),
{
course: 'Course02',
Expand Down
1 change: 0 additions & 1 deletion packages/backend/tests/moodle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { ICourseDetails } from '../src/controllers/moodle/interfaces/coursedetai

jest.mock('../src/configuration/environment.ts');
jest.mock('../src/controllers/moodle/fetch.ts');
jest.mock('../src/controllers/connectors/plugins/discordBot.ts');

jest.useFakeTimers();

Expand Down