Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

emoji-to-issue

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

emoji-to-issue - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

.prettierignore

3

.release-it.json
{
"github": {
"release": true
},
"npm": {
"skipChecks": true
}
}

18

dist/github-client.d.ts
export default class GithubClient {
token: string
constructor(token: any)
apiHeaders(): {
'Content-Type': string
Authorization: string
Accept: string
}
createIssue(repo: any, params: any): Promise<any>
getLatestIssues(repo: any): Promise<any>
token: string;
constructor(token: any);
apiHeaders(): {
'Content-Type': string;
Authorization: string;
Accept: string;
};
createIssue(repo: any, params: any): Promise<any>;
getLatestIssues(repo: any): Promise<any>;
}

@@ -1,88 +0,55 @@

'use strict'
var __awaiter =
(this && this.__awaiter) ||
function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P
? value
: new P(function(resolve) {
resolve(value)
})
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value))
} catch (e) {
reject(e)
}
}
function rejected(value) {
try {
step(generator['throw'](value))
} catch (e) {
reject(e)
}
}
function step(result) {
result.done
? resolve(result.value)
: adopt(result.value).then(fulfilled, rejected)
}
step((generator = generator.apply(thisArg, _arguments || [])).next())
})
}
var __importDefault =
(this && this.__importDefault) ||
function(mod) {
return mod && mod.__esModule ? mod : { default: mod }
}
Object.defineProperty(exports, '__esModule', { value: true })
const axios_1 = __importDefault(require('axios'))
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
class GithubClient {
constructor(token) {
this.token = token || process.env.GITHUB_TOKEN
}
apiHeaders() {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.token}`,
Accept: 'application/vnd.github.v3+json'
constructor(token) {
this.token = token || process.env.GITHUB_TOKEN;
}
}
createIssue(repo, params) {
return __awaiter(this, void 0, void 0, function*() {
const res = yield axios_1.default.post(
`https://api.github.com/repos/${repo}/issues`,
params,
{
headers: this.apiHeaders()
}
)
if (res.status > 300) {
console.error(res.data)
throw new Error(res.data.message)
}
return res.data
})
}
getLatestIssues(repo) {
return __awaiter(this, void 0, void 0, function*() {
const res = yield axios_1.default.get(
`https://api.github.com/repos/${repo}/issues`,
{
params: {
state: 'all'
},
headers: this.apiHeaders()
}
)
if (res.status > 300) {
console.error(res.data)
throw new Error(res.data.message)
}
return res.data
})
}
apiHeaders() {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.token}`,
Accept: 'application/vnd.github.v3+json'
};
}
createIssue(repo, params) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield axios_1.default.post(`https://api.github.com/repos/${repo}/issues`, params, {
headers: this.apiHeaders()
});
if (res.status > 300) {
console.error(res.data);
throw new Error(res.data.message);
}
return res.data;
});
}
getLatestIssues(repo) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield axios_1.default.get(`https://api.github.com/repos/${repo}/issues`, {
params: {
state: 'all'
},
headers: this.apiHeaders()
});
if (res.status > 300) {
console.error(res.data);
throw new Error(res.data.message);
}
return res.data;
});
}
}
exports.default = GithubClient
exports.default = GithubClient;
export declare class ReactionHandler {
issueRepo: string
reactionName: string[] | null
slackToken: string
githubToken: string
constructor(params: {
issueRepo: string
reactionName?: string[]
githubToken?: string
slackToken?: string
})
match(event: any): boolean
extractAssignee(reactionName: any): any
reactionNames(): string[]
extractSlackUsersFromText(text: any): any[]
removeSlackFormatting(text: any, users: any): any
extractSlackUsersFromMessages(messages: any): string[]
buildIssueContent(
event: any
): Promise<{
title: any
body: string
}>
handle(event: any): Promise<any>
issueRepo: string;
reactionName: string[] | null;
slackToken: string;
githubToken: string;
constructor(params: {
issueRepo: string;
reactionName?: string[];
githubToken?: string;
slackToken?: string;
});
match(event: any): boolean;
extractAssignee(reactionName: any): any;
reactionNames(): string[];
extractSlackUsersFromText(text: any): any[];
removeSlackFormatting(text: any, users: any): any;
extractSlackUsersFromMessages(messages: any): string[];
buildIssueContent(event: any): Promise<{
title: any;
body: string;
}>;
handle(event: any): Promise<any>;
}

@@ -1,189 +0,160 @@

