Skip to content

Commit 0ba430d

Browse files
committed
find, add, profile commands
1 parent 73c4c03 commit 0ba430d

File tree

8 files changed

+221
-29
lines changed

8 files changed

+221
-29
lines changed

src/commandDetails/company/add.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { container } from '@sapphire/framework';
2+
import {
3+
CodeyCommandDetails,
4+
CodeyCommandOptionType,
5+
SapphireMessageExecuteType,
6+
SapphireMessageResponse,
7+
getUserFromMessage,
8+
} from '../../codeyCommand';
9+
import { addUserToCompany, getCompanyInfo, insertCompany } from '../../components/company';
10+
11+
const companyAddExecuteCommand: SapphireMessageExecuteType = async (
12+
_client,
13+
messageFromUser,
14+
args,
15+
): Promise<SapphireMessageResponse> => {
16+
const company_id = args['company_id'];
17+
if (!company_id) {
18+
throw new Error('please enter a valid user mention or ID for balance adjustment.');
19+
}
20+
const role = args['role'];
21+
if (!role) {
22+
throw new Error('please enter a role.');
23+
}
24+
const company = await getCompanyInfo(<string>company_id);
25+
if (!company) {
26+
await insertCompany(<string>company_id);
27+
}
28+
const userId = getUserFromMessage(messageFromUser).id;
29+
await addUserToCompany(userId, <string>company_id, <string>role);
30+
return 'Successfully added company to profile!';
31+
};
32+
33+
export const companyAddCommandDetails: CodeyCommandDetails = {
34+
name: 'add',
35+
aliases: ['a'],
36+
description: 'Add a company to your profile',
37+
detailedDescription: `**Examples:**
38+
\`${container.botPrefix}company add https://www.crunchbase.com/organization/microsoft\`
39+
\`${container.botPrefix}company a microsoft \``,
40+
messageWhenExecutingCommand: 'Adding...',
41+
executeCommand: companyAddExecuteCommand,
42+
43+
options: [
44+
{
45+
name: 'company_id',
46+
description: `The unique identifier for the company. This can be either a link to its crunchbarse url or the company's crunchbase id,
47+
which is the last part of the crunchbase url (/organization/{crunchbase_id}).`,
48+
type: CodeyCommandOptionType.STRING,
49+
required: true,
50+
},
51+
{
52+
name: 'role',
53+
description: `Your role at the company. For example, "Software Engineering Intern" or "Data Science Intern".`,
54+
type: CodeyCommandOptionType.STRING,
55+
required: true,
56+
},
57+
],
58+
subcommandDetails: {},
59+
};

src/commandDetails/company/enroll.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,21 @@ import {
66
SapphireMessageResponse,
77
} from '../../codeyCommand';
88
import { getCompanyInfo, insertCompany } from '../../components/company';
9-
import { getCrunchbaseCompanyDetails } from '../../utils/companyInfo';
109

11-
interface CrunchbaseCompanyProperties {
12-
short_description: string;
13-
}
1410
const companyEnrollExecuteCommand: SapphireMessageExecuteType = async (
15-
client,
16-
messageFromUser,
11+
_client,
12+
_messageFromUser,
1713
args,
1814
): Promise<SapphireMessageResponse> => {
1915
const company_id = args['company_id'];
2016
if (!company_id) {
21-
throw new Error('please enter a valid user mention or ID for balance adjustment.');
17+
throw new Error('please enter a valid company_id.');
2218
}
2319
const getExistingCompanyInfo = await getCompanyInfo(<string>company_id);
2420
if (getExistingCompanyInfo) {
2521
return 'Company already enrolled!.';
2622
}
27-
const crunchbaseCompanyResponse = await getCrunchbaseCompanyDetails(<string>company_id);
28-
const crunchbaseCompanyInfo = crunchbaseCompanyResponse.properties as CrunchbaseCompanyProperties;
29-
await insertCompany(<string>company_id, crunchbaseCompanyInfo.short_description);
23+
await insertCompany(<string>company_id);
3024
return 'Company succesfully enrolled!';
3125
};
3226

