Skip to content

Commit 08afa73

Browse files
committed
init
0 parents  commit 08afa73

14 files changed

+377
-0
lines changed

.eslintignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
/lib
3+
/coverage

.eslintrc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"root": true,
3+
"parser": "@typescript-eslint/parser",
4+
"plugins": [
5+
"@typescript-eslint"
6+
],
7+
"extends": [
8+
"eslint:recommended",
9+
"plugin:@typescript-eslint/eslint-recommended",
10+
"plugin:@typescript-eslint/recommended"
11+
],
12+
"rules": {
13+
"no-console": 1,
14+
"semi-style": ["error", "last"],
15+
"semi": [2, "always"]
16+
}
17+
}

.github/workflows/build.yaml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: NPM Publish
2+
on: [push]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
7+
steps:
8+
- name: Begin...
9+
uses: actions/checkout@v2
10+
11+
- name: Use Node 14
12+
uses: actions/setup-node@v1
13+
with:
14+
node-version: 14
15+
16+
- name: Install dependencies
17+
run: npm install && npm install node-fetch @types/node-fetch -g
18+
env:
19+
CI: true
20+
21+
- name: Automated Version Bump
22+
uses: "phips28/gh-action-bump-version@master"
23+
env:
24+
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
25+
26+
- name: Build
27+
run: npm run build
28+
env:
29+
CI: true
30+
31+
- name: Publish
32+
run: echo "//registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN" > ~/.npmrc && npm publish --access public
33+
env:
34+
NPM_AUTH_TOKEN: ${{ secrets.TOKEN }}

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
/coverage
3+
src/__tests__/local.test.ts
4+
package-lock.json

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Ayush Pathak
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.

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# @ayshptk/msngr
2+
3+
a tiny utility to post to user-provided webhooks without worrying about platforms built for [@raiddotfarm](https://github.com/raiddotfarm)
4+
5+
platforms supported:
6+
7+
- [x] slack
8+
- [x] discord
9+
10+
won't be adding new platforms myself because of current commitments but feel free to create PR **with a working test** to get it merged :)
11+
12+
13+
### 1. install:
14+
15+
```
16+
npm install @ayshptk/msngr
17+
```
18+
19+
or
20+
21+
```
22+
yarn install @ayshptk/msngr
23+
```
24+
25+
### 2. use
26+
27+
```ts
28+
// import
29+
import { send } from "@ayshptk/msngr";
30+
31+
// declaring webhook
32+
const webhook = "https://discord.com/api/webhooks/987654321/abcdefghijklmnopqrstuvwxyz";
33+
34+
// send
35+
await send(webhook, "Hello World!");
36+
```
37+
38+

jestconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"transform": {
3+
"^.+\\.(t|j)sx?$": "ts-jest"
4+
},
5+
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
6+
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
7+
"collectCoverageFrom": ["src/**/*.{ts,tsx}"],
8+
"collectCoverage":true
9+
}

lib/index.d.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface payload {
2+
message: string;
3+
}
4+
export declare type request = string | payload;
5+
export interface response {
6+
success: boolean;
7+
response?: unknown;
8+
reason?: string;
9+
}
10+
declare const send: (webhook: string, request: request) => Promise<response>;
11+
declare const ping: (webhook: string) => Promise<response>;
12+
export { send, ping };

lib/index.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
11+
Object.defineProperty(exports, "__esModule", { value: true });
12+
exports.ping = exports.send = void 0;
13+
const node_fetch_1 = require("node-fetch");
14+
const send = (webhook, request) => __awaiter(void 0, void 0, void 0, function* () {
15+
let finalPayload;
16+
if (typeof request === "string") {
17+
request = { message: request };
18+
}
19+
if (webhook.startsWith("https://hooks.slack.com/services/")) {
20+
finalPayload = {
21+
text: request.message,
22+
};
23+
}
24+
else if (webhook.startsWith("https://discord.com/api/webhooks")) {
25+
finalPayload = {
26+
content: request.message,
27+
};
28+
}
29+
else {
30+
return {
31+
success: false,
32+
reason: "Invalid webhook",
33+
};
34+
}
35+
return (0, node_fetch_1.default)(webhook, {
36+
method: "POST",
37+
body: JSON.stringify(finalPayload),
38+
headers: {
39+
"Content-Type": "application/json",
40+
},
41+
})
42+
.then((res) => __awaiter(void 0, void 0, void 0, function* () {
43+
if (res.ok) {
44+
return {
45+
success: true,
46+
response: yield res.text(),
47+
};
48+
}
49+
else {
50+
throw new Error(res.statusText);
51+
}
52+
}))
53+
.catch((err) => {
54+
return {
55+
success: false,
56+
reason: err.message,
57+
};
58+
});
59+
});
60+
exports.send = send;
61+
const ping = (webhook) => __awaiter(void 0, void 0, void 0, function* () {
62+
return yield send(webhook, { message: "Webhook pinged successfully!" });
63+
});
64+
exports.ping = ping;

