Skip to content

Commit

Permalink
Merge pull request #4 from mohammadhb/master
Browse files Browse the repository at this point in the history
Master
  • Loading branch information
mohammadhb authored Apr 27, 2021
2 parents 8439c05 + 7b0d340 commit d95ba29
Show file tree
Hide file tree
Showing 53 changed files with 5,223 additions and 1,008 deletions.
57 changes: 57 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Environment
NODE_ENV=dev

# Services

## Messenger
MESSENGER_BOT_VERIFICATION_TOKEN=
MESSENGER_BOT_ACCESS_TOKEN=

## Weather
WEATHER_SERVICE_API_KEY=57b1fa5fa18a4939a1a215628211204


# Persistant Database Selection (POSTGRESQL,MONGODB) [Default:MONGODB]
DATABASE=MONGODB

## Postgresql Normal
POSTGRESQL_DATABASE_NAME=
POSTGRESQL_DATABASE_HOST=localhost
POSTGRESQL_DATABASE_PORT=
POSTGRESQL_DATABASE_USER=
POSTGRESQL_DATABASE_PASS=

## Postgresql Test
POSTGRESQL_TEST_DATABASE_NAME=
POSTGRESQL_TEST_DATABASE_HOST=localhost
POSTGRESQL_TEST_DATABASE_PORT=
POSTGRESQL_TEST_DATABASE_USER=
POSTGRESQL_TEST_DATABASE_PASS=

## MongoDB Normal
MONGODB_DATABASE_NAME=
MONGODB_DATABASE_HOST=localhost
MONGODB_DATABASE_PORT=27017
MONGODB_DATABASE_USER=
MONGODB_DATABASE_PASS=

## MongoDB Test
MONGODB_TEST_DATABASE_NAME=
MONGODB_TEST_DATABASE_HOST=localhost
MONGODB_TEST_DATABASE_PORT=27017
MONGODB_TEST_DATABASE_USER=
MONGODB_TEST_DATABASE_PASS=

## Redis
REDIS_TEST_DATABASE_NAME=
REDIS_TEST_DATABASE_HOST=localhost
REDIS_TEST_DATABASE_PORT=6379
REDIS_TEST_DATABASE_USER=
REDIS_TEST_DATABASE_PASS=

## Redis Test
REDIS_DATABASE_NAME=
REDIS_DATABASE_HOST=localhost
REDIS_DATABASE_PORT=6379
REDIS_DATABASE_USER=
REDIS_DATABASE_PASS=
86 changes: 83 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,100 @@

<img alt="Sample demo of The Messenger Bot" src="./example.gif" width="270" height="480">

## Table of Contents