src/commandDetails/company/find.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { container } from '@sapphire/framework';
2+
import {
3+
CodeyCommandDetails,
4+
CodeyCommandOptionType,
5+
SapphireMessageExecuteType,
6+
SapphireMessageResponse,
7+
} from '../../codeyCommand';
8+
import { getEmployeesByCompanyId } from '../../components/company';
9+
10+
const CRUNCHBASE_IMAGE_CDN =
11+
'https://res.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco,dpr_1';
12+
const companyFindExecuteCommand: SapphireMessageExecuteType = async (
13+
client,
14+
_messageFromUser,
15+
args,
16+
): Promise<SapphireMessageResponse> => {
17+
const company_id = args['company_id'];
18+
if (!company_id) {
19+
throw new Error('please enter a valid user mention or ID for balance adjustment.');
20+
}
21+
const companyUsers = await getEmployeesByCompanyId(<string>company_id);
22+
if (!companyUsers) {
23+
return 'No one works at this company in the server!';
24+
}
25+
const formattedUsers = await Promise.all(
26+
companyUsers.map(async (user) => {
27+
return {
28+
...user,
29+
tag: (await client.users.fetch(user.user_id)).tag,
30+
};
31+
}),
32+
);
33+
return `employees are: ${JSON.stringify(formattedUsers)}`;
34+
};
35+
36+
export const companyFindCommandDetails: CodeyCommandDetails = {
37+
name: 'find',
38+
aliases: ['f'],
39+
description: 'Find all individuals that work at the company.',
40+
detailedDescription: `**Examples:**
41+
\`${container.botPrefix}company find https://www.crunchbase.com/organization/microsoft\`
42+
\`${container.botPrefix}company f microsoft\``,
43+
messageWhenExecutingCommand: 'Enrolling company...',
44+
executeCommand: companyFindExecuteCommand,
45+
46+
options: [
47+
{
48+
name: 'company_id',
49+
description: `The unique identifier for the company. This can be either a link to its crunchbarse url or the company's crunchbase id,
50+
which is the last part of the crunchbase url (/organization/{crunchbase_id}).`,
51+
type: CodeyCommandOptionType.STRING,
52+
required: true,
53+
},
54+
],
55+
subcommandDetails: {},
56+
};

src/commandDetails/company/profile.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { container } from '@sapphire/framework';
2+
import {
3+
CodeyCommandDetails,
4+
CodeyCommandOptionType,
5+
SapphireMessageExecuteType,
6+
SapphireMessageResponse,
7+
getUserFromMessage,
8+
} from '../../codeyCommand';
9+
import { getCompaniesByUserId, getEmployeesByCompanyId } from '../../components/company';
10+
11+
const companyProfileExecuteCommand: SapphireMessageExecuteType = async (
12+
client,
13+
messageFromUser,
14+
args,
15+
): Promise<SapphireMessageResponse> => {
16+
const user = getUserFromMessage(messageFromUser);
17+
const companies = await getCompaniesByUserId(user.id);
18+
console.log(companies);
19+
return `your companies are: ${JSON.stringify(companies)}`;
20+
};
21+
22+
export const companyProfileCommandDetails: CodeyCommandDetails = {
23+
name: 'profile',
24+
aliases: ['p'],
25+
description: 'List all the companies you are associated with',
26+
detailedDescription: `**Examples:**
27+
\`${container.botPrefix}company profile\`
28+
\`${container.botPrefix}company p\``,
29+
messageWhenExecutingCommand: 'Finding...',
30+
executeCommand: companyProfileExecuteCommand,
31+
options: [],
32+
subcommandDetails: {},
33+
};

src/commands/company/company.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Command, container } from '@sapphire/framework';
22
import { CodeyCommand, CodeyCommandDetails } from '../../codeyCommand';
33
import { companyEnrollCommandDetails } from '../../commandDetails/company/enroll';
4+
import { companyAddCommandDetails } from '../../commandDetails/company/add';
5+
import { companyFindCommandDetails } from '../../commandDetails/company/find';
6+
import { companyProfileCommandDetails } from '../../commandDetails/company/profile';
47

