├── .node-version ├── .prettierignore ├── test ├── blacklisted_users.txt └── test.ts ├── .prettierrc ├── .vscode └── settings.json ├── .gitignore ├── .mocharc.json ├── .npmignore ├── .github ├── dependabot.yml ├── workflows │ ├── npm-audit.yml │ ├── npm-audit-fix.yml │ ├── test.yml │ ├── coverage.yml │ └── linting.yml └── FUNDING.yml ├── .nycrc ├── .editorconfig ├── tsconfig.test.json ├── docs ├── BlacklistedException.java └── BlacklistChecker.java ├── tsconfig.json ├── LICENSE ├── eslint.config.mjs ├── package.json ├── src └── app.ts ├── README.md └── CHANGELOG.md /.node-version: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | -------------------------------------------------------------------------------- /test/blacklisted_users.txt: -------------------------------------------------------------------------------- 1 | 123 2 | 123456 3 | abc 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnPaste": true, 3 | "editor.formatOnSave": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | build/ 4 | dist/ 5 | npm-debug.log 6 | *.txt 7 | *.log 8 | coverage/ 9 | .nyc_output/ 10 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ["ts"], 3 | "spec": "test/**/*.ts", 4 | "require": "ts-node/register", 5 | "exit": true 6 | } 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | node_modules 3 | build 4 | npm-debug.log 5 | *.txt 6 | *.log 7 | coverage 8 | tsconfig.json 9 | .eslintrc.js 10 | CHANGELOG.md 11 | tsconfig.test.json 12 | test 13 | docs 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'npm' 4 | directory: '/' 5 | schedule: 6 | interval: 'daily' 7 | - package-ecosystem: 'github-actions' 8 | directory: '/' 9 | schedule: 10 | interval: 'daily' 11 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src/**/*.ts" 4 | ], 5 | "extension": [ 6 | ".ts" 7 | ], 8 | "require": [ 9 | "ts-node/register" 10 | ], 11 | "reporter": [ 12 | "text-summary" 13 | ], 14 | "sourceMap": true, 15 | "instrument": true 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/npm-audit.yml: -------------------------------------------------------------------------------- 1 | name: Run a security audit 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v5.0.1 15 | 16 | - uses: actions/setup-node@v6.1.0 17 | with: 18 | node-version: 18 19 | 20 | - run: npm audit 21 | -------------------------------------------------------------------------------- /.github/workflows/npm-audit-fix.yml: -------------------------------------------------------------------------------- 1 | name: npm audit fix 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | npm-audit-fix: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | steps: 15 | - uses: actions/checkout@v5.0.1 16 | 17 | - uses: ybiquitous/npm-audit-fix-action@v7.3.3 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 4 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | 17 | [package.json] 18 | indent_size = 2 19 | 20 | [*.yml] 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "module": "commonjs", 5 | "noImplicitAny": true, 6 | "noImplicitReturns": false, 7 | "noImplicitThis": true, 8 | "strictNullChecks": true, 9 | "outDir": "dist", 10 | "removeComments": true, 11 | "target": "ES2023", 12 | "lib": ["DOM", "ES2023"] 13 | }, 14 | "include": ["src/*.ts", "test/*.ts"] 15 | } 16 | -------------------------------------------------------------------------------- /docs/BlacklistedException.java: -------------------------------------------------------------------------------- 1 | package your.package; 2 | 3 | public class BlacklistedException extends Exception { 4 | public BlacklistedException() { 5 | super(); 6 | } 7 | 8 | public BlacklistedException(String message) { 9 | super(message); 10 | } 11 | 12 | public BlacklistedException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public BlacklistedException(Throwable cause) { 17 | super(cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "module": "commonjs", 5 | "noImplicitAny": true, 6 | "noImplicitReturns": false, 7 | "strictNullChecks": true, 8 | "noImplicitThis": true, 9 | "noFallthroughCasesInSwitch": true, 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "outDir": "dist", 13 | "removeComments": true, 14 | "target": "ES2023", 15 | "lib": ["DOM", "ES2023"] 16 | }, 17 | "include": ["src/*.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Run the testsuite 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ubuntu-latest, windows-latest, macos-latest] 15 | 16 | steps: 17 | - uses: actions/checkout@v5.0.1 18 | 19 | - uses: actions/setup-node@v6.1.0 20 | with: 21 | node-version: 18 22 | 23 | - name: Environment Information 24 | run: | 25 | node --version 26 | npm --version 27 | 28 | - name: Tetsuite 29 | run: npm cit 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [timbru31] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://paypal.me/timbru/ 13 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v5.0.1 14 | 15 | - uses: actions/setup-node@v6.1.0 16 | with: 17 | node-version: 18 18 | 19 | - name: Environment Information 20 | run: | 21 | node --version 22 | npm --version 23 | 24 | - name: Setup project 25 | run: npm ci 26 | 27 | - name: Test & publish code coverage 28 | uses: paambaati/codeclimate-action@v9.0.0 29 | env: 30 | CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} 31 | with: 32 | coverageCommand: npm run coverage 33 | coverageLocations: ${{github.workspace}}/coverage/lcov.info:lcov 34 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v5.0.1 15 | 16 | - uses: actions/setup-node@v6.1.0 17 | with: 18 | node-version: 18 19 | 20 | - name: Environment Information 21 | run: | 22 | node --version 23 | npm --version 24 | 25 | - name: Linting 26 | run: | 27 | npm ci 28 | npm run lint 29 | 30 | auto-merge: 31 | runs-on: ubuntu-latest 32 | needs: build 33 | 34 | permissions: 35 | pull-requests: write 36 | contents: write 37 | 38 | steps: 39 | - name: Automatically merge dependabot upgrades 40 | uses: fastify/github-action-merge-dependabot@v3.11.2 41 | with: 42 | target: minor 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Tim Brust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import eslint from '@eslint/js'; 4 | import tseslint from 'typescript-eslint'; 5 | import eslintPluginPrettier from 'eslint-plugin-prettier/recommended'; 6 | 7 | export default tseslint.config({ 8 | files: ['**/*.ts'], 9 | extends: [ 10 | eslint.configs.recommended, 11 | ...tseslint.configs.strictTypeChecked, 12 | ...tseslint.configs.stylisticTypeChecked, 13 | eslintPluginPrettier, 14 | ], 15 | rules: { 16 | '@typescript-eslint/no-unused-vars': [ 17 | 'error', 18 | { 19 | args: 'all', 20 | argsIgnorePattern: '^_', 21 | caughtErrors: 'all', 22 | caughtErrorsIgnorePattern: '^_', 23 | destructuredArrayIgnorePattern: '^_', 24 | varsIgnorePattern: '^_', 25 | ignoreRestSiblings: true, 26 | }, 27 | ], 28 | '@typescript-eslint/restrict-template-expressions': [ 29 | 'error', 30 | { 31 | allowNumber: true, 32 | }, 33 | ], 34 | 'prettier/prettier': [ 35 | 'error', 36 | { 37 | endOfLine: 'auto', 38 | }, 39 | ], 40 | }, 41 | languageOptions: { 42 | parserOptions: { 43 | project: 'tsconfig.test.json', 44 | tsconfigDirName: import.meta.dirname, 45 | }, 46 | }, 47 | }); 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spigot-anti-piracy-backend", 3 | "version": "2.1.2", 4 | "description": "A koajs application to blacklist leaked plugins", 5 | "bin": "dist/app.js", 6 | "main": "dist/app.js", 7 | "scripts": { 8 | "coverage": "npm test && nyc report --reporter=lcov", 9 | "lint": "eslint 'src/**/*.ts' 'test/**/*.ts'", 10 | "start": "ts-node src/app.ts", 11 | "prerelease": "npm run test && rm -rf dist && tsc", 12 | "release": "standard-version -s", 13 | "test": "nyc mocha", 14 | "watch": "nodemon --exec 'ts-node' src/app.ts" 15 | }, 16 | "engines": { 17 | "node": ">=18" 18 | }, 19 | "author": "Tim Brust ", 20 | "dependencies": { 21 | "@koa/router": "^13.0.0", 22 | "koa": "^2.15.3", 23 | "koa-bodyparser": "^4.4.1", 24 | "winston": "^3.14.2" 25 | }, 26 | "devDependencies": { 27 | "@eslint/js": "^9.9.1", 28 | "@types/eslint__js": "^9.14.0", 29 | "@types/koa": "^2.15.0", 30 | "@types/koa__router": "^12.0.4", 31 | "@types/koa-bodyparser": "^4.3.12", 32 | "@types/mocha": "^10.0.7", 33 | "@types/node": "^18.19.47", 34 | "@types/supertest": "^6.0.2", 35 | "eslint-config-prettier": "^10.0.1", 36 | "eslint-plugin-prettier": "^5.2.1", 37 | "mocha": "^11.1.0", 38 | "nodemon": "^3.1.4", 39 | "nyc": "^17.0.0", 40 | "should": "^13.2.3", 41 | "standard-version": "^9.5.0", 42 | "supertest": "^7.0.0", 43 | "ts-node": "^10.9.2", 44 | "typescript": "^5.5.4", 45 | "typescript-eslint": "^8.3.0" 46 | }, 47 | "license": "MIT", 48 | "repository": "timbru31/spigot-anti-piracy-backend", 49 | "bugs": "https://github.com/timbru31/spigot-anti-piracy-backend/issues", 50 | "keywords": [ 51 | "spigot", 52 | "bukkit", 53 | "minecraft", 54 | "ban", 55 | "leak" 56 | ], 57 | "standard-version": { 58 | "scripts": { 59 | "postchangelog": "npx prettier --write CHANGELOG.md" 60 | } 61 | }, 62 | "funding": "https://github.com/sponsors/timbru31" 63 | } 64 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import * as Router from '@koa/router'; 4 | import * as Koa from 'koa'; 5 | import * as bodyParser from 'koa-bodyparser'; 6 | import { promises } from 'node:fs'; 7 | import { AddressInfo } from 'node:net'; 8 | import { join } from 'node:path'; 9 | import { createLogger, format, transports } from 'winston'; 10 | 11 | interface IRequestBody { 12 | user_id?: string; 13 | userId?: string; 14 | plugin?: string; 15 | port?: string; 16 | } 17 | 18 | export const app = new Koa(); 19 | app.proxy = Boolean(process.env.PROXY) || false; 20 | 21 | const router = new Router(); 22 | 23 | const logger = createLogger({ 24 | format: format.combine(format.timestamp(), format.splat(), format.json()), 25 | }); 26 | 27 | logger.add( 28 | new transports.File({ 29 | filename: process.env.LOG_FILE ?? join(__dirname, 'request.log'), 30 | maxFiles: 5, 31 | maxsize: 5000000, 32 | tailable: true, 33 | }), 34 | ); 35 | 36 | if (process.env.NODE_ENV !== 'test') { 37 | logger.add( 38 | new transports.Console({ 39 | format: format.simple(), 40 | }), 41 | ); 42 | } 43 | 44 | router.post('/', async (ctx, next) => { 45 | const body = ctx.request.body as IRequestBody; 46 | if (!ctx.request.body || (!body.user_id && !body.userId)) { 47 | return (ctx.status = 400); 48 | } 49 | await handleAuthRequest(ctx); 50 | 51 | await next(); 52 | }); 53 | 54 | async function handleAuthRequest(ctx: Router.RouterContext) { 55 | const request = ctx.request; 56 | const body = request.body as IRequestBody; 57 | const userId = body.user_id ?? body.userId; 58 | if (!userId) { 59 | ctx.status = 400; 60 | return; 61 | } 62 | const ip = request.ip; 63 | const blacklisted = await isUserBlacklisted(userId); 64 | const response = { 65 | blacklisted, 66 | }; 67 | if (blacklisted) { 68 | ctx.status = 401; 69 | } 70 | logger.info( 71 | 'request from %s for user %s --> blacklisted %s', 72 | ip, 73 | userId, 74 | blacklisted, 75 | { 76 | blacklisted, 77 | ip, 78 | plugin: body.plugin, 79 | port: request.headers['bukkit-server-port'] ?? body.port, 80 | userId, 81 | }, 82 | ); 83 | ctx.set('Content-Type', 'application/json'); 84 | ctx.body = JSON.stringify(response); 85 | } 86 | 87 | async function isUserBlacklisted(userId: string) { 88 | const bannedFileLocation = 89 | process.env.BLACKLISTED_USERS_FILE ?? 90 | join(__dirname, 'banned_users.txt'); 91 | try { 92 | const bannedUsersFile = await promises.readFile( 93 | bannedFileLocation, 94 | 'utf-8', 95 | ); 96 | if (!bannedUsersFile) { 97 | return false; 98 | } 99 | const bannedUsers = bannedUsersFile 100 | .toString() 101 | .match(/[^\r\n]+/g) as string[]; 102 | return bannedUsers.includes(userId); 103 | } catch { 104 | return false; 105 | } 106 | } 107 | 108 | app.use(bodyParser()); 109 | app.use(router.routes()); 110 | app.use(router.allowedMethods()); 111 | 112 | const server = app.listen(process.env.PORT ?? 3000, () => { 113 | const loggerFileLocation = 114 | process.env.LOG_FILE ?? join(__dirname, 'request.log'); 115 | const bannedFileLocation = 116 | process.env.BLACKLISTED_USERS_FILE ?? 117 | join(__dirname, 'banned_users.txt'); 118 | logger.info( 119 | 'Spigot Anti Piracy Backend listening at http://%s:%s', 120 | (server.address() as AddressInfo).address, 121 | (server.address() as AddressInfo).port, 122 | ); 123 | logger.info('Logging to %s', loggerFileLocation); 124 | logger.info('Using %s for blacklisted users', bannedFileLocation); 125 | }); 126 | -------------------------------------------------------------------------------- /test/test.ts: -------------------------------------------------------------------------------- 1 | import * as supertest from 'supertest'; 2 | 3 | import { join } from 'path'; 4 | import { app } from '../src/app'; 5 | 6 | process.env.BLACKLISTED_USERS_FILE = join(__dirname, 'blacklisted_users.txt'); 7 | process.env.NODE_ENV = 'test'; 8 | 9 | const request = supertest.agent(app.listen()); 10 | 11 | describe('Using PUT', () => { 12 | it('should return a 405 (Method not allowed)', async () => { 13 | await request.put('/').expect(405); 14 | }); 15 | }); 16 | 17 | describe('Using DELETE', () => { 18 | it('should return a 405 (Method not allowed)', async () => { 19 | await request.delete('/').expect(405); 20 | }); 21 | }); 22 | 23 | describe('Using HEAD', () => { 24 | it('should return a 405 (Method not allowed)', async () => { 25 | await request.head('/').expect(405); 26 | }); 27 | }); 28 | 29 | describe('Using GET', () => { 30 | it('should return a 405 (Method not allowed)', async () => { 31 | await request.get('/').expect(405); 32 | }); 33 | }); 34 | 35 | describe('Using PATCH', () => { 36 | it('should return a 405 (Method not allowed)', async () => { 37 | await request.patch('/').expect(405); 38 | }); 39 | }); 40 | 41 | describe('Using HEAD', () => { 42 | it('should return a 405 (Method not allowed)', async () => { 43 | await request.head('/').expect(405); 44 | }); 45 | }); 46 | 47 | describe('Using OPTIONS', () => { 48 | it('should return a 200 (OK)', async () => { 49 | await request.options('/').expect(200); 50 | }); 51 | }); 52 | 53 | describe('Using POST', () => { 54 | it('should return a 400 (Bad Request) with no parameters', async () => { 55 | await request.post('/').expect(400); 56 | }); 57 | 58 | it('should return a 400 (Bad Request) if no user id was supplied', async () => { 59 | await request.post('/').send({ foo: 'bar' }).expect(400); 60 | }); 61 | 62 | it('should return a 400 (Bad Request) for an empty user id', async () => { 63 | await request.post('/').send({ user_id: '' }).expect(400); 64 | }); 65 | 66 | it('should return a 401 (Unauthorized) for a blacklisted user id (123)', async () => { 67 | await request 68 | .post('/') 69 | .send({ user_id: '123' }) 70 | .expect(401, { 71 | blacklisted: true, 72 | }) 73 | .expect('Content-Type', /json/); 74 | }); 75 | 76 | it('should return a 401 (Unauthorized) for a blacklisted user id (abc)', async () => { 77 | await request 78 | .post('/') 79 | .send({ user_id: 'abc' }) 80 | .expect(401, { 81 | blacklisted: true, 82 | }) 83 | .expect('Content-Type', /json/); 84 | }); 85 | 86 | it('should return a 200 (OK) for a non blacklisted user id', async () => { 87 | await request 88 | .post('/') 89 | .send({ user_id: 'not-banned' }) 90 | .expect(200, { 91 | blacklisted: false, 92 | }) 93 | .expect('Content-Type', /json/); 94 | }); 95 | 96 | it('should return a 200 (OK) for a non blacklisted user id with userId payload', async () => { 97 | await request 98 | .post('/') 99 | .send({ userId: 'not-banned' }) 100 | .expect(200, { 101 | blacklisted: false, 102 | }) 103 | .expect('Content-Type', /json/); 104 | }); 105 | 106 | it('should accept application/x-www-form-urlencoded', async () => { 107 | await request 108 | .post('/') 109 | .type('form') 110 | .send({ 111 | bar: true, 112 | user_id: '123', 113 | }) 114 | .expect(401, { 115 | blacklisted: true, 116 | }) 117 | .expect('Content-Type', /json/); 118 | }); 119 | 120 | it('should return a 200 (OK) if the banned users file is not found', async () => { 121 | process.env.BLACKLISTED_USERS_FILE = `${__dirname}/not-existing.txt`; 122 | await request 123 | .post('/') 124 | .send({ user_id: '123' }) 125 | .expect(200, { 126 | blacklisted: false, 127 | }) 128 | .expect('Content-Type', /json/); 129 | }); 130 | 131 | it('should ignore other parameters', async () => { 132 | await request 133 | .post('/') 134 | .send({ 135 | example: true, 136 | foo: 'bar', 137 | user_id: '123', 138 | }) 139 | .expect(200, { 140 | blacklisted: false, 141 | }) 142 | .expect('Content-Type', /json/); 143 | }); 144 | }); 145 | 146 | describe('Defaulting to banned_users.txt', () => { 147 | it('when no process.env.BLACKLISTED_USERS_FILE is defined', async () => { 148 | delete process.env.BLACKLISTED_USERS_FILE; 149 | await request 150 | .post('/') 151 | .send({ user_id: 'foo' }) 152 | .expect(200, { 153 | blacklisted: false, 154 | }) 155 | .expect('Content-Type', /json/); 156 | }); 157 | }); 158 | -------------------------------------------------------------------------------- /docs/BlacklistChecker.java: -------------------------------------------------------------------------------- 1 | package your.package; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.net.HttpURLConnection; 8 | import java.net.MalformedURLException; 9 | import java.net.ProtocolException; 10 | import java.net.URL; 11 | import java.net.UnknownHostException; 12 | 13 | import com.google.gson.JsonElement; 14 | import com.google.gson.JsonObject; 15 | import com.google.gson.JsonParser; 16 | 17 | import org.bukkit.plugin.java.JavaPlugin; 18 | 19 | import your.package.BlacklistedException; 20 | 21 | public class BlacklistChecker { 22 | private static final int TIMEOUT = 5000; 23 | private static final int SERVER_ERROR = 500; 24 | private JavaPlugin plugin; 25 | private JsonParser parser = new JsonParser(); 26 | 27 | public BlacklistChecker(JavaPlugin plugin) { 28 | this.plugin = plugin; 29 | } 30 | 31 | public int blacklistCheck(String userId) throws BlacklistedException { 32 | // TODO: use your server host 33 | return blacklistCheck(userId, "https://your-server.host/", true); 34 | } 35 | 36 | // HTTP POST request 37 | public int blacklistCheck(String userId, String apiHost, boolean useSSL) throws BlacklistedException { 38 | // URL 39 | URL url = null; 40 | try { 41 | url = new URL(apiHost); 42 | } catch (MalformedURLException e) { 43 | disableDueToError("An error occurred, disabling ... (1)"); 44 | return -1; 45 | } 46 | 47 | // HTTPS Connection 48 | HttpURLConnection.setFollowRedirects(false); 49 | HttpURLConnection con = null; 50 | try { 51 | con = (HttpURLConnection) url.openConnection(); 52 | 53 | } catch (IOException e) { 54 | disableDueToError("An error occurred, disabling ... (2)"); 55 | return -1; 56 | } 57 | 58 | // Get user id 59 | String serverPort = String.valueOf(plugin.getServer().getPort()); 60 | JsonObject jsonObject = new JsonObject(); 61 | jsonObject.addProperty("user_id", userId); 62 | jsonObject.addProperty("port", serverPort); 63 | jsonObject.addProperty("plugin", plugin.getDescription().getFullName()); 64 | String data = jsonObject.toString(); 65 | 66 | // Make POST request 67 | try { 68 | con.setRequestMethod("POST"); 69 | } catch (ProtocolException e) { 70 | disableDueToError("An error occurred, disabling ... (3)"); 71 | return -1; 72 | } 73 | con.setRequestProperty("Content-Length", String.valueOf(data.length())); 74 | con.setRequestProperty("Content-Type", "application/json"); 75 | con.setRequestProperty("Bukkit-Server-Port", serverPort); 76 | con.setConnectTimeout(TIMEOUT); 77 | con.setReadTimeout(TIMEOUT); 78 | con.setDoOutput(true); 79 | try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { 80 | wr.write(data.getBytes("UTF-8")); 81 | wr.flush(); 82 | } catch (UnknownHostException e) { 83 | // Handle being offline nice 84 | return -1; 85 | } catch (IOException e) { 86 | if (useSSL) { 87 | // TODO: use your server host 88 | return blacklistCheck(userId, "http://your-server.host/", false); 89 | } 90 | disableDueToError("An error occurred, disabling ... (4)"); 91 | return -1; 92 | } 93 | 94 | int responseCode = 0; 95 | try { 96 | responseCode = con.getResponseCode(); 97 | } catch (IOException e) { 98 | // Handle case when server instance is down gracefully. 99 | return responseCode; 100 | } 101 | 102 | String inputLine; 103 | StringBuffer response = new StringBuffer(); 104 | if (responseCode >= SERVER_ERROR) { 105 | return responseCode; 106 | } else if (responseCode == HttpURLConnection.HTTP_OK) { 107 | try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"))) { 108 | while ((inputLine = in.readLine()) != null) { 109 | response.append(inputLine); 110 | } 111 | } catch (IOException e) { 112 | disableDueToError("An error occurred, disabling ... (5)"); 113 | return responseCode; 114 | } 115 | } else { 116 | try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getErrorStream(), "UTF-8"))) { 117 | while ((inputLine = in.readLine()) != null) { 118 | response.append(inputLine); 119 | } 120 | } catch (IOException e) { 121 | disableDueToError("An error occurred, disabling ... (6)"); 122 | return responseCode; 123 | } 124 | } 125 | boolean blacklisted = true; 126 | try { 127 | JsonElement parse = parser.parse(response.toString()); 128 | blacklisted = parse.getAsJsonObject().get("blacklisted").getAsBoolean(); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | disableDueToError("An error occurred, disabling... (7)"); 132 | return responseCode; 133 | } 134 | if (blacklisted) { 135 | disableDueToError("You are blacklisted..."); 136 | } 137 | return responseCode; 138 | } 139 | 140 | private void disableDueToError(String... messages) throws BlacklistedException { 141 | for (String message : messages) { 142 | plugin.getLogger().severe(message); 143 | } 144 | throw new BlacklistedException(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spigot-anti-piracy-backend 2 | 3 | [![Linting](https://github.com/timbru31/spigot-anti-piracy-backend/workflows/Linting/badge.svg)](https://github.com/timbru31/spigot-anti-piracy-backend/actions?query=workflow%3ALinting) 4 | [![Run a security audit](https://github.com/timbru31/spigot-anti-piracy-backend/workflows/Run%20a%20security%20audit/badge.svg)](https://github.com/timbru31/spigot-anti-piracy-backend/actions?query=workflow%3A%22Run+a+security+audit%22) 5 | [![Coverage](https://github.com/timbru31/spigot-anti-piracy-backend/workflows/Coverage/badge.svg)](https://github.com/timbru31/spigot-anti-piracy-backend/actions?query=workflow%3ACoverage) 6 | [![Run the testsuite](https://github.com/timbru31/spigot-anti-piracy-backend/workflows/Run%20the%20testsuite/badge.svg)](https://github.com/timbru31/spigot-anti-piracy-backend/actions?query=workflow%3A%22Run+the+testsuite%22) 7 | 8 | [![Test Coverage](https://codeclimate.com/github/timbru31/spigot-anti-piracy-backend/badges/coverage.svg)](https://codeclimate.com/github/timbru31/spigot-anti-piracy-backend/coverage) 9 | [![Code Climate](https://codeclimate.com/github/timbru31/spigot-anti-piracy-backend/badges/gpa.svg)](https://codeclimate.com/github/timbru31/spigot-anti-piracy-backend) 10 | [![Known Vulnerabilities](https://snyk.io/test/github/timbru31/spigot-anti-piracy-backend/badge.svg)](https://snyk.io/test/github/timbru31/spigot-anti-piracy-backend) 11 | 12 | [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](https://commitizen.github.io/cz-cli/) 13 | [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) 14 | [![npm](https://img.shields.io/npm/v/spigot-anti-piracy-backend.svg)](https://www.npmjs.com/package/spigot-anti-piracy-backend) 15 | 16 | #### A Koa.js powered Node.js backend to blacklist leaked Spigot Premium plugins 17 | 18 | ### Motivation 19 | 20 | I'm sad that such a project is existing. 21 | Since 2011 I have been providing the community with a lot of free CraftBukkit plugins. 22 | Over **one and a half million** downloads in total. That is a huge number. 23 | Nevertheless, at some points, the community is an unkind one. 24 | It does not matter how much spare time you spent working on the new version, the update was never fast enough. And complaining is always easier than saying 'thank you!'. 25 | 26 | With the premium plugin solution, Spigot offers developers a way to the get something back for their work. 27 | And in general a lot cheaper than hiring a private plugin developer. 28 | When you see your plugin on sites that offer leaked plugins just one week after the initial release, it's frustrating. 29 | 30 | That's why I decided to make my own validation service - blacklisting the leaker is often a lot faster than sending DMCA requests to One-Click-Hosters (OCH). 31 | 32 | ### Description 33 | 34 | The Spigot built in piracy protection is well-known and easy to remove. 35 | There is a way to receive the user id of the buyer in your code. 36 | Please contact me on SpigotMC, I'd prefer not to make the method not easily and publicly accessible (although it is when you dig enough). 37 | 38 | Once you retrieved the user id you can make a POST request to the URL where you service runs. 39 | In the body, include the following information: 40 | 41 | ``` 42 | user_id=foobar 43 | ``` 44 | 45 | (userId works, too) 46 | 47 | An example Java implementation can be found in [docs/](docs/). 48 | 49 | The service is only accepting POST, no GET. 50 | You receive a JSON with either blacklisted true or false: 51 | 52 | ```json 53 | { 54 | "blacklisted": true 55 | } 56 | ``` 57 | 58 | ### Installation 59 | 60 | Ensure that the server you wish to run the piracy backend with is running at least **Node.js v18 LTS** 61 | 62 | #### Normal Installation 63 | 64 | ```shell 65 | $ npm install -g spigot-anti-piracy-backend 66 | ``` 67 | 68 | (Optionally without the global flag) 69 | 70 | #### Development Installation 71 | 72 | ```shell 73 | $ git clone https://github.com/timbru31/spigot-anti-piracy-backend.git 74 | $ cd spigot-anti-piracy-backend 75 | $ npm install 76 | $ npm run watch 77 | ``` 78 | 79 | ### Usage 80 | 81 | You need to manually maintain a blacklisted users file. 82 | I'd recommend a simple text file, with one blacklisted user id per line. 83 | 84 | Just use 85 | 86 | ```shell 87 | $ npm run start 88 | ``` 89 | 90 | Configuration via environment variables 91 | 92 | | Environment Variable | Default | Description | 93 | | :--------------------- | :----------------- | :------------------------------------------------------------------- | 94 | | PORT | 3000 | Port to run the app on | 95 | | BLACKLISTED_USERS_FILE | ./banned_users.txt | Blacklist file | 96 | | LOG_FILE | ./request.log | Log file for requests | 97 | | PROXY | false | Tells Koa to run on proxy mode, for support for X-Forwarded Headers | 98 | | JSON_LOG | true | Logs to the file in a JSON format, disable for human readable output | 99 | 100 | It's up to you if you would like to start the service on startup e.g. using a linux start script. 101 | For example, below is a systemd script which runs the script as a non-privileged user. 102 | 103 | ``` 104 | [Unit] 105 | Description=Spigot Anti-Piracy Backend Server 106 | After=network.target 107 | 108 | [Service] 109 | Environment=PORT=3005 110 | Environment=BLACKLISTED_USERS_FILE=/home/example/banned_users.txt 111 | Type=simple 112 | User=example 113 | # Assuming a global installation 114 | ExecStart=spigot-anti-piracy-backend 115 | Restart=on-failure 116 | 117 | [Install] 118 | WantedBy=multi-user.target 119 | ``` 120 | 121 | ### Development 122 | 123 | You can watch the `app.ts` for file changes via the task 124 | 125 | ```shell 126 | $ npm run watch 127 | ``` 128 | 129 | It uses [Nodemon](https://nodemon.io) to watch for file changes and restarts the server if any are found. 130 | 131 | Test are run with [Mocha](https://mochajs.org) via 132 | 133 | ```shell 134 | $ npm run test 135 | ``` 136 | 137 | The code is linted using `ESLint`. 138 | Keep the warnings to zero. :smile: 139 | 140 | Please make sure they all pass and add new ones when you develop new stuff! :smile: 141 | 142 | **Please follow the commitizen style when making new commits!** 143 | 144 | ### Future 145 | 146 | Since this is a blacklist solution, the planned future is to validate the supplied user id against the buyers of the premium plugin. 147 | Only when it's on the list, the plugin is allowed to start (as long as the user is not blacklisted). 148 | 149 | The following document query can be used to retrieve an array of all user ids who bought the plugin: 150 | 151 | ```js 152 | let buyers = Array.from( 153 | document.querySelector('.memberList').querySelectorAll('a.username') 154 | ); 155 | buyers.forEach((elem, index, arr) => { 156 | arr[index] = parseInt( 157 | elem.pathname 158 | .replace(/\/members\/[-_a-zA-Z0-9]+\./, '') 159 | .replace('/', '') 160 | ); 161 | }); 162 | ``` 163 | 164 | --- 165 | 166 | Built by (c) Tim Brust and contributors. Released under the MIT license. 167 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [2.1.2](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v2.1.1...v2.1.2) (2021-01-23) 6 | 7 | ### [2.1.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v2.1.0...v2.1.1) (2020-08-01) 8 | 9 | ## [2.1.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v2.0.0...v2.1.0) (2020-04-29) 10 | 11 | ### Features 12 | 13 | - adds timestamp logging ([6abc218](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6abc2187111c2c511ff26f917c7df9c452d3a7ce)) 14 | 15 | ### Bug Fixes 16 | 17 | - checkout step ([4010996](https://github.com/timbru31/spigot-anti-piracy-backend/commit/401099600ddc263a821cb41470aa99f5f68f8fe0)) 18 | - GitHub Action ([3e3dd1d](https://github.com/timbru31/spigot-anti-piracy-backend/commit/3e3dd1d0cfaba80994487b96d8372f80f9e44383)) 19 | 20 | ## [2.0.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.2.1...v2.0.0) (2019-06-12) 21 | 22 | ### Build System 23 | 24 | - **deps:** [security] bump handlebars from 4.0.12 to 4.1.0 ([485d80f](https://github.com/timbru31/spigot-anti-piracy-backend/commit/485d80f)) 25 | - **deps:** bump winston from 3.2.0 to 3.2.1 ([ec087d0](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ec087d0)) 26 | - **deps-dev:** bump @types/koa-bodyparser from 4.2.1 to 4.2.2 ([ed8c136](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ed8c136)) 27 | - **deps-dev:** bump @types/koa-bodyparser from 4.2.2 to 4.3.0 ([742b3e5](https://github.com/timbru31/spigot-anti-piracy-backend/commit/742b3e5)) 28 | - **deps-dev:** bump @types/koa-router from 7.0.39 to 7.0.40 ([ab4b6c2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ab4b6c2)) 29 | - **deps-dev:** bump @types/mocha from 5.2.5 to 5.2.6 ([eb03ffc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/eb03ffc)) 30 | - **deps-dev:** bump @types/mocha from 5.2.6 to 5.2.7 ([4208be7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4208be7)) 31 | - **deps-dev:** bump @types/node from 10.12.18 to 10.12.19 ([f6c7f54](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f6c7f54)) 32 | - **deps-dev:** bump @types/node from 10.12.19 to 10.12.20 ([e6f460c](https://github.com/timbru31/spigot-anti-piracy-backend/commit/e6f460c)) 33 | - **deps-dev:** bump @types/node from 10.12.20 to 10.12.21 ([6a9e4d1](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6a9e4d1)) 34 | - **deps-dev:** bump @types/node from 10.12.21 to 10.12.23 ([d2833b8](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d2833b8)) 35 | - **deps-dev:** bump @types/node from 10.12.23 to 10.12.24 ([ddabfd7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ddabfd7)) 36 | - **deps-dev:** bump @types/node from 10.12.24 to 11.9.0 ([6ad3430](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6ad3430)) 37 | - **deps-dev:** bump @types/node from 10.14.5 to 10.14.6 ([84dad0a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/84dad0a)) 38 | - **deps-dev:** bump @types/node from 10.14.5 to 10.14.6 ([#311](https://github.com/timbru31/spigot-anti-piracy-backend/issues/311)) ([d410eb3](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d410eb3)) 39 | - **deps-dev:** bump @types/node from 10.14.6 to 10.14.7 ([e71c853](https://github.com/timbru31/spigot-anti-piracy-backend/commit/e71c853)) 40 | - **deps-dev:** bump @types/node from 10.14.6 to 10.14.7 ([#313](https://github.com/timbru31/spigot-anti-piracy-backend/issues/313)) ([85696f4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/85696f4)) 41 | - **deps-dev:** bump @types/node from 10.14.7 to 10.14.8 ([cca3fe0](https://github.com/timbru31/spigot-anti-piracy-backend/commit/cca3fe0)) 42 | - **deps-dev:** bump @types/node from 11.10.4 to 11.10.5 ([dad636a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/dad636a)) 43 | - **deps-dev:** bump @types/node from 11.10.5 to 11.11.0 ([6731634](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6731634)) 44 | - **deps-dev:** bump @types/node from 11.11.0 to 11.11.1 ([6583dcf](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6583dcf)) 45 | - **deps-dev:** bump @types/node from 11.11.1 to 11.11.3 ([93bc597](https://github.com/timbru31/spigot-anti-piracy-backend/commit/93bc597)) 46 | - **deps-dev:** bump @types/node from 11.11.3 to 11.11.4 ([4a88517](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4a88517)) 47 | - **deps-dev:** bump @types/node from 11.11.4 to 11.11.5 ([c8f69c4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c8f69c4)) 48 | - **deps-dev:** bump @types/node from 11.11.5 to 11.11.6 ([9b0533a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/9b0533a)) 49 | - **deps-dev:** bump @types/node from 11.11.6 to 11.11.7 ([894af85](https://github.com/timbru31/spigot-anti-piracy-backend/commit/894af85)) 50 | - **deps-dev:** bump @types/node from 11.11.7 to 11.12.0 ([76b4240](https://github.com/timbru31/spigot-anti-piracy-backend/commit/76b4240)) 51 | - **deps-dev:** bump @types/node from 11.12.0 to 11.12.1 ([d0d544d](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d0d544d)) 52 | - **deps-dev:** bump @types/node from 11.12.1 to 11.12.2 ([23c65fc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/23c65fc)) 53 | - **deps-dev:** bump @types/node from 11.12.2 to 11.13.0 ([4e891cc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4e891cc)) 54 | - **deps-dev:** bump @types/node from 11.13.0 to 11.13.2 ([ee7efa7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ee7efa7)) 55 | - **deps-dev:** bump @types/node from 11.13.2 to 11.13.4 ([cd20317](https://github.com/timbru31/spigot-anti-piracy-backend/commit/cd20317)) 56 | - **deps-dev:** bump @types/node from 11.13.4 to 11.13.5 ([89e2d51](https://github.com/timbru31/spigot-anti-piracy-backend/commit/89e2d51)) 57 | - **deps-dev:** bump @types/node from 11.13.5 to 11.13.6 ([0331691](https://github.com/timbru31/spigot-anti-piracy-backend/commit/0331691)) 58 | - **deps-dev:** bump @types/node from 11.13.6 to 11.13.7 ([b4f037c](https://github.com/timbru31/spigot-anti-piracy-backend/commit/b4f037c)) 59 | - **deps-dev:** bump @types/node from 11.9.0 to 11.9.3 ([18311f6](https://github.com/timbru31/spigot-anti-piracy-backend/commit/18311f6)) 60 | - **deps-dev:** bump @types/node from 11.9.3 to 11.9.4 ([6ccf775](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6ccf775)) 61 | - **deps-dev:** bump @types/node from 11.9.4 to 11.9.5 ([8b84b94](https://github.com/timbru31/spigot-anti-piracy-backend/commit/8b84b94)) 62 | - **deps-dev:** bump @types/node from 11.9.5 to 11.9.6 ([38718c7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/38718c7)) 63 | - **deps-dev:** bump @types/node from 11.9.6 to 11.10.4 ([13df7b4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/13df7b4)) 64 | - **deps-dev:** bump coveralls from 3.0.2 to 3.0.3 ([d4b3669](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d4b3669)) 65 | - **deps-dev:** bump coveralls from 3.0.3 to 3.0.4 ([417a2b9](https://github.com/timbru31/spigot-anti-piracy-backend/commit/417a2b9)) 66 | - **deps-dev:** bump mocha from 5.2.0 to 6.0.2 ([6292bfd](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6292bfd)) 67 | - **deps-dev:** bump mocha from 6.0.2 to 6.1.2 ([b538e1b](https://github.com/timbru31/spigot-anti-piracy-backend/commit/b538e1b)) 68 | - **deps-dev:** bump mocha from 6.1.2 to 6.1.3 ([f2878bc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f2878bc)) 69 | - **deps-dev:** bump mocha from 6.1.3 to 6.1.4 ([ff93f01](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ff93f01)) 70 | - **deps-dev:** bump nodemon from 1.18.10 to 1.18.11 ([18d30a7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/18d30a7)) 71 | - **deps-dev:** bump nodemon from 1.18.11 to 1.19.0 ([27b3ff2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/27b3ff2)) 72 | - **deps-dev:** bump nodemon from 1.18.9 to 1.18.10 ([70897f3](https://github.com/timbru31/spigot-anti-piracy-backend/commit/70897f3)) 73 | - **deps-dev:** bump nodemon from 1.19.0 to 1.19.1 ([03b89c4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/03b89c4)) 74 | - **deps-dev:** bump nyc from 13.1.0 to 13.2.0 ([6d26e89](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6d26e89)) 75 | - **deps-dev:** bump nyc from 13.2.0 to 13.3.0 ([4e794ac](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4e794ac)) 76 | - **deps-dev:** bump nyc from 13.3.0 to 14.0.0 ([50c3df1](https://github.com/timbru31/spigot-anti-piracy-backend/commit/50c3df1)) 77 | - **deps-dev:** bump nyc from 14.0.0 to 14.1.0 ([531e888](https://github.com/timbru31/spigot-anti-piracy-backend/commit/531e888)) 78 | - **deps-dev:** bump nyc from 14.1.0 to 14.1.1 ([99c0cdd](https://github.com/timbru31/spigot-anti-piracy-backend/commit/99c0cdd)) 79 | - **deps-dev:** bump standard-version from 4.4.0 to 5.0.0 ([ff6796d](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ff6796d)) 80 | - **deps-dev:** bump standard-version from 5.0.0 to 5.0.1 ([65f8dc5](https://github.com/timbru31/spigot-anti-piracy-backend/commit/65f8dc5)) 81 | - **deps-dev:** bump standard-version from 5.0.1 to 5.0.2 ([4144921](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4144921)) 82 | - **deps-dev:** bump standard-version from 5.0.2 to 6.0.1 ([19b40b2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/19b40b2)) 83 | - **deps-dev:** bump standard-version from 5.0.2 to 6.0.1 ([#310](https://github.com/timbru31/spigot-anti-piracy-backend/issues/310)) ([c6e8699](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c6e8699)) 84 | - **deps-dev:** bump supertest from 3.4.2 to 4.0.2 ([b4f8a4f](https://github.com/timbru31/spigot-anti-piracy-backend/commit/b4f8a4f)) 85 | - **deps-dev:** bump ts-node from 8.0.2 to 8.0.3 ([b476f8a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/b476f8a)) 86 | - **deps-dev:** bump ts-node from 8.0.3 to 8.1.0 ([adbacfd](https://github.com/timbru31/spigot-anti-piracy-backend/commit/adbacfd)) 87 | - **deps-dev:** bump ts-node from 8.1.0 to 8.2.0 ([1ffaa10](https://github.com/timbru31/spigot-anti-piracy-backend/commit/1ffaa10)) 88 | - **deps-dev:** bump tslint from 5.12.1 to 5.13.0 ([6f84edc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6f84edc)) 89 | - **deps-dev:** bump tslint from 5.13.0 to 5.13.1 ([c398d01](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c398d01)) 90 | - **deps-dev:** bump tslint from 5.13.1 to 5.14.0 ([03ba2a2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/03ba2a2)) 91 | - **deps-dev:** bump tslint from 5.14.0 to 5.15.0 ([c022700](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c022700)) 92 | - **deps-dev:** bump tslint from 5.15.0 to 5.16.0 ([3546e87](https://github.com/timbru31/spigot-anti-piracy-backend/commit/3546e87)) 93 | - **deps-dev:** bump tslint from 5.16.0 to 5.17.0 ([5b321e2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/5b321e2)) 94 | - **deps-dev:** bump typescript from 3.2.4 to 3.3.1 ([1c6e177](https://github.com/timbru31/spigot-anti-piracy-backend/commit/1c6e177)) 95 | - **deps-dev:** bump typescript from 3.3.1 to 3.3.3 ([a5db1dc](https://github.com/timbru31/spigot-anti-piracy-backend/commit/a5db1dc)) 96 | - **deps-dev:** bump typescript from 3.3.3 to 3.3.3333 ([6850a40](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6850a40)) 97 | - **deps-dev:** bump typescript from 3.3.3333 to 3.3.4000 ([42e7876](https://github.com/timbru31/spigot-anti-piracy-backend/commit/42e7876)) 98 | - **deps-dev:** bump typescript from 3.3.4000 to 3.4.1 ([6c4c864](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6c4c864)) 99 | - **deps-dev:** bump typescript from 3.4.1 to 3.4.2 ([81accb7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/81accb7)) 100 | - **deps-dev:** bump typescript from 3.4.2 to 3.4.3 ([2af2a4e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/2af2a4e)) 101 | - **deps-dev:** bump typescript from 3.4.3 to 3.4.4 ([0a5a710](https://github.com/timbru31/spigot-anti-piracy-backend/commit/0a5a710)) 102 | - **deps-dev:** bump typescript from 3.4.4 to 3.4.5 ([33d44f1](https://github.com/timbru31/spigot-anti-piracy-backend/commit/33d44f1)) 103 | 104 | 105 | 106 | ## [1.2.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.2.0...v1.2.1) (2019-01-28) 107 | 108 | 109 | 110 | # [1.2.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.1.0...v1.2.0) (2018-08-18) 111 | 112 | ### Features 113 | 114 | - update to winston 3.0 ([92bee05](https://github.com/timbru31/spigot-anti-piracy-backend/commit/92bee05)) 115 | 116 | 117 | 118 | # [1.1.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.0.3...v1.1.0) (2018-03-26) 119 | 120 | ### Bug Fixes 121 | 122 | - correctly split newlines ([dd8e7b0](https://github.com/timbru31/spigot-anti-piracy-backend/commit/dd8e7b0)) 123 | 124 | ### Features 125 | 126 | - allow userId payload in body ([62b8c7e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/62b8c7e)) 127 | 128 | 129 | 130 | ## [1.0.3](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.0.2...v1.0.3) (2018-03-25) 131 | 132 | ### Bug Fixes 133 | 134 | - allow cross platform usage ([e31933f](https://github.com/timbru31/spigot-anti-piracy-backend/commit/e31933f)) 135 | - lint ([63fcb28](https://github.com/timbru31/spigot-anti-piracy-backend/commit/63fcb28)) 136 | 137 | 138 | 139 | ## [1.0.2](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.0.1...v1.0.2) (2017-07-18) 140 | 141 | ### Bug Fixes 142 | 143 | - **deps:** update to koa-router[@7](https://github.com/7).2.1, fixes [#152](https://github.com/timbru31/spigot-anti-piracy-backend/issues/152) ([9e648d8](https://github.com/timbru31/spigot-anti-piracy-backend/commit/9e648d8)) 144 | - **package:** update koa-router to version 7.2.0 ([#151](https://github.com/timbru31/spigot-anti-piracy-backend/issues/151)) ([fa8d9fb](https://github.com/timbru31/spigot-anti-piracy-backend/commit/fa8d9fb)) 145 | 146 | 147 | 148 | ## [1.0.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v1.0.0...v1.0.1) (2017-03-21) 149 | 150 | ### Bug Fixes 151 | 152 | - **package:** update koa to version 2.1.0 (#140) ([9093ed2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/9093ed2)) 153 | - **package:** update koa to version 2.2.0 (#141) ([dd5a14d](https://github.com/timbru31/spigot-anti-piracy-backend/commit/dd5a14d)) 154 | - **package:** update koa-bodyparser to version 4.0.0 (#136) ([ce84b73](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ce84b73)) 155 | - **package:** update koa-bodyparser to version 4.1.0 (#137) ([3377afb](https://github.com/timbru31/spigot-anti-piracy-backend/commit/3377afb)) 156 | - **package:** update koa-bodyparser to version 4.2.0 (#143) ([18b70bb](https://github.com/timbru31/spigot-anti-piracy-backend/commit/18b70bb)) 157 | 158 | 159 | 160 | # [1.0.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.6.1...v1.0.0) (2017-02-25) 161 | 162 | ### Code Refactoring 163 | 164 | - remove Babel ([c111714](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c111714)) 165 | 166 | ### BREAKING CHANGES 167 | 168 | - required NodeJS >= 7.6 169 | 170 | 171 | 172 | ## [0.6.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.6.0...v0.6.1) (2017-02-16) 173 | 174 | ### Bug Fixes 175 | 176 | - compile src directory correctly ([120be99](https://github.com/timbru31/spigot-anti-piracy-backend/commit/120be99)) 177 | 178 | 179 | 180 | # [0.6.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.5.3...v0.6.0) (2017-02-16) 181 | 182 | ### Bug Fixes 183 | 184 | - quotes in .eslintrc ([60525bf](https://github.com/timbru31/spigot-anti-piracy-backend/commit/60525bf)) 185 | - **package:** update babel-cli to version 6.22.0 ([14d6e5e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/14d6e5e)) 186 | - **package:** update babel-core to version 6.21.0 ([abf3011](https://github.com/timbru31/spigot-anti-piracy-backend/commit/abf3011)) 187 | - **package:** update babel-core to version 6.22.1 ([85385b5](https://github.com/timbru31/spigot-anti-piracy-backend/commit/85385b5)) 188 | - **package:** update babel-core to version 6.23.1 (#132) ([cad797e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/cad797e)) 189 | - **package:** update babel-plugin-transform-async-to-generator to version 6.22.0 ([dfcbe03](https://github.com/timbru31/spigot-anti-piracy-backend/commit/dfcbe03)) 190 | - **package:** update babel-runtime to version 6.23.0 (#133) ([74523c5](https://github.com/timbru31/spigot-anti-piracy-backend/commit/74523c5)) 191 | - **package:** update koa-router to version 7.1.0 ([a6db85e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/a6db85e)) 192 | 193 | ### Features 194 | 195 | - log port from body and plugin name ([01439e4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/01439e4)) 196 | 197 | 198 | 199 | ## [0.5.4](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.5.3...v0.5.4) (2016-11-25) 200 | 201 | ### chore 202 | 203 | - bump version ([d43b6111e5c3304901328c51dc604cb0132e912c](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d43b6111e5c3304901328c51dc604cb0132e912c)) 204 | - test up to Node v7 ([6fcfd911a40d7c73f81beeb0a8b13da43f355f53](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6fcfd911a40d7c73f81beeb0a8b13da43f355f53)) 205 | - update dependencies ([c96a42b69cf518d5991fef54b0bd345e63447c31](https://github.com/timbru31/spigot-anti-piracy-backend/commit/c96a42b69cf518d5991fef54b0bd345e63447c31)) 206 | 207 | ### fix 208 | 209 | - quotes in .eslintrc ([60525bf0a769b85c4578fae2bb89159cf0667d35](https://github.com/timbru31/spigot-anti-piracy-backend/commit/60525bf0a769b85c4578fae2bb89159cf0667d35)) 210 | 211 | 212 | 213 | ## [0.5.3](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.5.2...v0.5.3) (2016-10-07) 214 | 215 | ### chore 216 | 217 | - release 0.5.3 ([23234687b5aec36ac262e65bfbbcb398e1ccbeae](https://github.com/timbru31/spigot-anti-piracy-backend/commit/23234687b5aec36ac262e65bfbbcb398e1ccbeae)) 218 | - updated dependencies ([1e814c022798168974bfb7278f381023920dd918](https://github.com/timbru31/spigot-anti-piracy-backend/commit/1e814c022798168974bfb7278f381023920dd918)) 219 | - updated dependencies ([17578633ec5b3cbfdd9674180a55cfee9989de69](https://github.com/timbru31/spigot-anti-piracy-backend/commit/17578633ec5b3cbfdd9674180a55cfee9989de69)) 220 | 221 | ### docs 222 | 223 | - add license badge ([8f8b92b5cbb77daf46c3d9e2dd09762a01f2f7b7](https://github.com/timbru31/spigot-anti-piracy-backend/commit/8f8b92b5cbb77daf46c3d9e2dd09762a01f2f7b7)) 224 | 225 | 226 | 227 | ## [0.5.2](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.5.1...v0.5.2) (2016-05-29) 228 | 229 | ### chore 230 | 231 | - add conventional-changelog-cli dependency ([0faa79e5100812b19cade879679c950afe8cdfd4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/0faa79e5100812b19cade879679c950afe8cdfd4)) 232 | - release 0.5.2 ([6fa2e2aae906da70908249c1cfcf1280a1c13160](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6fa2e2aae906da70908249c1cfcf1280a1c13160)) 233 | 234 | ### docs 235 | 236 | - add CHANGELOG.md ([39e160f90c85651630792053cbe72dff6201a10b](https://github.com/timbru31/spigot-anti-piracy-backend/commit/39e160f90c85651630792053cbe72dff6201a10b)) 237 | 238 | ### feat 239 | 240 | - log server port if set in headers ([d1aa179f26e1e7cac5e9f8697cde47d4f367c34e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d1aa179f26e1e7cac5e9f8697cde47d4f367c34e)) 241 | 242 | 243 | 244 | ## [0.5.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.5.0...v0.5.1) (2016-05-25) 245 | 246 | ### chore 247 | 248 | - tets against Node 6, too ([bca1c47fd61af355a6c77817de7b301d109f77f8](https://github.com/timbru31/spigot-anti-piracy-backend/commit/bca1c47fd61af355a6c77817de7b301d109f77f8)) 249 | - update dependencies ([8dde026e140188a430f61d0d5abfe2b6e1738b81](https://github.com/timbru31/spigot-anti-piracy-backend/commit/8dde026e140188a430f61d0d5abfe2b6e1738b81)) 250 | - updated babel-eslint ([fb09519c944a03256923a93a3a5b9caccde8ae61](https://github.com/timbru31/spigot-anti-piracy-backend/commit/fb09519c944a03256923a93a3a5b9caccde8ae61)) 251 | - updated depndencies ([a0605c8e588ce8d21dff00f95471905e5a1dc718](https://github.com/timbru31/spigot-anti-piracy-backend/commit/a0605c8e588ce8d21dff00f95471905e5a1dc718)) 252 | 253 | ### fix 254 | 255 | - typo in log message ([ba83e4aac6ceeb30789b9731f47cb772d79c04c6](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ba83e4aac6ceeb30789b9731f47cb772d79c04c6)) 256 | 257 | 258 | 259 | # [0.5.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.4.2...v0.5.0) (2016-03-30) 260 | 261 | ### chore 262 | 263 | - updated koa.js to 2.0.0 ([87dd36d33a69eb6a2f1d23d68f5c90e7960fc6a3](https://github.com/timbru31/spigot-anti-piracy-backend/commit/87dd36d33a69eb6a2f1d23d68f5c90e7960fc6a3)) 264 | 265 | ### docs 266 | 267 | - updated README with new setup instructions for upstart ([14b7cd072bbfca0ba8c66268d82dbe5024d45998](https://github.com/timbru31/spigot-anti-piracy-backend/commit/14b7cd072bbfca0ba8c66268d82dbe5024d45998)) 268 | 269 | ### feat 270 | 271 | - make JSON log of winston configurable ([9beb890843e7ae9b2b4669bcd2b3b706070f5045](https://github.com/timbru31/spigot-anti-piracy-backend/commit/9beb890843e7ae9b2b4669bcd2b3b706070f5045)) 272 | 273 | 274 | 275 | ## [0.4.2](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.4.1...v0.4.2) (2016-03-26) 276 | 277 | ### fix 278 | 279 | - installation via npm ([ae3626f4b860f6ebe869d601267ac7404c304493](https://github.com/timbru31/spigot-anti-piracy-backend/commit/ae3626f4b860f6ebe869d601267ac7404c304493)) 280 | 281 | 282 | 283 | ## [0.4.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.4.0...v0.4.1) (2016-03-26) 284 | 285 | ### docs 286 | 287 | - updated installation instructions ([f371a98e63c675de7bd3ea17d584405392a1e0ef](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f371a98e63c675de7bd3ea17d584405392a1e0ef)) 288 | 289 | 290 | 291 | # [0.4.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.3.1...v0.4.0) (2016-03-26) 292 | 293 | ### chore 294 | 295 | - update dependencies ([e125445fa6c704d1c91aef675da6ccc535956066](https://github.com/timbru31/spigot-anti-piracy-backend/commit/e125445fa6c704d1c91aef675da6ccc535956066)) 296 | 297 | ### fix 298 | 299 | - fix tests by removing babel polyfill and installing babel runtime ([f58c67e8f953ae5797b7226aaa8e93e5b9accf9a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f58c67e8f953ae5797b7226aaa8e93e5b9accf9a)) 300 | - typo in response ([d0ec252906d9b4e0e497bff76f7d4451c54649d2](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d0ec252906d9b4e0e497bff76f7d4451c54649d2)) 301 | 302 | ### refactor 303 | 304 | - prepare release on npm, updated package.json ([878181526ef5c9481f3c5a4d172c0c42b203f706](https://github.com/timbru31/spigot-anti-piracy-backend/commit/878181526ef5c9481f3c5a4d172c0c42b203f706)) 305 | 306 | 307 | 308 | ## [0.3.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.3.0...v0.3.1) (2016-02-24) 309 | 310 | ### chore 311 | 312 | - add appveyor setup ([2075e1e871b94c05c22de31da65ae8f55ea8579b](https://github.com/timbru31/spigot-anti-piracy-backend/commit/2075e1e871b94c05c22de31da65ae8f55ea8579b)) 313 | - adds circleci setup ([8cbd93e5ce2677d9648987e8c475ccc1e607d0a9](https://github.com/timbru31/spigot-anti-piracy-backend/commit/8cbd93e5ce2677d9648987e8c475ccc1e607d0a9)) 314 | - update dependencies and CI configs ([f33788686999645f932313bae8c7749867fb30be](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f33788686999645f932313bae8c7749867fb30be)) 315 | - updated dependencies ([261337277e599139250f0644b07cdac184e1e52d](https://github.com/timbru31/spigot-anti-piracy-backend/commit/261337277e599139250f0644b07cdac184e1e52d)) 316 | 317 | ### doc 318 | 319 | - add license ([636e4c738e58584c08ac46bbcf87e64213475bad](https://github.com/timbru31/spigot-anti-piracy-backend/commit/636e4c738e58584c08ac46bbcf87e64213475bad)) 320 | 321 | ### feat 322 | 323 | - log some info on startup ([01bc0b88f3e39a05f8efabfeeff793bec004a3c8](https://github.com/timbru31/spigot-anti-piracy-backend/commit/01bc0b88f3e39a05f8efabfeeff793bec004a3c8)) 324 | 325 | ### fix 326 | 327 | - fix npm run test by requiring babel-polyfill in tests, too ([3d13c1d74df792db27514054c06257aad6143758](https://github.com/timbru31/spigot-anti-piracy-backend/commit/3d13c1d74df792db27514054c06257aad6143758)) 328 | - ignore coverage folders when linting ([cd808b7b248f175c7e3576829b04034ee06a6110](https://github.com/timbru31/spigot-anti-piracy-backend/commit/cd808b7b248f175c7e3576829b04034ee06a6110)) 329 | 330 | 331 | 332 | # [0.3.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.2.1...v0.3.0) (2016-02-05) 333 | 334 | ### feat 335 | 336 | - log request ip, add support for koa proxy ([da7d3b38d2c9958d03e001b51034a3eb0a4d2add](https://github.com/timbru31/spigot-anti-piracy-backend/commit/da7d3b38d2c9958d03e001b51034a3eb0a4d2add)) 337 | 338 | 339 | 340 | ## [0.2.1](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.2.0...v0.2.1) (2016-02-04) 341 | 342 | ### fix 343 | 344 | - add max log size and tail configuration ([e55bc0dbad0e65275f286bb8b9506f9d58b2d41a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/e55bc0dbad0e65275f286bb8b9506f9d58b2d41a)) 345 | 346 | 347 | 348 | # [0.2.0](https://github.com/timbru31/spigot-anti-piracy-backend/compare/v0.1.0...v0.2.0) (2016-02-03) 349 | 350 | ### chore 351 | 352 | - adds coverage configuration for codeclimate, adds missing test file ([fb2d6e1bd937f5e8209bdd255ca82a9abcc816cb](https://github.com/timbru31/spigot-anti-piracy-backend/commit/fb2d6e1bd937f5e8209bdd255ca82a9abcc816cb)) 353 | - drop support for node 0.12 ([a29701b1132b326d581d2e65f8c46b2fbb63dbc4](https://github.com/timbru31/spigot-anti-piracy-backend/commit/a29701b1132b326d581d2e65f8c46b2fbb63dbc4)) 354 | - updated dependencies ([d8c0ddb55d95dae5c7716f46bc24af137d7270a8](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d8c0ddb55d95dae5c7716f46bc24af137d7270a8)) 355 | - updated dependencies ([f0531846be8989b7d3f67f0e5595a72414f4423a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/f0531846be8989b7d3f67f0e5595a72414f4423a)) 356 | 357 | ### doc 358 | 359 | - adds example for upstart configuration ([d413ec7e566c12cbbbfc846a490ea9004a79a368](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d413ec7e566c12cbbbfc846a490ea9004a79a368)) 360 | 361 | ### docs 362 | 363 | - adds README content ([6583147c261a9eb5fdc1274f11d947c1c24f101a](https://github.com/timbru31/spigot-anti-piracy-backend/commit/6583147c261a9eb5fdc1274f11d947c1c24f101a)) 364 | 365 | ### feat 366 | 367 | - add logging via winston ([d6b77ec569c0fd7ac5723209e2298955b2095f69](https://github.com/timbru31/spigot-anti-piracy-backend/commit/d6b77ec569c0fd7ac5723209e2298955b2095f69)) 368 | 369 | ### refactor 370 | 371 | - use async readFile ([017874347a0b3170a8e62f7021e74987afeb3d78](https://github.com/timbru31/spigot-anti-piracy-backend/commit/017874347a0b3170a8e62f7021e74987afeb3d78)) 372 | 373 | ### test 374 | 375 | - adds additional tests for PUT, DELETE; HEAD and a test for an invalid blacklist ([81310ce101a278743f9354a80f739abd1158a523](https://github.com/timbru31/spigot-anti-piracy-backend/commit/81310ce101a278743f9354a80f739abd1158a523)) 376 | - adds test for app.js ([4e76bb37de0bd30c772571a9231382eb5d730e02](https://github.com/timbru31/spigot-anti-piracy-backend/commit/4e76bb37de0bd30c772571a9231382eb5d730e02)) 377 | - check for JSON response in test ([5a97820d2d4ed7b27774a4b8ee997ff99341ea4e](https://github.com/timbru31/spigot-anti-piracy-backend/commit/5a97820d2d4ed7b27774a4b8ee997ff99341ea4e)) 378 | 379 | 380 | 381 | # 0.1.0 (2016-01-23) 382 | --------------------------------------------------------------------------------