package.json

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "@ayshptk/msngr",
3+
"version": "0.0.10",
4+
"description": "",
5+
"main": "lib/index.js",
6+
"scripts": {
7+
"build": "tsc",
8+
"lint": "eslint . --ext .ts",
9+
"test": "jest --config jestconfig.json"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git+https://github.com/ayshptk/msngr"
14+
},
15+
"files": [
16+
"lib/**/*"
17+
],
18+
"keywords": [
19+
"webhooks"
20+
],
21+
"author": "Ayush Pathak",
22+
"license": "MIT",
23+
"bugs": {
24+
"url": "https://github.com/ayshptk/msngr/issues"
25+
},
26+
"homepage": "https://github.com/ayshptk/msngr#readme",
27+
"devDependencies": {
28+
"@types/jest": "^27.4.0",
29+
"@types/node": "^16.11.6",
30+
"@types/node-fetch": "^3.0.3",
31+
"@typescript-eslint/eslint-plugin": "^5.3.0",
32+
"@typescript-eslint/parser": "^5.3.0",
33+
"eslint": "^8.2.0",
34+
"eslint-config-prettier": "^8.3.0",
35+
"eslint-config-standard": "^16.0.3",
36+
"eslint-plugin-import": "^2.25.2",
37+
"eslint-plugin-node": "^11.1.0",
38+
"eslint-plugin-promise": "^5.1.1",
39+
"jest": "^27.3.1",
40+
"ts-jest": "^27.0.7",
41+
"typescript": "^4.4.4"
42+
},
43+
"dependencies": {
44+
"node-fetch": "2.6.7"
45+
}
46+
}

src/__tests__/send.test.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { send } from "../index";
2+
3+
describe.skip("success", () => {
4+
test("discord", async () => {
5+
expect(
6+
// feel free to use your own discord webhook :)
7+
(
8+
await send("https://discord.com/api/webhooks/../..", {
9+
message: "Hello, world!",
10+
})
11+
).success
12+
).toBe(true);
13+
});
14+
15+
test.skip("slack", async () => {
16+
expect(
17+
// feel free to use your own slack webhook :)
18+
(
19+
await send("https://hooks.slack.com/services/../..", {
20+
message: "Hello, world!",
21+
})
22+
).success
23+
).toBe(true);
24+
});
25+
});
26+
describe("errors", () => {
27+
test("invalid webhooks", async () => {
28+
expect(
29+
(
30+
await send(
31+
"https://badwebhook.com", // feel free to use your own slack webhook :)
32+
{
33+
message: "Hello, world!",
34+
}
35+
)
36+
).reason
37+
).toBe("Invalid webhook");
38+
});
39+
test("expired webhooks", async () => {
40+
expect(
41+
(
42+
await send(
43+
"https://hooks.slack.com/services/T032WAH0TGU/B032WAKGF28/8F0LznNK6JRzpKR7R5srLXZ", // feel free to use your own slack webhook :)
44+
{
45+
message: "Hello, world!",
46+
}
47+
)
48+
).reason
49+
).toBe("Forbidden");
50+
});
51+
});

src/index.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2+
// @ts-ignore
3+
import fetch from "node-fetch";
4+
export interface payload {
5+
message: string;
6+
}
7+
export type request = string | payload;
8+
export interface response {
9+
success: boolean;
10+
response?: unknown;
11+
// returns the reason if success is false
12+
reason?: string;
13+
}
14+
15+
const send = async (webhook: string, request: request): Promise<response> => {
16+
let finalPayload;
17+
if (typeof request === "string") {
18+
request = { message: request };
19+
}
20+
if (webhook.startsWith("https://hooks.slack.com/services/")) {
21+
finalPayload = {
22+
text: request.message,
23+
};
24+
} else if (webhook.startsWith("https://discord.com/api/webhooks")) {
25+
finalPayload = {
26+
content: request.message,
27+
};
28+
} else {
29+
return {
30+
success: false,
31+
reason: "Invalid webhook",
32+
};
33+
}
34+
return fetch(webhook, {
35+
method: "POST",
36+
body: JSON.stringify(finalPayload),
37+
headers: {
38+
"Content-Type": "application/json",
39+
},
40+
})
41+
.then(async (res: any) => {
42+
if (res.ok) {
43+
return {
44+
success: true,
45+
response: await res.text(),
46+
};
47+
} else {
48+
throw new Error(res.statusText);
49+
}
50+
})
51+
.catch((err : any) => {
52+
return {
53+
success: false,
54+
reason: err.message,
55+
};
56+
});
57+
};
58+
59+
const ping = async (webhook: string): Promise<response> => {
60+
return await send(webhook, { message: "Webhook pinged successfully!" });
61+
};
62+
export { send, ping };

tsconfig.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"outDir": "./lib",
4+
"module": "commonjs",
5+
"target": "es6",
6+
"declaration": true,
7+
"strict": true
8+
},
9+
"include": ["src"],
10+
"exclude": ["node_modules", "**/__tests__/*"]
11+
}

tsconfig.spec.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"types": ["jest", "node"]
4+
}
5+
}

0 commit comments

Comments
 (0)