From c2bc6e0178cdd14278f7b749647e15d6e5c08a87 Mon Sep 17 00:00:00 2001
From: Ronny Gunawan <3048897+ronnygunawan@users.noreply.github.com>
Date: Sat, 17 Feb 2024 16:01:11 +0700
Subject: [PATCH] Add vps table
---
.../BotUpdate/Message/MessageUpdateHandler.cs | 6 +-
.../SQL/SQLCommandHandler.cs | 103 +++++++++-------
.../GoogleSheets/GoogleSheetsClient.cs | 112 +++++++++++++++++
.../Options/GoogleSheetsOptions.cs | 5 +
.../ServiceCollectionExtensions.cs | 20 +++
.../ServiceCollectionExtensions.cs | 11 ++
.../VPSBenchmark.cs | 7 +-
.../VPSBenchmarkDataSource.cs | 114 ++++++++++++++++++
BotNet.Services/VPS/VPSBenchmarkDataSource.cs | 14 ---
BotNet/Program.cs | 8 +-
10 files changed, 335 insertions(+), 65 deletions(-)
create mode 100644 BotNet.Services/GoogleSheets/GoogleSheetsClient.cs
create mode 100644 BotNet.Services/GoogleSheets/Options/GoogleSheetsOptions.cs
create mode 100644 BotNet.Services/GoogleSheets/ServiceCollectionExtensions.cs
create mode 100644 BotNet.Services/KokizzuVPSBenchmark/ServiceCollectionExtensions.cs
rename BotNet.Services/{VPS => KokizzuVPSBenchmark}/VPSBenchmark.cs (85%)
create mode 100644 BotNet.Services/KokizzuVPSBenchmark/VPSBenchmarkDataSource.cs
delete mode 100644 BotNet.Services/VPS/VPSBenchmarkDataSource.cs
diff --git a/BotNet.CommandHandlers/BotUpdate/Message/MessageUpdateHandler.cs b/BotNet.CommandHandlers/BotUpdate/Message/MessageUpdateHandler.cs
index 55f5a45..495cd29 100644
--- a/BotNet.CommandHandlers/BotUpdate/Message/MessageUpdateHandler.cs
+++ b/BotNet.CommandHandlers/BotUpdate/Message/MessageUpdateHandler.cs
@@ -176,7 +176,8 @@ out AIFollowUpMessage? aiFollowUpMessage
try {
await _telegramBotClient.SendTextMessageAsync(
chatId: update.Message.Chat.Id,
- text: $"Your SQL contains more than one statement.",
+ text: $"Your SQL contains more than one statement.
",
+ parseMode: ParseMode.Html,
replyToMessageId: update.Message.MessageId,
cancellationToken: cancellationToken
);
@@ -192,7 +193,8 @@ await _telegramBotClient.SendTextMessageAsync(
try {
await _telegramBotClient.SendTextMessageAsync(
chatId: update.Message.Chat.Id,
- text: $"Your SQL is not a SELECT statement.",
+ text: $"Your SQL is not a SELECT statement.
",
+ parseMode: ParseMode.Html,
replyToMessageId: update.Message.MessageId,
cancellationToken: cancellationToken
);
diff --git a/BotNet.CommandHandlers/SQL/SQLCommandHandler.cs b/BotNet.CommandHandlers/SQL/SQLCommandHandler.cs
index f80a5ee..828570b 100644
--- a/BotNet.CommandHandlers/SQL/SQLCommandHandler.cs
+++ b/BotNet.CommandHandlers/SQL/SQLCommandHandler.cs
@@ -2,6 +2,7 @@
using BotNet.Commands.SQL;
using BotNet.Services.SQL;
using BotNet.Services.Sqlite;
+using Microsoft.Data.Sqlite;
using Microsoft.Extensions.DependencyInjection;
using SqlParser.Ast;
using Telegram.Bot;
@@ -20,7 +21,8 @@ public async Task Handle(SQLCommand command, CancellationToken cancellationToken
|| froms.Count == 0) {
await _telegramBotClient.SendTextMessageAsync(
chatId: command.Chat.Id,
- text: "No FROM clause found.",
+ text: "No FROM clause found.
",
+ parseMode: ParseMode.Html,
replyToMessageId: command.SQLMessageId,
cancellationToken: cancellationToken
);
@@ -53,9 +55,12 @@ await _telegramBotClient.SendTextMessageAsync(
await _telegramBotClient.SendTextMessageAsync(
chatId: command.Chat.Id,
text: $$"""
- Table '{{table}}' not found. Available tables are:
+ Table '{{table}}' not found. Available tables are:
- pilpres
+ - vps
+
""",
+ parseMode: ParseMode.Html,
replyToMessageId: command.SQLMessageId,
cancellationToken: cancellationToken
);
@@ -68,52 +73,64 @@ await _telegramBotClient.SendTextMessageAsync(
// Execute query
using ScopedDatabase scopedDatabase = serviceScope.ServiceProvider.GetRequiredService();
StringBuilder resultBuilder = new();
- scopedDatabase.ExecuteReader(
- commandText: command.RawStatement,
- readAction: (reader) => {
- string[] values = new string[reader.FieldCount];
-
- // Get column names
- for (int i = 0; i < reader.FieldCount; i++) {
- values[i] = '"' + reader.GetName(i).Replace("\"", "\"\"") + '"';
- }
- resultBuilder.AppendLine(string.Join(',', values));
- // Get rows
- while (reader.Read()) {
+ try {
+ scopedDatabase.ExecuteReader(
+ commandText: command.RawStatement,
+ readAction: (reader) => {
+ string[] values = new string[reader.FieldCount];
+
+ // Get column names
for (int i = 0; i < reader.FieldCount; i++) {
- if (reader.IsDBNull(i)) {
- values[i] = "";
- continue;
- }
+ values[i] = '"' + reader.GetName(i).Replace("\"", "\"\"") + '"';
+ }
+ resultBuilder.AppendLine(string.Join(',', values));
- Type fieldType = reader.GetFieldType(i);
- if (fieldType == typeof(string)) {
- values[i] = '"' + reader.GetString(i).Replace("\"", "\"\"") + '"';
- } else if (fieldType == typeof(int)) {
- values[i] = reader.GetInt32(i).ToString();
- } else if (fieldType == typeof(long)) {
- values[i] = reader.GetInt64(i).ToString();
- } else if (fieldType == typeof(float)) {
- values[i] = reader.GetFloat(i).ToString();
- } else if (fieldType == typeof(double)) {
- values[i] = reader.GetDouble(i).ToString();
- } else if (fieldType == typeof(decimal)) {
- values[i] = reader.GetDecimal(i).ToString();
- } else if (fieldType == typeof(bool)) {
- values[i] = reader.GetBoolean(i).ToString();
- } else if (fieldType == typeof(DateTime)) {
- values[i] = reader.GetDateTime(i).ToString();
- } else if (fieldType == typeof(byte[])) {
- values[i] = BitConverter.ToString(reader.GetFieldValue(i)).Replace("-", "");
- } else {
- values[i] = reader[i].ToString();
+ // Get rows
+ while (reader.Read()) {
+ for (int i = 0; i < reader.FieldCount; i++) {
+ if (reader.IsDBNull(i)) {
+ values[i] = "";
+ continue;
+ }
+
+ Type fieldType = reader.GetFieldType(i);
+ if (fieldType == typeof(string)) {
+ values[i] = '"' + reader.GetString(i).Replace("\"", "\"\"") + '"';
+ } else if (fieldType == typeof(int)) {
+ values[i] = reader.GetInt32(i).ToString();
+ } else if (fieldType == typeof(long)) {
+ values[i] = reader.GetInt64(i).ToString();
+ } else if (fieldType == typeof(float)) {
+ values[i] = reader.GetFloat(i).ToString();
+ } else if (fieldType == typeof(double)) {
+ values[i] = reader.GetDouble(i).ToString();
+ } else if (fieldType == typeof(decimal)) {
+ values[i] = reader.GetDecimal(i).ToString();
+ } else if (fieldType == typeof(bool)) {
+ values[i] = reader.GetBoolean(i).ToString();
+ } else if (fieldType == typeof(DateTime)) {
+ values[i] = reader.GetDateTime(i).ToString();
+ } else if (fieldType == typeof(byte[])) {
+ values[i] = BitConverter.ToString(reader.GetFieldValue(i)).Replace("-", "");
+ } else {
+ values[i] = reader[i].ToString();
+ }
}
+ resultBuilder.AppendLine(string.Join(',', values));
}
- resultBuilder.AppendLine(string.Join(',', values));
}
- }
- );
+ );
+ } catch (SqliteException exc) {
+ await _telegramBotClient.SendTextMessageAsync(
+ chatId: command.Chat.Id,
+ text: "" + exc.Message.Replace("SQLite Error", "Error") + "
",
+ parseMode: ParseMode.Html,
+ replyToMessageId: command.SQLMessageId,
+ cancellationToken: cancellationToken
+ );
+ return;
+ }
// Send result
await _telegramBotClient.SendTextMessageAsync(
@@ -123,8 +140,6 @@ await _telegramBotClient.SendTextMessageAsync(
replyToMessageId: command.SQLMessageId,
cancellationToken: cancellationToken
);
-
- return;
}
private static void CollectTableNames(ref HashSet tables, TableFactor tableFactor) {
diff --git a/BotNet.Services/GoogleSheets/GoogleSheetsClient.cs b/BotNet.Services/GoogleSheets/GoogleSheetsClient.cs
new file mode 100644
index 0000000..c627840
--- /dev/null
+++ b/BotNet.Services/GoogleSheets/GoogleSheetsClient.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Apis.Sheets.v4;
+using Google.Apis.Sheets.v4.Data;
+
+namespace BotNet.Services.GoogleSheets {
+ public sealed class GoogleSheetsClient(
+ SheetsService sheetsService
+ ) {
+ private readonly SheetsService _sheetsService = sheetsService;
+
+ public async Task> GetDataAsync(string spreadsheetId, string range, string firstColumn, CancellationToken cancellationToken) {
+ int firstColumnIndex = GetColumnIndex(firstColumn);
+
+ // Fetch data
+ SpreadsheetsResource.ValuesResource.GetRequest getRequest = _sheetsService.Spreadsheets.Values.Get(
+ spreadsheetId: spreadsheetId,
+ range: range
+ );
+ ValueRange response = await getRequest.ExecuteAsync(cancellationToken);
+
+ // Get type info
+ ConstructorInfo constructor = typeof(T).GetConstructors().Single();
+ PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+
+ // Map data
+ ImmutableList.Builder builder = ImmutableList.CreateBuilder();
+ foreach (IList