From 034010e4edfd0e9900f4dc4f0941e6ae14fbacf9 Mon Sep 17 00:00:00 2001 From: Arthur DANJOU Date: Tue, 26 Oct 2021 18:06:47 +0200 Subject: [PATCH] Move cli commands in core module to use node ace --- ace-manifest.json | 150 ++++++++++++++++++++++++++++++++++++++++++++- commands/Create.ts | 45 ++++++++++++++ commands/Delete.ts | 30 +++++++++ commands/List.ts | 40 ++++++++++++ commands/Logs.ts | 41 +++++++++++++ commands/Update.ts | 49 +++++++++++++++ 6 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 commands/Create.ts create mode 100644 commands/Delete.ts create mode 100644 commands/List.ts create mode 100644 commands/Logs.ts create mode 100644 commands/Update.ts diff --git a/ace-manifest.json b/ace-manifest.json index 79eaee7..b3d95c2 100755 --- a/ace-manifest.json +++ b/ace-manifest.json @@ -1,5 +1,144 @@ { "commands": { + "link:create": { + "settings": { + "loadApp": true, + "stayAlive": false + }, + "commandPath": "./commands/Create", + "commandName": "link:create", + "description": "Quickly and easily create a new link", + "args": [ + { + "type": "string", + "propertyName": "code", + "name": "code", + "required": true, + "description": "Code of the new link" + }, + { + "type": "string", + "propertyName": "target", + "name": "target", + "required": true, + "description": "Target of the new link" + } + ], + "aliases": [ + "new" + ], + "flags": [ + { + "name": "date", + "propertyName": "date", + "type": "string", + "alias": "d", + "description": "Date of the new link (Format: yyyy-MM-dd/HH:mm:ss)" + } + ] + }, + "link:delete": { + "settings": { + "loadApp": true, + "stayAlive": false + }, + "commandPath": "./commands/Delete", + "commandName": "link:delete", + "description": "Delete an existing link", + "args": [ + { + "type": "string", + "propertyName": "code", + "name": "code", + "required": true, + "description": "Code of the new link" + } + ], + "aliases": [ + "del", + "remove", + "rem" + ], + "flags": [] + }, + "link:list": { + "settings": { + "loadApp": true, + "stayAlive": false + }, + "commandPath": "./commands/List", + "commandName": "link:list", + "description": "List all your links", + "args": [], + "aliases": [ + "link:ls" + ], + "flags": [] + }, + "link:logs": { + "settings": { + "loadApp": true, + "stayAlive": false + }, + "commandPath": "./commands/Logs", + "commandName": "link:logs", + "description": "Retrieves the number of visits of a link", + "args": [ + { + "type": "string", + "propertyName": "code", + "name": "code", + "required": true, + "description": "Code of the new link" + } + ], + "aliases": [ + "link:stats", + "link:show" + ], + "flags": [] + }, + "link:update": { + "settings": { + "loadApp": true, + "stayAlive": false + }, + "commandPath": "./commands/Update", + "commandName": "link:update", + "description": "Update an existing link", + "args": [ + { + "type": "string", + "propertyName": "code", + "name": "code", + "required": true, + "description": "Code of the new link" + } + ], + "aliases": [ + "set" + ], + "flags": [ + { + "name": "new-code", + "propertyName": "new_code", + "type": "string", + "description": "The new code of the link" + }, + { + "name": "target", + "propertyName": "target", + "type": "string", + "description": "The new target of the link" + }, + { + "name": "expire", + "propertyName": "expire", + "type": "string", + "description": "The new expiration date of the link" + } + ] + }, "dump:rcfile": { "settings": {}, "commandPath": "@adonisjs/core/build/commands/DumpRc", @@ -263,5 +402,14 @@ ] } }, - "aliases": {} + "aliases": { + "new": "link:create", + "del": "link:delete", + "remove": "link:delete", + "rem": "link:delete", + "link:ls": "link:list", + "link:stats": "link:logs", + "link:show": "link:logs", + "set": "link:update" + } } diff --git a/commands/Create.ts b/commands/Create.ts new file mode 100644 index 0000000..b7d9b95 --- /dev/null +++ b/commands/Create.ts @@ -0,0 +1,45 @@ +import {args, BaseCommand, flags} from '@adonisjs/core/build/standalone' +import {DateTime} from "luxon"; +import Link from "App/Models/Link"; +import User from "App/Models/User"; +import Env from "@ioc:Adonis/Core/Env"; + +export default class Create extends BaseCommand { + + public static commandName = 'link:create' + + public static description = 'Quickly and easily create a new link' + + public static aliases = ['new'] + + public static settings = { + loadApp: true, + stayAlive: false, + } + + @args.string({ description: 'Code of the new link' }) + public code: string + + @args.string({ description: 'Target of the new link' }) + public target: string + + @flags.string({ alias: 'd', description: 'Date of the new link (Format: yyyy-MM-dd/HH:mm:ss)' }) + public date: string + + public async run () { + const exist = await Link.findBy('code', this.code) + if (exist) { + this.logger.warning(`The link with code '${this.code}' already exists!`) + return + } + + await Link.create({ + code: this.code, + target: this.target, + type: this.date ? 'TEMPORARY' : 'PERMANENT', + expire: DateTime.fromJSDate(new Date(this.date || new Date())) ?? null, + authorId: (await User.findByOrFail('email', Env.get('ADMIN_USER'))).id + }) + this.logger.info(`The link '${this.colors.yellow(this.code)}' was successfully created!`) + } +} diff --git a/commands/Delete.ts b/commands/Delete.ts new file mode 100644 index 0000000..b7e8716 --- /dev/null +++ b/commands/Delete.ts @@ -0,0 +1,30 @@ +import {args, BaseCommand} from '@adonisjs/core/build/standalone' +import Link from "App/Models/Link"; + +export default class Delete extends BaseCommand { + + public static commandName = 'link:delete' + + public static description = 'Delete an existing link' + + public static aliases = ['del', 'remove', 'rem'] + + public static settings = { + loadApp: true, + stayAlive: false, + } + + @args.string({ description: 'Code of the new link' }) + public code: string + + public async run () { + const link = await Link.findBy('code', this.code) + if (!link) { + this.logger.warning(`The link with code '${this.code}' does not exist!`) + return + } + await link.related('author').dissociate() + await link.delete() + this.logger.info(`The link '${this.colors.yellow(link.code)}' was successfully deleted!`) + } +} diff --git a/commands/List.ts b/commands/List.ts new file mode 100644 index 0000000..1b5339b --- /dev/null +++ b/commands/List.ts @@ -0,0 +1,40 @@ +import { BaseCommand } from '@adonisjs/core/build/standalone' +import Link from "App/Models/Link"; + +export default class List extends BaseCommand { + + public static commandName = 'link:list' + + public static description = 'List all your links' + + public static aliases = ['link:ls'] + + public static settings = { + loadApp: true, + stayAlive: false, + } + + public async run () { + const table = this.ui.table() + table.head(['Id', 'Code', 'Target', 'Clicks count', 'Author', 'Type', 'Expire']) + + const links = await Link + .query() + .preload('clicks') + .preload('author') + .orderBy('id', 'asc') + links.forEach((link) => { + table.row([ + `${link.id}`, + link.code, + link.target, + link.clicks.length > 0 ? this.colors.yellow(String(link.clicks.length)) : this.colors.grey('0'), + link.author.email, + link.type, + link.type === 'TEMPORARY' ? link.expire!.toSQL() : this.colors.grey('Never') + ]) + }) + + table.render() + } +} diff --git a/commands/Logs.ts b/commands/Logs.ts new file mode 100644 index 0000000..4d20f38 --- /dev/null +++ b/commands/Logs.ts @@ -0,0 +1,41 @@ +import {args, BaseCommand} from '@adonisjs/core/build/standalone' +import Link from "App/Models/Link"; + +export default class Logs extends BaseCommand { + + public static commandName = 'link:logs' + + public static description = 'Retrieves the number of visits of a link' + + public static aliases = ['link:stats', 'link:show'] + + public static settings = { + loadApp: true, + stayAlive: false, + } + + @args.string({ description: 'Code of the new link' }) + public code: string + + public async run () { + const link = await Link.findBy('code', this.code) + if (!link) { + this.logger.warning(`The link with code '${this.code}' does not exist!`) + return + } + await link.load('clicks') + const table = this.ui.table() + table.head(['Id', 'IP', 'Country', 'Date']) + + link.clicks.forEach((click) => { + table.row([ + `${click.id}`, + click.ip, + click.country.length == 0 ? this.colors.grey('Unknown') : click.country, + click.date.toSQL() + ]) + }) + + table.render() + } +} diff --git a/commands/Update.ts b/commands/Update.ts new file mode 100644 index 0000000..11ab198 --- /dev/null +++ b/commands/Update.ts @@ -0,0 +1,49 @@ +import {args, BaseCommand, flags} from '@adonisjs/core/build/standalone' +import Link from "App/Models/Link"; +import {DateTime} from "luxon"; + +export default class Update extends BaseCommand { + + public static commandName = 'link:update' + + public static description = 'Update an existing link' + + public static aliases = ['set'] + + public static settings = { + loadApp: true, + stayAlive: false, + } + + @args.string({ description: 'Code of the new link' }) + public code: string + + @flags.string({ name: 'code', description: 'The new code of the link' }) + public new_code: string + + @flags.string({ description: 'The new target of the link' }) + public target: string + + @flags.string({ description: 'The new expiration date of the link' }) + public expire: string + + public async run () { + const link = await Link.findBy('code', this.code) + if (!link) { + this.logger.warning(`The link with code '${this.code}' does not exist!`) + return + } + if (this.target) { + link.target = this.target + const clicks = await link.related('clicks').query() + clicks.forEach(click => click.delete()) + } + if (this.new_code) link.code = this.new_code + if (this.expire) { + (this.expire == 'PERMANENT'.toLowerCase() || this.expire == 'PERM'.toLowerCase()) ? link.type = 'PERMANENT' : link.type = 'TEMPORARY' + link.expire = DateTime.fromJSDate(new Date(this.expire || new Date())) ?? null + } + await link.save() + this.logger.info('The user was successfully updated!') + } +}