Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
clvs7-gh committed Feb 13, 2019
0 parents commit 8860617
Show file tree
Hide file tree
Showing 30 changed files with 1,008 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false
90 changes: 90 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# IntelliJ
.idea

# Plugins
plugins/*
!plugins/.gitkeep

# Built files
output
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright 2019 Rec0-bot contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Rec0-bot --- A bot for revolution of comm.

## What's this?

A bot for Slack workspace. Works on Node.js.

## Requirement

Node.js >= v10. Not tested on other versions.

## How to use

Run `npm start` to start bot.

You can change configuration by setting environment variables below.

## Environment variables

- `REC0_ENV_SLACK_TOKEN` : Token for Slack RTM API.
- `REC0_ENV_SLACK_USE_MOCK` : Flag whether use mock connector or not.
- `REC0_ENV_PLUGIN_DIR_PATH` : Path for plugins directory.
- `REC0_ENV_PLUGIN_DISABLED_NAMES` : Plugin names that are excluded from running. You can specify multiple names with comma-separated.

# Plugins

Rec0-bot has simple plugin system, so you can extend functionality by plugins.

For examples, see rec0bot-plugins-* repositories.

# License

Apache License 2.0.
49 changes: 49 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "rec0-bot",
"version": "1.0.0",
"description": "A bot for revolution of comm :)",
"main": "index.js",
"scripts": {
"start": "npm run exec-ts",
"start:js": "npm run build && npm run exec",
"build": "tsc",
"exec": "node ./output/index.js",
"exec-ts": "ts-node src/index.ts",
"test": "source src/__tests__/env.sh && jest"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@slack/client": "^4.8.0",
"@types/lodash": "^4.14.120",
"cron": "^1.6.0",
"lodash": "^4.17.11",
"log4js": "^4.0.2"
},
"devDependencies": {
"@types/cron": "^1.6.0",
"@types/jest": "^24.0.3",
"jest": "^24.1.0",
"ts-jest": "^23.10.5",
"ts-lint": "^4.5.1",
"ts-node": "^8.0.2",
"typescript": "^3.3.3"
},
"jest": {
"moduleFileExtensions": [
"ts",
"js"
],
"transform": {
"^.+\\.(ts)$": "ts-jest"
},
"globals": {
"ts-jest": {
"tsConfigFile": "tsconfig.json"
}
},
"testMatch": [
"**/__tests__/**/*.test.(ts|js)"
]
}
}
Empty file added plugins/.gitkeep
Empty file.
31 changes: 31 additions & 0 deletions src/__tests__/__plugins__/mock/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Logger } from 'log4js';
import * as path from 'path';
import { BotProxy } from '../../../interface/bot-proxy.interface';

let mBot: BotProxy;
let logger: Logger;
let metadata: {[key: string]: string};

export const init = async (bot: BotProxy, options: { [key: string]: any }): Promise<void> => {
mBot = bot;
logger = options.logger || console;
metadata = await import(path.resolve(__dirname, 'package.json'));

logger.info(`${metadata.name} plugin v${metadata.version} has been initialized.`);
};

export const onStart = () => {
logger.debug('onStart()');
};

export const onStop = () => {
logger.debug('onStop()');
};

export const onMessage = (message: string, channelId: string, userId: string, data: { [key: string]: any }) => {
mBot.sendTalk(channelId, `モック:${message.split(' ').slice(1).join()}`);
};

export const onPluginEvent = (eventName: string, value?: any, fromId?: string) => {
// Nop
};
8 changes: 8 additions & 0 deletions src/__tests__/__plugins__/mock/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "mock",
"version": "1.0.0",
"description": "Mock",
"filter_prefixes": [
"mock"
]
}
31 changes: 31 additions & 0 deletions src/__tests__/__plugins__/mock2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Logger } from 'log4js';
import * as path from 'path';
import { BotProxy } from '../../../interface/bot-proxy.interface';

let mBot: BotProxy;
let logger: Logger;
let metadata: {[key: string]: string};

export const init = async (bot: BotProxy, options: { [key: string]: any }): Promise<void> => {
mBot = bot;
logger = options.logger || console;
metadata = await import(path.resolve(__dirname, 'package.json'));

logger.info(`${metadata.name} plugin v${metadata.version} has been initialized.`);
};

export const onStart = () => {
logger.debug('onStart()');
};

export const onStop = () => {
logger.debug('onStop()');
};

export const onMessage = (message: string, channelId: string, userId: string, data: { [key: string]: any }) => {
mBot.sendTalk(channelId, `モック2:${message.split(' ').slice(1).join()}`);
};

