@intocode-io/fireliff-cli
Version:
Command line interface for building LIFF app on Firebase
438 lines (408 loc) • 14.2 kB
JavaScript
import 'console.table';
import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
import './colors-set-theme';
import pjson from '../package.json';
import {
LIFFConfig,
RichMenuAddRequest,
RichMenuDeleteRequest,
RichMenuLinkUserRequest,
RichMenuGetRequest,
RichMenuUploadRequest,
RichMenuSetDefaultRequest,
RichMenuUnlinkUserRequest,
} from './index';
import { commandErrorHandler, getConfig, validateConfig } from './shared';
try {
const commandLineArgs = require('command-line-args');
const { operation, _unknown } = commandLineArgs(
[{ name: 'operation', defaultOption: true }],
{ stopAtFirstUnknown: true }
);
const argv = _unknown || [];
const options = commandLineArgs(
[
{ name: 'id', type: String },
{ name: 'data', type: String },
{ name: 'image', type: String },
{ name: 'name', type: String },
{ name: 'type', type: String },
{ name: 'url', type: String },
{ name: 'user', alias: 'U', type: String },
{ name: 'version', alias: 'v', type: Boolean },
{ name: 'detail', type: Boolean },
],
{ argv }
);
// Commands that need Functions config
if (
['add', 'delete', 'get', 'default', 'link', 'unlink'].indexOf(operation) >
-1
) {
getConfig().then(async (config) => {
let accessToken = config.line.access_token;
let names;
let data;
let dataSrc;
let imageSrc;
let req;
let res;
let uploadReq;
validateConfig(config);
switch (operation) {
case 'add':
req = new RichMenuAddRequest({ accessToken });
dataSrc = path.resolve(process.cwd(), options.data || '');
imageSrc = path.resolve(process.cwd(), options.image || '');
if (
options.data &&
options.image &&
fs.existsSync(dataSrc) &&
fs.existsSync(imageSrc)
) {
data = require(dataSrc);
} else {
console.log('Data file and image file must exist'.error);
process.exit(1);
}
try {
console.log('Sending request to add RichMenu...'.verbose);
res = await req.send(data);
} catch (error) {
console.log(`Failed to add RichMenu`.error);
console.error(error);
process.exit(1);
}
try {
console.log(
`Created ${options.name.input} with RichMenu ID: ${res.data.richMenuId.info}`
.verbose
);
await LIFFConfig.setRichMenu(options.name, res.data.richMenuId);
} catch (error) {
console.log(`Failed to set Functions configuration`.error);
console.log(`Try re-run with the following command`.help);
console.log(
`firebase functions:config:set richmenus.${options.name}=${res.data.richMenuId}`
.code
);
console.error(error);
process.exit(1);
}
try {
console.log(
`Uploading image for RichMenu ${res.data.richMenuId.info}`.verbose
);
uploadReq = new RichMenuUploadRequest({ accessToken });
await uploadReq.send(res.data.richMenuId, imageSrc);
console.log(`Uploaded`);
} catch (error) {
console.log(`Failed to upload image`.error);
console.error(error);
process.exit(1);
}
break;
case 'delete':
req = new RichMenuDeleteRequest({ accessToken });
if (!options.id && !options.name) {
console.warn(
`Command ${
'richmenu delete'.prompt
} required RichMenu ID or name option`.warn
);
console.log(
`Try re-run ${'richmenu delete --id <richMenuId>'.input} OR ${
'richmenu delete --name <richMenuName>'.input
}`.help
);
process.exit(1);
}
if (options.name) {
options.id = await LIFFConfig.getRichMenuIdByName(
options.name,
config
);
if (typeof options.id !== 'string') {
console.error(
`Failed to retrieve RichMenu ID using RichMenu name ${options.name.input}`
.error
);
process.exit(1);
}
}
try {
console.log(
`Sending request to delete RichMenu ${options.id.input}`.verbose
);
res = await req.send(options.id);
console.log(`Deleted RichMenu ID: ${options.id.input}`.verbose);
} catch (error) {
if (error.response && error.response.data) {
if (error.response.data.message) {
console.log(error.response.data.message.info);
} else {
console.log(
`Failed to delete RichMenu ${options.id.input}`.error
);
console.error(error.response.data.error);
process.exit(1);
}
} else {
console.log(
`Failed to delete RichMenu ${options.id.input}`.error
);
console.error(error);
process.exit(1);
}
}
try {
names = await LIFFConfig.getRichMenuNamesById(options.id, config);
await Promise.all(
names.map((name) => LIFFConfig.unsetRichMenu(name))
);
console.log(
`Unset richmenu(s) in Functions configuration`.info,
names
);
} catch (error) {
console.log(
`Failed to unset richmenu(s) in Functions configuration`.error
);
console.log(
`Try looking for RichMenu name with RichMenu ID ${
options.id.input
} using ${'richmenu get'.prompt} command and unset it manually`
.help
);
console.log(
`firebase functions:config:unset richmenus.<richMenuName>`.code
);
console.error(error);
process.exit(1);
}
break;
case 'get':
try {
console.log('Sending request to get RichMenu(s)...'.verbose);
req = new RichMenuGetRequest({ accessToken });
res = await req.send();
if (!res.data.richmenus || res.data.richmenus.length === 0) {
console.log('RichMenu not found');
process.exit(0);
}
} catch (error) {
if (error.response && error.response.data) {
if (error.response.data.message) {
console.log(error.response.data.message.info);
process.exit(0);
} else {
console.error(error.response.data.error);
process.exit(1);
}
} else {
console.error(error);
process.exit(1);
}
}
if (options.detail === true) {
console.log(util.inspect(res.data.richmenus, false, null, true));
} else {
console.table(
res.data.richmenus.map((menu) => {
const richmenus = Object.keys(config.richmenus).filter(
(key) => {
return config.richmenus[key] === menu.richMenuId;
}
);
return {
RichMenu: richmenus.join(', '),
'RichMenu ID': menu.richMenuId,
Size: `${menu.size.width}x${menu.size.height}`,
'Bar Text': menu.chatBarText,
Selected: menu.selected,
'No. of Areas': menu.areas.length,
};
})
);
}
break;
case 'default': // Set menu as default for all users
req = new RichMenuSetDefaultRequest({ accessToken });
if (!options.id && !options.name) {
console.warn(
`Command ${
'richmenu default'.prompt
} required RichMenu ID or name option`.warn
);
console.log(
`Try re-run ${'richmenu default --id <richMenuId>'.input} OR ${
'richmenu default --name <richMenuName>'.input
}`.help
);
process.exit(1);
}
if (options.name) {
options.id = await LIFFConfig.getRichMenuIdByName(
options.name,
config
);
if (typeof options.id !== 'string') {
console.error(
`Failed to retrieve RichMenu ID using RichMenu name ${options.name.input}`
.error
);
process.exit(1);
}
}
try {
console.log(
`Sending request to set RichMenu ${options.id.input} as default`
.verbose
);
res = await req.send(options.id);
console.log(`Set default RichMenu ID: ${options.id.input}`.verbose);
} catch (error) {
if (error.response && error.response.data) {
if (error.response.data.message) {
console.log(error.response.data.message.info);
} else {
console.log(
`Failed to set RichMenu ${options.id.input} as default`.error
);
console.error(error.response.data.error);
process.exit(1);
}
} else {
console.log(
`Failed to set RichMenu ${options.id.input} as default`.error
);
console.error(error);
process.exit(1);
}
}
break;
case 'link': // Link a rich menu to an individual user
req = new RichMenuLinkUserRequest({ accessToken });
if ((!options.id && !options.name) || !options.user) {
console.warn(
`Command ${
'richmenu link'.prompt
} required RichMenu ID or name option, and user option`.warn
);
console.log(
`Try re-run ${
'richmenu link --id <richMenuId> --user <userId>'.input
} OR ${
'richmenu link --name <richMenuName> --user <userId>'.input
}`.help
);
process.exit(1);
}
if (options.name) {
options.id = await LIFFConfig.getRichMenuIdByName(
options.name,
config
);
if (typeof options.id !== 'string') {
console.error(
`Failed to retrieve RichMenu ID using RichMenu name ${options.name.input}`
.error
);
process.exit(1);
}
}
try {
console.log(
`Sending request to link RichMenu ${options.id.input} to User ${options.user}`
.verbose
);
res = await req.send(options.id, options.user);
console.log(
`Linked RichMenu ID ${options.id.input} to User ${options.user.input}`
.verbose
);
} catch (error) {
if (error.response && error.response.data) {
if (error.response.data.message) {
console.log(error.response.data.message.info);
} else {
console.log(
`Failed to link RichMenu ${options.id.input} to User ${options.user.input}`
.error
);
console.error(error.response.data.error);
process.exit(1);
}
} else {
console.log(
`Failed to link RichMenu ${options.id.input} to User ${options.user.input}`
.error
);
console.error(error);
process.exit(1);
}
}
break;
case 'unlink':
req = new RichMenuUnlinkUserRequest({ accessToken });
if (!options.user) {
console.warn(
`Command ${'richmenu unlink'.prompt} required user option`.warn
);
console.log(
`Try re-run ${'richmenu unlink --user <userId>'.input}`.help
);
process.exit(1);
}
try {
console.log(
`Sending request to unlink RichMenu from User ${options.user}`
.verbose
);
res = await req.send(options.user);
console.log(
`Unlinked RichMenu from User ${options.user.input}`.verbose
);
} catch (error) {
if (error.response && error.response.data) {
if (error.response.data.message) {
console.log(error.response.data.message.info);
} else {
console.log(
`Failed to unlink RichMenu from User ${options.user.input}`
.error
);
console.error(error.response.data.error);
process.exit(1);
}
} else {
console.log(
`Failed to unlink RichMenu from User ${options.user.input}`
.error
);
console.error(error);
process.exit(1);
}
}
break;
default:
}
});
} else if (operation) {
switch (operation) {
case 'version':
console.log(`Version: ${pjson.version}`);
break;
case 'help':
default:
// TODO: Display help message
}
} else if (options.version) {
console.log(`Version: ${pjson.version}`);
}
} catch (commandError) {
commandErrorHandler(commandError);
}