From f151e08486ca225f77eb5494150dac0cf71cd3d5 Mon Sep 17 00:00:00 2001 From: maximo Date: Wed, 13 Sep 2023 17:28:24 +0700 Subject: [PATCH] Added stats command --- bot/functions/get_location.ts | 4 +- bot/functions/get_stats.ts | 45 +++++++++++++++++++ bot/functions/send_context.ts | 15 +++++++ bot/manifest.ts | 7 ++- .../create_get_location_info_shortcut.ts | 4 +- bot/triggers/create_get_stats_shortcut.ts | 20 +++++++++ bot/workflows/get_stats_info.ts | 37 +++++++++++++++ database/fetch.ts | 2 +- database/getters.ts | 22 ++++----- 9 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 bot/functions/get_stats.ts create mode 100644 bot/triggers/create_get_stats_shortcut.ts create mode 100644 bot/workflows/get_stats_info.ts diff --git a/bot/functions/get_location.ts b/bot/functions/get_location.ts index 8154244a..674e960d 100644 --- a/bot/functions/get_location.ts +++ b/bot/functions/get_location.ts @@ -10,7 +10,7 @@ import { getDbArgs } from '../util/db-args.ts' import { LocationType } from '../types/location.ts' export const GetLocation = DefineFunction({ - callback_id: 'get_location', + callback_id: 'get_location_info', title: 'Get location', description: 'Gets the location given any of its params.', source_file: 'functions/get_location.ts', @@ -31,7 +31,7 @@ export const GetLocation = DefineFunction({ properties: { location: { type: LocationType, - description: 'The location', + description: 'The location instance', }, }, required: ['location'], diff --git a/bot/functions/get_stats.ts b/bot/functions/get_stats.ts new file mode 100644 index 00000000..a361e540 --- /dev/null +++ b/bot/functions/get_stats.ts @@ -0,0 +1,45 @@ +/* eslint-disable no-console */ + +import { + DefineFunction, + Schema, + SlackFunction, +} from 'https://deno.land/x/deno_slack_sdk@2.2.0/mod.ts' +import { getStats } from '../../database/getters.ts' +import { getDbAuthArgs } from '../util/db-args.ts' + +export const GetStats = DefineFunction({ + callback_id: 'get_stats', + title: 'Get stats', + description: 'Gets the stats from the database', + source_file: 'functions/get_stats.ts', + input_parameters: { + properties: { + environment: { + type: Schema.types.string, + enum: ['Test', 'Production'], + }, + }, + required: ['environment'], + }, + output_parameters: { + properties: { + stats: { + type: Schema.types.object, + description: 'The stats from the database as JSON', + }, + }, + required: ['stats'], + }, +}) + +export default SlackFunction( + GetStats, + async ({ inputs, env }) => { + const res = await getStats(getDbAuthArgs(env, inputs.environment === 'Test')) + console.log(`Fetched stats ${JSON.stringify(res)}`) + return !res || typeof res === 'string' + ? { error: JSON.stringify(res) } + : { outputs: { stats: res } } + }, +) diff --git a/bot/functions/send_context.ts b/bot/functions/send_context.ts index ce55cba2..22b29b15 100644 --- a/bot/functions/send_context.ts +++ b/bot/functions/send_context.ts @@ -18,6 +18,10 @@ export const SendContext = DefineFunction({ type: LocationType, description: 'Name of the location', }, + stats: { + type: Schema.types.object, + description: 'Stats of the database', + }, reviewer: { type: Schema.slack.types.user_id, }, @@ -31,6 +35,7 @@ export const SendContext = DefineFunction({ 'location_deleted', 'location_added', 'location_info', + 'stats', 'info', ], }, @@ -79,6 +84,16 @@ export default SlackFunction( : env.CRYPTO_MAP_DOMAIN, }) break + case 'stats': + text = `:cryptomap: Crypto Map Statistics :bar_chart: + +Message triggered by <@${inputs.reviewer!}>. + + \`\`\` +${JSON.stringify(inputs.stats, null, 2)} + \`\`\` + ` + break case 'info': text = `:cryptomap: Crypto Map Bot Help :cryptomap: diff --git a/bot/manifest.ts b/bot/manifest.ts index 5ac5cea6..27b78514 100644 --- a/bot/manifest.ts +++ b/bot/manifest.ts @@ -4,8 +4,9 @@ import CreateAddLocationPlaceIdWorkflow from './workflows/add_location_place_id. import CreateAddLocationRawWorkflow from './workflows/add_location_manually.ts' import DeleteLocationWorkflow from './workflows/delete_location.ts' import GetLocationInfoWorkflow from './workflows/get_location_info.ts' -import HandleCandidateWorkflow from './workflows/handle_candidate.ts' +import GetStatsWorkflow from './workflows/get_stats_info.ts' import HandleIssueWorkflow from './workflows/handle_issue.ts' +import HandleCandidateWorkflow from './workflows/handle_candidate.ts' import ShowHelpWorkflow from './workflows/show_help.ts' export default Manifest({ @@ -15,15 +16,13 @@ export default Manifest({ workflows: [ CreateAddLocationPlaceIdWorkflow, CreateAddLocationRawWorkflow, + GetStatsWorkflow, DeleteLocationWorkflow, GetLocationInfoWorkflow, HandleCandidateWorkflow, HandleIssueWorkflow, ShowHelpWorkflow, ], - // functions: [ - // CreateLocationWithPlaceId, CreateRawLocation, DeleteLocation, GetLocation, HandleCandidateMessage, HandleIssueMessage, SendContext, UpdateContextMessage, VerifyCaptcha, - // ], outgoingDomains: [ 'www.google.com', 'mycbdmurjytbdahjljoh.supabase.co', diff --git a/bot/triggers/create_get_location_info_shortcut.ts b/bot/triggers/create_get_location_info_shortcut.ts index 0393a35f..4b7dfd34 100644 --- a/bot/triggers/create_get_location_info_shortcut.ts +++ b/bot/triggers/create_get_location_info_shortcut.ts @@ -5,9 +5,7 @@ import { } from 'https://deno.land/x/deno_slack_api@2.1.1/mod.ts' import GetLocationInfoWorkflow from '../workflows/get_location_info.ts' -const createDeleteLocationShortcut: Trigger< - typeof GetLocationInfoWorkflow.definition -> = { +const createDeleteLocationShortcut: Trigger = { type: TriggerTypes.Shortcut, name: 'Get Location info', description: 'Get Location info with a uuid', diff --git a/bot/triggers/create_get_stats_shortcut.ts b/bot/triggers/create_get_stats_shortcut.ts new file mode 100644 index 00000000..73f147ab --- /dev/null +++ b/bot/triggers/create_get_stats_shortcut.ts @@ -0,0 +1,20 @@ +import type { Trigger } from 'https://deno.land/x/deno_slack_sdk@2.2.0/types.ts' +import { + TriggerContextData, + TriggerTypes, +} from 'https://deno.land/x/deno_slack_api@2.1.1/mod.ts' +import GetStatsInfoWorkflow from '../workflows/get_stats_info.ts' + +const createDeleteLocationShortcut: Trigger = { + type: TriggerTypes.Shortcut, + name: 'Get Stats', + description: 'Get Stats from the database', + workflow: `#/workflows/${GetStatsInfoWorkflow.definition.callback_id}`, + inputs: { + interactivity: { + value: TriggerContextData.Shortcut.interactivity, + }, + }, +} + +export default createDeleteLocationShortcut diff --git a/bot/workflows/get_stats_info.ts b/bot/workflows/get_stats_info.ts new file mode 100644 index 00000000..c3df33b1 --- /dev/null +++ b/bot/workflows/get_stats_info.ts @@ -0,0 +1,37 @@ +import { + DefineWorkflow, + Schema, +} from 'https://deno.land/x/deno_slack_sdk@2.2.0/mod.ts' +import { SendContext } from '../functions/send_context.ts' +import { GetStats } from '../functions/get_stats.ts' + +const GetStatsWorkflow = DefineWorkflow({ + callback_id: 'get_stats_wf', + title: 'Get stats', + description: 'Get stats from the database', + input_parameters: { + properties: { + interactivity: { + type: Schema.slack.types.interactivity, + }, + }, + required: ['interactivity'], + }, +}) + +const statsStep = GetStatsWorkflow.addStep( + GetStats, + { environment: 'Production' }, +) + +GetStatsWorkflow.addStep( + SendContext, + { + stats: statsStep.outputs.stats, + environment: 'Production', + reviewer: GetStatsWorkflow.inputs.interactivity.interactor.id, + type: 'stats', + }, +) + +export default GetStatsWorkflow diff --git a/database/fetch.ts b/database/fetch.ts index 745c472b..e558fad0 100644 --- a/database/fetch.ts +++ b/database/fetch.ts @@ -19,7 +19,7 @@ export async function fetchDb Location): Promise { +export async function getLocation(dbArgs: DatabaseArgs, uuid: string, parseLocation: (l: Location) => Location): Promise { const params = new URLSearchParams() params.append('location_uuid', uuid) - const location = await fetchDb(DbReadFunction.GetLocation, { apikey, url: baseUrl }, params.toString()) + const location = await fetchDb(DbReadFunction.GetLocation, dbArgs, params.toString()) if (!location) { console.warn(`Location ${uuid} not found`) return undefined @@ -28,17 +28,17 @@ export async function getLocation({ apikey, url: baseUrl }: DatabaseArgs, uuid: return parseLocation(location) } -export async function searchLocations({ apikey, url: baseUrl }: DatabaseArgs, query: string) { +export async function searchLocations(dbArgs: DatabaseArgs, query: string) { const params = new URLSearchParams() params.append('p_query', query) - return await fetchDb[]>(DbReadFunction.SearchLocations, { apikey, url: baseUrl }, params.toString()) ?? [] + return await fetchDb[]>(DbReadFunction.SearchLocations, dbArgs, params.toString()) ?? [] } -export async function getClusters({ apikey, url: baseUrl }: DatabaseArgs, bbox: BoundingBox, zoom: number, parseLocation: (l: Location) => Location = l => l): Promise { +export async function getClusters(dbArgs: DatabaseArgs, bbox: BoundingBox, zoom: number, parseLocation: (l: Location) => Location = l => l): Promise { const params = new URLSearchParams() Object.entries(bbox).forEach(([key, value]) => params.append(key.toLocaleLowerCase(), value.toString())) params.append('zoom_level', zoom.toString()) - const res = await fetchDb(DbReadFunction.GetLocationsClustersSet, { apikey, url: baseUrl }, params.toString()) + const res = await fetchDb(DbReadFunction.GetLocationsClustersSet, dbArgs, params.toString()) return { clusters: res?.clusters ?? [], singles: res?.singles.map(parseLocation) ?? [], @@ -49,10 +49,10 @@ export async function getClusters({ apikey, url: baseUrl }: DatabaseArgs, bbox: * The maximum zoom level at which the clusters are computed in the database. * If the user zooms in more than this, the clusters will be computed in the client. */ -export async function getClusterMaxZoom({ apikey, url: baseUrl }: DatabaseArgs): Promise { - return await fetchDb(DbReadFunction.GetMaxZoom, { apikey, url: baseUrl }) ?? -1 // FIXME: Show error to user instead of using -1 +export async function getClusterMaxZoom(dbArgs: DatabaseArgs): Promise { + return await fetchDb(DbReadFunction.GetMaxZoom, dbArgs) ?? -1 // FIXME: Show error to user instead of using -1 } -export async function getStats({ apikey, url: baseUrl }: DatabaseArgs): Promise { - return await fetchDb(DbReadFunction.GetStats, { apikey, url: baseUrl }) +export async function getStats(dbArgs: DatabaseAuthArgs): Promise { + return await fetchDb(DbReadFunction.GetStats, dbArgs) }