export const onPluginEvent = (eventName: string, value?: any, fromId?: string) => {
// Nop
};
8 changes: 8 additions & 0 deletions src/__tests__/__plugins__/mock2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "mock2",
"version": "1.0.0",
"description": "Mock2",
"filter_prefixes": [
"mock2"
]
}
45 changes: 45 additions & 0 deletions src/__tests__/bot-service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BotService } from '../service/bot.service';
import { MockConnectorService } from '../service/connector/mock-connector.service';

describe('Testing BotService', async () => {
const mockConnector = new MockConnectorService();
const bot = new BotService(mockConnector);
it('Init', async () => {
await bot.run();
});
it('Test plugin', async () => {
const plugins = await bot.getActivePlugins();
expect(plugins.length).toEqual(1);
expect(plugins[0].metadata.name).toEqual('mock');
});
it('Test getChannel', async () => {
expect(await bot.getChannelId('mock')).toEqual('CDUMMYCNL000');
});
it('Test onMessage', async () => {
const messageOk = 'mock test';
let isCalled = false;
const plugin = await bot.getActivePlugins()[0].instance;
const oldFn = plugin.onMessage;
plugin.onMessage = (message: string, channelId: string, userId: string, data: { [key: string]: any }) => {
expect(message).toEqual(messageOk);
isCalled = true;
};
mockConnector.emitMessage(messageOk);
await new Promise((r) => setTimeout(r, 100));
expect(isCalled).toEqual(true);
plugin.onMessage = oldFn;
});
it('Test onMessage (filtered)', async () => {
const messageNg = 'mock2 test';
let isCalled = false;
const plugin = await bot.getActivePlugins()[0].instance;
const oldFn = plugin.onMessage;
plugin.onMessage = (message: string, channelId: string, userId: string, data: { [key: string]: any }) => {
isCalled = true;
};
mockConnector.emitMessage(messageNg);
await new Promise((r) => setTimeout(r, 100));
expect(isCalled).toEqual(false);
plugin.onMessage = oldFn;
});
});
3 changes: 3 additions & 0 deletions src/__tests__/env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
export REC0_ENV_PLUGIN_DIR_PATH=./src/__tests__/__plugins__
export REC0_ENV_PLUGIN_DISABLED_NAMES=mock2
15 changes: 15 additions & 0 deletions src/environment/environment.dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as path from 'path';
import { Environment } from '../interface/environment.interface';

export const environmentDev: Environment = {
version: '1.00',
isProduction: false,
slack: {
token: (process.env.REC0_ENV_SLACK_TOKEN || '').trim(),
useMock: (process.env.REC0_ENV_SLACK_USE_MOCK || 'true').trim().toLowerCase() === 'true'
},
plugin: {
rootDir: path.resolve(process.env.REC0_ENV_PLUGIN_DIR_PATH || path.resolve(__dirname, '../../plugins')),
disabledPluginNames: (process.env.REC0_ENV_PLUGIN_DISABLED_NAMES || '').split(',').map((n) => n.trim()) || []
}
};
15 changes: 15 additions & 0 deletions src/environment/environment.prod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as path from 'path';
import { Environment } from '../interface/environment.interface';

export const environmentProd: Environment = {
version: '1.00',
isProduction: true,
slack: {
token: (process.env.REC0_ENV_SLACK_TOKEN || '').trim(),
useMock: (process.env.REC0_ENV_SLACK_USE_MOCK || 'false').trim().toLowerCase() === 'true'
},
plugin: {
rootDir: path.resolve(process.env.REC0_ENV_PLUGIN_DIR_PATH || path.resolve(__dirname, '../../plugins')),
disabledPluginNames: (process.env.REC0_ENV_PLUGIN_DISABLED_NAMES || '').split(',').map((n) => n.trim()) || []
}
};
5 changes: 5 additions & 0 deletions src/environment/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Environment } from '../interface/environment.interface';
import { environmentDev } from './environment.dev';
import { environmentProd } from './environment.prod';

export const environment: Environment = (process.env.NODE_ENV === 'production') ? environmentProd : environmentDev;
18 changes: 18 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { environment } from './environment/environment';
import { BotService } from './service/bot.service';
import { MockConnectorService } from './service/connector/mock-connector.service';
import { SlackConnectorService } from './service/connector/slack-connector.service';
import { LoggerService } from './service/logger.service';

async function main() {
const logger = LoggerService.getLogger('Launcher');
logger.info(`REC0 Bot v${environment.version} has been started!`);
const bot = new BotService(environment.slack.useMock ? new MockConnectorService() : new SlackConnectorService(environment.slack.token));
try {
await bot.run();
} catch (e) {
logger.error(e);
}
}

main();
Loading

0 comments on commit 8860617

Please sign in to comment.