- [Introduction](#introduction)
- [Technical Features](#technical-features)
- [Directory Layout](#directory-layout)
- [Getting Started](#getting-started)
- [Building a Service](#building-a-service)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Tests](#tests)
- [Documents](#documents)

### Introduction:

### Technical Features:

Here are addential **Key Technical Features** implemented into this project.
- [x] Repository Pattern : Implemented a single integrated DAO API that is exposed to serve the different perpose of operating on data.
- [x] Service Discovery Pattern and Being Service-Based : This Bot is based on a variety of Services that is Implemented in this platform by default ( e.g. Register, Weather). Also developer can add Any Services with minimum effort by just Adding the config and their service-plugin into the Service section.
- [x] Caching Data : For performance perposes, I used Redis to cache the data it became much more faster with caching methods ( From 100ms to 4ms On my Personal System )
- [x] Automatic Database Configuration Selection : You can select your own Database you just need to change the **DATABASE** variable in **.env** and you're good to go!

## Directory Layout

```
root
├── config # Configurations
├── constants # Constant Variables
├── controllers # Router Controllers
├── repository # DAO Repository
├── middlewares # Express middlewares
├── databases # Database Core
| |── mongodb # Mongoose for Mongo DB
| |── postgresql # Sequelize for Postgresql
| └── redis # Redis Client for Caching
├── router # Routes and Router
| |──conversation # Facebook Webhooks routes
| └── message # Messages routes
├── requests # Third party libraries/services
├── services # Service Discovery and Services
| |── user # User Service
| |── weather # Weather Service
| └── example # An Example Service to be added by you
├── tests # Tests
└── utils # Utility and Handy Functions
```

### Getting Started:

To get the project running first start to clone the project and then follow the instructions :
1. install the requirements ([Installation](#installation))
2. Configure the project ([Configuration](#configuration))
3. Integrate and Develop any Services you need* ([Building a Service](#building-a-service))
4. Run the Project ([Usage](#usage))
5. For any more information about End-Points Checkout here* ([Documents](#documents))

*Optional Instruction

### Building a Service:

### Installation:

- Install required packages
```shell script
npm i
```

### Configuration

- Copy and modify .env file for Environment Variables
```shell script
cp .env.example .env
```

### Configuration
- Put the Access Token in the `MESSENGER_BOT_ACCESS_TOKEN` in `.env` file
- Put the Verify Token in the `MESSENGER_BOT_VERIFY_TOKEN` in `.env` file
- Configuration Table in `.env` File :

1. Messenger Configurations
Configuration Key | Description
----------------- | -----------
`MESSENGER_BOT_VERIFICATION_TOKEN` | Verification token -> Messenger bot settings on Facebook when Verifying URL callback
`MESSENGER_BOT_ACCESS_TOKEN` | Access token -> Messenger bot settings on Facebook when Generating Access Token

1. Database Configurations
Configuration Key | Description
----------------- | -----------
`DATABASE` | Database Type -> You can select either `MONGODB` or `POSTGRESQL` but anything else would endup on `MONGODB`
`POSTGRESQL_DATABASE_NAME` | Database Name -> The database you are connecting to
`POSTGRESQL_DATABASE_HOST` | Database Host -> The IP or name of the host that database is on it
`POSTGRESQL_DATABASE_PORT` | Database Port -> Database Port
`POSTGRESQL_DATABASE_USER` | Database Username -> Database Username
`POSTGRESQL_DATABASE_PASS` | Database Password -> Database Password

DATABASE

### Usage

Expand Down
3 changes: 3 additions & 0 deletions config/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
node_env: process.env.NODE_ENV,
};
79 changes: 79 additions & 0 deletions config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const { node_env } = require("./common");
const database = process.env.DATABASE;

const options = {
useCreateIndex: true,
useNewUrlParser: true,
useFindAndModify: true,
useUnifiedTopology: true,
};

const mongodbConfig =
node_env === "test"
? {
database: process.env.MONGODB_TEST_DATABASE_NAME,
host: process.env.MONGODB_TEST_DATABASE_HOST,
port: process.env.MONGODB_TEST_DATABASE_PORT | 27017,
username: process.env.MONGODB_TEST_DATABASE_USER,
password: process.env.MONGODB_TEST_DATABASE_PASS,
dialect: "mongodb",
options,
}
: {
database: process.env.MONGODB_DATABASE_NAME,
host: process.env.MONGODB_DATABASE_HOST,
port: process.env.MONGODB_DATABASE_PORT | 27017,
username: process.env.MONGODB_DATABASE_USER,
password: process.env.MONGODB_DATABASE_PASS,
dialect: "mongodb",
options,
};

const postgresqlConfig =
node_env === "test"
? {
database: process.env.POSTGRESQL_TEST_DATABASE_NAME,
host: process.env.POSTGRESQL_TEST_DATABASE_HOST,
port: process.env.POSTGRESQL_TEST_DATABASE_PORT | 5432,
username: process.env.POSTGRESQL_TEST_DATABASE_USER,
password: process.env.POSTGRESQL_TEST_DATABASE_PASS,
dialect: "postgres",
options: {},
}
: {
database: process.env.POSTGRESQL_DATABASE_NAME,
host: process.env.POSTGRESQL_DATABASE_HOST,
port: process.env.POSTGRESQL_DATABASE_PORT | 5432,
username: process.env.POSTGRESQL_DATABASE_USER,
password: process.env.POSTGRESQL_DATABASE_PASS,
dialect: "postgres",
options: {},
};

const redisConfig =
node_env === "test"
?{
database: "cacher",
host: process.env.REDIS_TEST_DATABASE_HOST,
username: process.env.REDIS_TEST_DATABASE_USER,
password: process.env.REDIS_TEST_DATABASE_PASS,
dialect: "redis",
options: {},
}:{
database: "cacher",
host: process.env.REDIS_DATABASE_HOST,
username: process.env.REDIS_DATABASE_USER,
password: process.env.REDIS_DATABASE_PASS,
dialect: "redis",
options: {},
};

console.log(process.env.DATABASE);

module.exports = {
database,
config: {
temporary: redisConfig,
persistant: database === "POSTGRESQL" ? postgresqlConfig : mongodbConfig,
},
};
5 changes: 5 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
database: require("./database"),
common: require("./common"),
request: require("./request")
};
21 changes: 21 additions & 0 deletions config/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
exports.messenger = {
config: {
baseURL: "https://graph.facebook.com/v7.0",
headers: {
"Content-Type": "application/json",
},
responseType: "json",
},
access_token: process.env.MESSENGER_BOT_ACCESS_TOKEN,
};

exports.weather = {
config: {
baseURL: "https://api.weatherapi.com/v1",
headers: {
"Content-Type": "application/json",
},
responseType: "json",
},
api_key: process.env.WEATHER_SERVICE_API_KEY,
};
2 changes: 2 additions & 0 deletions constants/bot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exports.VERIFICATION_TOKEN = process.env.MESSENGER_BOT_VERIFICATION_TOKEN;
exports.ACESS_TOKEN = process.env.MESSENGER_BOT_ACESS_TOKEN;
4 changes: 4 additions & 0 deletions constants/cache_keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
MESSAGE:"MESSAGE",
USER:"USER",
};
85 changes: 85 additions & 0 deletions constants/http_codes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Informational
*/
exports.HTTP_CONTINUE = 100;
exports.HTTP_SWITCHING_PROTOCOLS = 101;
exports.HTTP_PROCESSING = 102; // RFC2518

/**
* Success
*/
exports.HTTP_OK = 200;
exports.HTTP_CREATED = 201;
exports.HTTP_ACCEPTED = 202;
exports.HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
exports.HTTP_NO_CONTENT = 204;
exports.HTTP_RESET_CONTENT = 205;
exports.HTTP_PARTIAL_CONTENT = 206;
exports.HTTP_MULTI_STATUS = 207; // RFC4918
exports.HTTP_ALREADY_REPORTED = 208; // RFC5842
exports.HTTP_IM_USED = 226; // RFC3229

/**
* Redirection
*/
exports.HTTP_MULTIPLE_CHOICES = 300;
exports.HTTP_MOVED_PERMANENTLY = 301;
exports.HTTP_FOUND = 302;
exports.HTTP_SEE_OTHER = 303;
exports.HTTP_NOT_MODIFIED = 304;
exports.HTTP_USE_PROXY = 305;
exports.HTTP_RESERVED = 306;
exports.HTTP_TEMPORARY_REDIRECT = 307;
exports.HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238

/**
* Client Error
*/
exports.HTTP_BAD_REQUEST = 400;
exports.HTTP_UNAUTHORIZED = 401;
exports.HTTP_PAYMENT_REQUIRED = 402;
exports.HTTP_FORBIDDEN = 403;
/**
* The requested resource could not be found
*
* Note: This is sometimes used to mask if there was an UNAUTHORIZED (401) or
* FORBIDDEN (403) error, for security reasons
*/
exports.HTTP_NOT_FOUND = 404;
exports.HTTP_METHOD_NOT_ALLOWED = 405;
exports.HTTP_NOT_ACCEPTABLE = 406;
exports.HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
exports.HTTP_REQUEST_TIMEOUT = 408;
exports.HTTP_CONFLICT = 409;
exports.HTTP_GONE = 410;
exports.HTTP_LENGTH_REQUIRED = 411;
exports.HTTP_PRECONDITION_FAILED = 412;
exports.HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
exports.HTTP_REQUEST_URI_TOO_LONG = 414;
exports.HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
exports.HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
exports.HTTP_EXPECTATION_FAILED = 417;
exports.HTTP_I_AM_A_TEAPOT = 418; // RFC2324
exports.HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918
exports.HTTP_LOCKED = 423; // RFC4918
exports.HTTP_FAILED_DEPENDENCY = 424; // RFC4918
exports.HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817
exports.HTTP_UPGRADE_REQUIRED = 426; // RFC2817
exports.HTTP_PRECONDITION_REQUIRED = 428; // RFC6585
exports.HTTP_TOO_MANY_REQUESTS = 429; // RFC6585
exports.HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585

/**
* The server encountered an unexpected error
*/
exports.HTTP_INTERNAL_SERVER_ERROR = 500;
exports.HTTP_NOT_IMPLEMENTED = 501;
exports.HTTP_BAD_GATEWAY = 502;
exports.HTTP_SERVICE_UNAVAILABLE = 503;
exports.HTTP_GATEWAY_TIMEOUT = 504;
exports.HTTP_VERSION_NOT_SUPPORTED = 505;
exports.HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295
exports.HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918
exports.HTTP_LOOP_DETECTED = 508; // RFC5842
exports.HTTP_NOT_EXTENDED = 510; // RFC2774
exports.HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
5 changes: 5 additions & 0 deletions constants/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
HTTP_CODES: require("./http_codes"),
BOT: require("./bot"),
CACHE_KEYS: require("./cache_keys"),
};
Loading

0 comments on commit d95ba29

Please sign in to comment.