58
const companyCommandDetails: CodeyCommandDetails = {
69
name: 'company',
@@ -12,6 +15,9 @@ const companyCommandDetails: CodeyCommandDetails = {
1215
options: [],
1316
subcommandDetails: {
1417
enroll: companyEnrollCommandDetails,
18+
add: companyAddCommandDetails,
19+
find: companyFindCommandDetails,
20+
profile: companyProfileCommandDetails,
1521
},
1622
};
1723

src/components/company.ts

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,68 @@
11
import _ from 'lodash';
22
import { openDB } from './db';
3+
import { getCrunchbaseCompanyDetails } from '../utils/companyInfo';
34

45
interface CompanyInfo {
56
company_id: string;
67
description: string;
78
}
89

9-
export const insertCompany = async (companyId: string, description: string): Promise<void> => {
10+
interface CrunchbaseCompanyProperties {
11+
name: string;
12+
short_description: string;
13+
image_id: string;
14+
}
15+
16+
export const insertCompany = async (companyId: string): Promise<void> => {
17+
const crunchbaseCompanyResponse = await getCrunchbaseCompanyDetails(<string>companyId);
18+
const { name, short_description } = crunchbaseCompanyResponse;
19+
const companyImageId = crunchbaseCompanyResponse.identifier?.image_id;
20+
const crunchbaseCompanyInfo = {
21+
name,
22+
short_description,
23+
image_id: <string>companyImageId,
24+
};
25+
await insertCompanyDetails(<string>companyId, crunchbaseCompanyInfo);
26+
};
27+
28+
export const insertCompanyDetails = async (
29+
companyId: string,
30+
crunchbaseCompanyInfo: CrunchbaseCompanyProperties,
31+
): Promise<void> => {
1032
const db = await openDB();
11-
const insertCompanyCommand = `INSERT INTO companies (company_id, description) VALUES (?,?)`;
12-
await db.run(insertCompanyCommand, companyId, description);
33+
const { name, image_id, short_description } = crunchbaseCompanyInfo;
34+
const insertCompanyCommand = `INSERT INTO companies (company_id, name, image_id, description) VALUES (?,?,?)`;
35+
await db.run(insertCompanyCommand, companyId, name, image_id, short_description);
36+
};
37+
38+
export const addUserToCompany = async (
39+
userId: string,
40+
companyId: string,
41+
role: string,
42+
): Promise<void> => {
43+
const db = await openDB();
44+
const insertCompanyCommand = `INSERT INTO companies_people (user_id, company_id, role) VALUES (?,?,?)`;
45+
await db.run(insertCompanyCommand, userId, companyId, role);
1346
};
1447

1548
export const getCompanyInfo = async (companyId: string): Promise<CompanyInfo> => {
1649
const db = await openDB();
1750
return (await db.get('SELECT * FROM companies WHERE company_id = ?', companyId)) as CompanyInfo;
1851
};
1952

20-
export const getCompaniesByUserId = async (userId: string): Promise<string[]> => {
53+
export const getCompaniesByUserId = async (userId: string): Promise<CompanyPersonDetails[]> => {
2154
const db = await openDB();
22-
23-
const res = await db.all('SELECT company_id FROM people_companies WHERE user_id = ?', userId);
24-
return res.map((row) => row.company_id);
55+
return await db.all('SELECT * FROM companies_people WHERE user_id = ?', userId);
2556
};
2657

27-
export const getUsersByCompanyId = async (companyId: string): Promise<string[]> => {
28-
const db = await openDB();
58+
interface CompanyPersonDetails {
59+
user_id: string;
60+
role: string;
61+
}
2962

30-
const res = await db.all('SELECT user_id FROM people_companies WHERE company_id = ?', companyId);
31-
return res.map((row) => row.user_id);
63+
export const getEmployeesByCompanyId = async (
64+
companyId: string,
65+
): Promise<CompanyPersonDetails[]> => {
66+
const db = await openDB();
67+
return await db.all('SELECT * FROM companies_people WHERE company_id = ?', companyId);
3268
};

src/components/db.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,20 +188,21 @@ const initCompaniesTable = async (db: Database): Promise<void> => {
188188
`
189189
CREATE TABLE IF NOT EXISTS companies (
190190
company_id VARCHAR(30) PRIMARY KEY NOT NULL,
191+
name VARCHAR(64) NOT NULL,
192+
image_id TEXT,
191193
description TEXT
192194
)`,
193195
);
194196
};
195197

196198
const initPeopleCompaniesTable = async (db: Database): Promise<void> => {
197-
await db.run(
198-
`
199+
await db.run(`
199200
CREATE TABLE IF NOT EXISTS companies_people (
200201
user_id VARCHAR(255) NOT NULL,
201-
company_id VARCHAR(30) NOT NULL,
202+
company_id VARCHAR(32) NOT NULL,
203+
role VARCHAR(64) NOT NULL,
202204
FOREIGN KEY(company_id) REFERENCES companies(company_id)
203-
)`,
204-
);
205+
)`);
205206
};
206207

207208
const initTables = async (db: Database): Promise<void> => {

src/utils/companyInfo.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@ const CRUNCHBASE_ORGANIZATION_API_URL = 'https://api.crunchbase.com/api/v4/entit
77

88
// fields to return from the API. See https://app.swaggerhub.com/apis-docs/Crunchbase/crunchbase-enterprise_api/1.0.3#/Entity/get_entities_organizations__entity_id_ for details
99
// NOTE: was unable to add website and categories, seems like the api is a bit broken
10-
const fields = ['short_description'];
10+
const fields = ['name', 'short_description'];
1111
// eslint-disable-next-line @typescript-eslint/no-unused-vars
12+
13+
interface CrunchbaesCompanyDetails {
14+
short_description: string;
15+
name: string;
16+
identifier: Record<string, unknown>;
17+
}
18+
1219
export const getCrunchbaseCompanyDetails = async (
1320
companyCrunchbaseLink: string,
14-
): Promise<Record<string, unknown>> => {
21+
): Promise<CrunchbaesCompanyDetails> => {
1522
// check if url contains crunchbase.com/organization
1623
// if not, throw error
1724
if (
@@ -46,5 +53,5 @@ export const getCrunchbaseCompanyDetails = async (
4653
throw new CodeyUserError(undefined, data.error);
4754
}
4855

49-
return data;
56+
return data.properties;
5057
};

0 commit comments

Comments
 (0)