using System.IO.Compression;
using System.IO;
using System;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
using System.Security.Cryptography;
using Discord.WebSocket;
using PluginManager.Items;
using System.Threading;
using System.Text.Json;
using System.Text;
namespace PluginManager.Others
{
///
/// A special class with functions
///
public static class Functions
{
///
/// The location for the Resources folder
///
public static readonly string dataFolder = @"./Data/Resources/";
///
/// The location for all logs
///
public static readonly string logFolder = @"./Output/Logs/";
///
/// The location for all errors
///
public static readonly string errFolder = @"./Output/Errors/";
///
/// Archives folder
///
public static readonly string pakFolder = @"./Data/Resources/PAK/";
///
/// Beta testing folder
///
public static readonly string betaFolder = @"./Data/BetaTest/";
///
/// Read data from a file that is inside an archive (ZIP format)
///
/// The file name that is inside the archive or its full path
/// The archive location from the PAKs folder
/// A string that represents the content of the file or null if the file does not exists or it has no content
public static Stream? ReadFromPakAsync(string FileName, string archFile)
{
archFile = pakFolder + archFile;
Directory.CreateDirectory(pakFolder);
if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !");
using ZipArchive archive = ZipFile.OpenRead(archFile);
ZipArchiveEntry? entry = archive.GetEntry(FileName);
return entry?.Open();
}
///
/// Write logs to file
///
/// The message to be wrote
public static void WriteLogFile(string LogMessage)
{
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n");
}
///
/// Write error to file
///
/// The message to be wrote
public static void WriteErrFile(string ErrMessage)
{
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n");
}
///
/// Merge one array of strings into one string
///
/// The array of strings
/// The index from where the merge should start (included)
/// A string built based on the array
public static string MergeStrings(this string[] s, int indexToStart)
{
string r = "";
int len = s.Length;
if (len <= indexToStart) return "";
for (int i = indexToStart; i < len - 1; ++i)
{
r += s[i] + " ";
}
r += s[len - 1];
return r;
}
///
/// Get the Operating system you are runnin on
///
/// An Operating system
public static OperatingSystem GetOperatingSystem()
{
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) return OperatingSystem.WINDOWS;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) return OperatingSystem.LINUX;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX)) return OperatingSystem.MAC_OS;
return OperatingSystem.UNKNOWN;
}
public static List GetArguments(SocketMessage message)
{
Command command = new Command(message);
return command.Arguments;
}
///
/// Copy one Stream to another
///
/// The base stream
/// The destination stream
/// The buffer to read
/// The progress
/// The cancellation token
/// Triggered if any is empty
/// Triggered if is less then or equal to 0
/// Triggered if is not readable
/// Triggered in is not writable
public static async Task CopyToOtherStreamAsync(this Stream stream, Stream destination, int bufferSize, IProgress? progress = null, CancellationToken cancellationToken = default)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
if (destination == null) throw new ArgumentNullException(nameof(destination));
if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination));
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
///
/// Extract zip to location
///
/// The zip location
/// The target location
/// The progress that is updated as a file is processed
/// The type of progress
///
public static async Task ExtractArchive(string zip, string folder, IProgress progress, UnzipProgressType type)
{
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip))
{
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{
int totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
else
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
currentZIPFile++;
await Task.Delay(10);
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
}
}
else if (type == UnzipProgressType.PercentageFromTotalSize)
{
ulong zipSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
zipSize += (ulong)entry.CompressedLength;
ulong currentSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/"))
{
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
continue;
}
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
currentSize += (ulong)entry.CompressedLength;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
await Task.Delay(10);
progress.Report((float)currentSize / zipSize * 100);
}
}
}
}
///
/// Convert Bytes to highest measurement unit possible
///
/// The amount of bytes
///
public static (double, string) ConvertBytes(long bytes)
{
List units = new List()
{
"B",
"KB",
"MB",
"GB",
"TB"
};
int i = 0;
while (bytes >= 1024)
{
i++;
bytes /= 1024;
}
return (bytes, units[i]);
}
///
/// Save to JSON file
///
/// The class type
/// The file path
/// The values
///
public static async Task SaveToJsonFile(string file, T Data)
{
File.Delete(file);
var s = File.Open(file, FileMode.OpenOrCreate);
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
s.Close();
}
///
/// Convert json text or file to some kind of data
///
/// The data type
/// The file or json text
///
public static async Task ConvertFromJson(string input)
{
Stream text;
if (File.Exists(input))
text = File.OpenRead(input);
else
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
text.Position = 0;
var obj = await JsonSerializer.DeserializeAsync(text);
text.Close();
return (obj ?? default)!;
}
///
/// Check if all words from are in
/// This function returns true if
/// 1. The is part of
/// 2. The words (split by a space) of are located (separately) in
///
/// The following example will return
/// STRContains("Hello World !", "I type word Hello and then i typed word World !")
/// The following example will return
/// STRContains("Hello World !", "I typed Hello World !"
/// The following example will return
/// STRContains("Hello World", "I type World then Hello")
/// The following example will return
/// STRContains("Hello World !", "I typed Hello World")
///
///
/// The string you are checking
/// The main string that should contain
///
public static bool STRContains(this string str, string baseString)
{
if (baseString.Contains(str)) return true;
string[] array = str.Split(' ');
foreach (var s in array)
if (!baseString.Contains(s))
return false;
return true;
}
public static bool TryReadValueFromJson(string input, string codeName, out JsonElement element)
{
Stream text;
if (File.Exists(input))
text = File.OpenRead(input);
else
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
var jsonObject = JsonDocument.Parse(text);
var data = jsonObject.RootElement.TryGetProperty(codeName, out element);
return data;
}
public static string CreateMD5(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}
}
}