'use strict'
var __awaiter =
(this && this.__awaiter) ||
function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P
? value
: new P(function(resolve) {
resolve(value)
})
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReactionHandler = void 0;
const decode = require("decode-html");
const github_client_1 = __importDefault(require("./github-client"));
const slack_client_1 = __importDefault(require("./slack-client"));
function debug(message) {
if (process.env.DEBUG) {
console.log(message);
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value))
} catch (e) {
reject(e)
}
}
function rejected(value) {
try {
step(generator['throw'](value))
} catch (e) {
reject(e)
}
}
function step(result) {
result.done
? resolve(result.value)
: adopt(result.value).then(fulfilled, rejected)
}
step((generator = generator.apply(thisArg, _arguments || [])).next())
})
}
var __importDefault =
(this && this.__importDefault) ||
function(mod) {
return mod && mod.__esModule ? mod : { default: mod }
}
Object.defineProperty(exports, '__esModule', { value: true })
exports.ReactionHandler = void 0
const decode = require('decode-html')
const github_client_1 = __importDefault(require('./github-client'))
const slack_client_1 = __importDefault(require('./slack-client'))
function debug(message) {
if (process.env.DEBUG) {
console.log(message)
}
}
class ReactionHandler {
constructor(params) {
this.issueRepo = params.issueRepo
this.reactionName = params.reactionName || null
this.slackToken = params.slackToken || process.env.SLACK_TOKEN
this.githubToken = params.githubToken || process.env.GITHUB_TOKEN
}
match(event) {
if (event.type !== 'reaction_added') return false
if (this.reactionNames().includes(event.reaction)) return true
const matched = this.reactionNames().some(name => {
return new RegExp(`^${name}-assign-.+$`).test(event.reaction)
})
return matched
}
extractAssignee(reactionName) {
const matchData = reactionName.match(/-assign-(.+)$/)
return matchData && matchData[1]
}
reactionNames() {
return this.reactionName || ['issue', 'イシュー']
}
extractSlackUsersFromText(text) {
const result = []
const regex = /<@([^>]+)>/g
let matched
while ((matched = regex.exec(text)) !== null) {
result.push(matched[1])
constructor(params) {
this.issueRepo = params.issueRepo;
this.reactionName = params.reactionName || null;
this.slackToken = params.slackToken || process.env.SLACK_TOKEN;
this.githubToken = params.githubToken || process.env.GITHUB_TOKEN;
}
return result
}
removeSlackFormatting(text, users) {
return text.replace(
/<([@#!])?([^>|]+)(?:\|([^>]+))?>/g,
(match, type, link, label) => {
if (type === '@') {
const info = users[link]
if (info) {
return `@${info.profile.display_name}`
} else {
return `@${link}`
}
match(event) {
if (event.type !== 'reaction_added')
return false;
if (this.reactionNames().includes(event.reaction))
return true;
const matched = this.reactionNames().some(name => {
return new RegExp(`^${name}-assign-.+$`).test(event.reaction);
});
return matched;
}
extractAssignee(reactionName) {
const matchData = reactionName.match(/-assign-(.+)$/);
return matchData && matchData[1];
}
reactionNames() {
return this.reactionName || ['issue', 'イシュー'];
}
extractSlackUsersFromText(text) {
const result = [];
const regex = /<@([^>]+)>/g;
let matched;
while ((matched = regex.exec(text)) !== null) {
result.push(matched[1]);
}
if (type === '#') {
return `#${label || link}`
}
return label || link
}
)
}
extractSlackUsersFromMessages(messages) {
const users = {}
messages
.filter(m => m.user)
.forEach(m => {
users[m.user] = null
})
messages.forEach(m => {
this.extractSlackUsersFromText(m.text).forEach(u => {
users[u] = null
})
})
return Object.keys(users)
}
buildIssueContent(event) {
return __awaiter(this, void 0, void 0, function*() {
const slackClient = new slack_client_1.default(this.slackToken)
const { channel, ts } = event.item
const { messages } = yield slackClient.getMessages(channel, ts, 10)
const slackUsers = this.extractSlackUsersFromMessages(messages)
const userInfos = yield Promise.all(
slackUsers.map(user => slackClient.getUserInfo(user))
)
const users = {}
userInfos.forEach(info => {
if (!info) return
users[info.id] = info
})
debug(messages)
const message = messages[0]
const permalink = yield slackClient.getPermalink(channel, message.ts)
const title = this.removeSlackFormatting(decode(message.text), users)
const historyText = messages
.reverse()
.filter(
m =>
m.type === 'message' &&
m.subtype !== 'bot_message' &&
m.bot_id === undefined &&
m.text
)
.map(m => {
const info = users[m.user]
const username = info ? info.profile.display_name : m.user
const decoded = decode(m.text)
const expanded = this.removeSlackFormatting(decoded, users)
return `${username}: ${expanded}`
})
.join('\n')
const body = `${permalink}\n` + '```\n' + historyText + '\n```'
return {
title: title,
body: body
}
})
}
// create an issue from a slack reaction event
handle(event) {
return __awaiter(this, void 0, void 0, function*() {
debug(event)
if (!this.match(event)) return
const { title, body } = yield this.buildIssueContent(event)
const githubClient = new github_client_1.default(this.githubToken)
const issueRepo = this.issueRepo
const issues = yield githubClient.getLatestIssues(issueRepo)
const foundIssue = issues.find(issue => {
return issue.title === title
})
if (foundIssue) {
return foundIssue
}
const issueParams = {
title: title,
body: body
}
const assignee = this.extractAssignee(event.reaction)
if (assignee) {
issueParams.assignees = [assignee]
}
debug(issueParams)
const issue = yield githubClient.createIssue(issueRepo, issueParams)
const { channel } = event.item
const slackClient = new slack_client_1.default(this.slackToken)
const slackMessage = `<@${event.user}> ${issue.html_url}`
yield slackClient.postMessage(channel, slackMessage)
return issue
})
}
return result;
}
removeSlackFormatting(text, users) {
return text.replace(/<([@#!])?([^>|]+)(?:\|([^>]+))?>/g, (match, type, link, label) => {
if (type === '@') {
const info = users[link];
if (info) {
return `@${info.profile.display_name}`;
}
else {
return `@${link}`;
}
}
if (type === '#') {
return `#${label || link}`;
}
return label || link;
});
}
extractSlackUsersFromMessages(messages) {
const users = {};
messages
.filter(m => m.user)
.forEach(m => {
users[m.user] = null;
});
messages.forEach(m => {
this.extractSlackUsersFromText(m.text).forEach(u => {
users[u] = null;
});
});
return Object.keys(users);
}
buildIssueContent(event) {
return __awaiter(this, void 0, void 0, function* () {
const slackClient = new slack_client_1.default(this.slackToken);
const { channel, ts } = event.item;
const { messages } = yield slackClient.getMessages(channel, ts, 10);
const slackUsers = this.extractSlackUsersFromMessages(messages);
const userInfos = yield Promise.all(slackUsers.map(user => slackClient.getUserInfo(user)));
const users = {};
userInfos.forEach(info => {
if (!info)
return;
users[info.id] = info;
});
debug(messages);
const message = messages[0];
const permalink = yield slackClient.getPermalink(channel, message.ts);
const title = this.removeSlackFormatting(decode(message.text), users);
const historyText = messages
.reverse()
.filter(m => m.type === 'message' &&
m.subtype !== 'bot_message' &&
m.bot_id === undefined &&
m.text)
.map(m => {
const info = users[m.user];
const username = info ? info.profile.display_name : m.user;
const decoded = decode(m.text);
const expanded = this.removeSlackFormatting(decoded, users);
return `${username}: ${expanded}`;
})
.join('\n');
const body = `${permalink}\n` + '```\n' + historyText + '\n```';
return {
title: title,
body: body
};
});
}
// create an issue from a slack reaction event
handle(event) {
return __awaiter(this, void 0, void 0, function* () {
debug(event);
if (!this.match(event))
return;
const { title, body } = yield this.buildIssueContent(event);
const githubClient = new github_client_1.default(this.githubToken);
const issueRepo = this.issueRepo;
const issues = yield githubClient.getLatestIssues(issueRepo);
const foundIssue = issues.find(issue => {
return issue.title === title;
});
if (foundIssue) {
return foundIssue;
}
const issueParams = {
title: title,
body: body
};
const assignee = this.extractAssignee(event.reaction);
if (assignee) {
issueParams.assignees = [assignee];
}
debug(issueParams);
const issue = yield githubClient.createIssue(issueRepo, issueParams);
const { channel } = event.item;
const slackClient = new slack_client_1.default(this.slackToken);
const slackMessage = `<@${event.user}> ${issue.html_url}`;
yield slackClient.postMessage(channel, slackMessage);
return issue;
});
}
}
exports.ReactionHandler = ReactionHandler
exports.ReactionHandler = ReactionHandler;
export default class SlackClient {
token: string
constructor(token: any)
apiHeaders(
token: any
): {
'Content-Type': string
Authorization: string
}
getMessages(channel: any, ts: any, count?: number): Promise<any>
postMessage(channel: any, text: any): Promise<void>
getPermalink(channel: any, ts: any): Promise<any>
getUserInfo(user: any): Promise<any>
token: string;
constructor(token: any);
apiHeaders(token: any): {
'Content-Type': string;
Authorization: string;
};
getMessages(channel: any, ts: any, count?: number): Promise<any>;
postMessage(channel: any, text: any): Promise<void>;
getPermalink(channel: any, ts: any): Promise<any>;
getUserInfo(user: any): Promise<any>;
}

@@ -1,127 +0,88 @@

'use strict'
var __awaiter =
(this && this.__awaiter) ||
function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P
? value
: new P(function(resolve) {
resolve(value)
})
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value))
} catch (e) {
reject(e)
}
}
function rejected(value) {
try {
step(generator['throw'](value))
} catch (e) {
reject(e)
}
}
function step(result) {
result.done
? resolve(result.value)
: adopt(result.value).then(fulfilled, rejected)
}
step((generator = generator.apply(thisArg, _arguments || [])).next())
})
}
var __importDefault =
(this && this.__importDefault) ||
function(mod) {
return mod && mod.__esModule ? mod : { default: mod }
}
Object.defineProperty(exports, '__esModule', { value: true })
const axios_1 = __importDefault(require('axios'))
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
class SlackClient {
constructor(token) {
this.token = token || process.env.SLACK_TOKEN
}
apiHeaders(token) {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
constructor(token) {
this.token = token || process.env.SLACK_TOKEN;
}
}
getMessages(channel, ts, count = 1) {
return __awaiter(this, void 0, void 0, function*() {
const res = yield axios_1.default.get(
'https://slack.com/api/conversations.history',
{
params: {
channel: channel,
latest: ts,
limit: count,
inclusive: true
},
headers: this.apiHeaders(this.token)
}
)
if (res.status > 300) {
console.error(res.data)
throw new Error(res.data.message)
}
if (!res.data.ok) {
console.error(res.data)
throw new Error(JSON.stringify(res.data))
}
return res.data
})
}
postMessage(channel, text) {
return __awaiter(this, void 0, void 0, function*() {
yield axios_1.default.post(
'https://slack.com/api/chat.postMessage',
{
channel: channel,
text: text
},
{
headers: this.apiHeaders(this.token)
}
)
})
}
getPermalink(channel, ts) {
return __awaiter(this, void 0, void 0, function*() {
const res = yield axios_1.default.get(
'https://slack.com/api/chat.getPermalink',
{
params: {
channel: channel,
message_ts: ts,
token: this.token
}
}
)
return res.data.permalink
})
}
getUserInfo(user) {
return __awaiter(this, void 0, void 0, function*() {
if (!user) {
throw new Error('user is null')
}
const res = yield axios_1.default.get(
'https://slack.com/api/users.info',
{
params: {
user: user,
token: this.token
}
}
)
if (!res.data.ok) {
return null
}
return res.data.user
})
}
apiHeaders(token) {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
};
}
getMessages(channel, ts, count = 1) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield axios_1.default.get('https://slack.com/api/conversations.history', {
params: {
channel: channel,
latest: ts,
limit: count,
inclusive: true
},
headers: this.apiHeaders(this.token)
});
if (res.status > 300) {
console.error(res.data);
throw new Error(res.data.message);
}
if (!res.data.ok) {
console.error(res.data);
throw new Error(JSON.stringify(res.data));
}
return res.data;
});
}
postMessage(channel, text) {
return __awaiter(this, void 0, void 0, function* () {
yield axios_1.default.post('https://slack.com/api/chat.postMessage', {
channel: channel,
text: text
}, {
headers: this.apiHeaders(this.token)
});
});
}
getPermalink(channel, ts) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield axios_1.default.get('https://slack.com/api/chat.getPermalink', {
params: {
channel: channel,
message_ts: ts,
token: this.token
}
});
return res.data.permalink;
});
}
getUserInfo(user) {
return __awaiter(this, void 0, void 0, function* () {
if (!user) {
throw new Error('user is null');
}
const res = yield axios_1.default.get('https://slack.com/api/users.info', {
params: {
user: user,
token: this.token
}
});
if (!res.data.ok) {
return null;
}
return res.data.user;
});
}
}
exports.default = SlackClient
exports.default = SlackClient;
{
"name": "emoji-to-issue",
"version": "1.0.0",
"version": "1.0.1",
"description": "the fastest way to create github issues with slack emoji reactions",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc