Skip to content

Instantly share code, notes, and snippets.

@Biendeo
Created October 31, 2016 10:26
Show Gist options
  • Select an option

  • Save Biendeo/2bfe127cf56e9d41475194f305275d49 to your computer and use it in GitHub Desktop.

Select an option

Save Biendeo/2bfe127cf56e9d41475194f305275d49 to your computer and use it in GitHub Desktop.
BlendoBot
using Discord;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace BlendoBot {
[System.Serializable]
[System.Xml.Serialization.XmlRoot]
[System.Xml.Serialization.XmlInclude(typeof(string))]
public class FileManagerEntry {
[System.Xml.Serialization.XmlElement]
public string name { get; set; }
[System.Xml.Serialization.XmlElement]
public ulong authorId { get; set; }
[System.Xml.Serialization.XmlArray]
[System.Xml.Serialization.XmlArrayItem]
public List<string> files { get; set; }
public FileManagerEntry() : this(null, 0) {}
public FileManagerEntry(string name, ulong authorId) {
this.name = name;
this.authorId = authorId;
files = new List<string>();
}
public bool AddFile(string file) {
if (!files.Contains(file)) {
files.Add(file);
files = files.OrderBy(o=>o).ToList();
return true;
} else {
return false;
}
}
public bool RemoveFile(string file) {
if (files.Contains(file)) {
files.Remove(file);
return true;
} else {
return false;
}
}
public bool RemoveFile(int index) {
if (index >= files.Count) {
return false;
} else {
return RemoveFile(files.ElementAt(index));
}
}
}
class FileManager {
private string filePath;
private SortedList<string, FileManagerEntry> entries;
public FileManager(string filePath) {
this.filePath = filePath;
entries = new SortedList<string, FileManagerEntry>();
if (File.Exists(filePath)) {
Load();
}
}
public void Load() {
var serializer = new XmlSerializer(typeof(List<FileManagerEntry>));
TextReader reader = new StreamReader(filePath);
List<FileManagerEntry> temp = (List<FileManagerEntry>)serializer.Deserialize(reader);
foreach (var o in temp) {
entries.Add(o.name, o);
}
reader.Close();
}
public void Save() {
var serializer = new XmlSerializer(typeof(List<FileManagerEntry>));
TextWriter writer = new StreamWriter(filePath);
List<FileManagerEntry> lists = new List<FileManagerEntry>(entries.Values);
serializer.Serialize(writer, lists);
writer.Close();
}
public bool NewEntry(string name, User author) {
if (entries.ContainsKey(name)) {
return false;
} else {
entries.Add(name, new FileManagerEntry(name, author.Id));
return true;
}
}
public bool RemoveEntry(string name, User author) {
if (Owns(name, author)) {
entries.Remove(name);
return true;
} else {
return false;
}
}
public bool RemoveEntry(int index, User author) {
if (index >= entries.Count) {
return false;
} else {
return RemoveEntry(entries.ElementAt(index).Key, author);
}
}
public bool Owns(string name, User author) {
if (entries.ContainsKey(name) && entries[name].authorId == author.Id) {
return true;
} else {
return false;
}
}
public bool AddToEntry(string name, User author, string item) {
if (Owns(name, author)) {
FileManagerEntry entry;
entries.TryGetValue(name, out entry);
entry.AddFile(item);
return true;
} else {
return false;
}
}
public bool AddToEntry(int index, User author, string item) {
if (index >= entries.Count) {
return false;
} else {
return AddToEntry(entries.ElementAt(index).Key, author, item);
}
}
public bool RemoveFromEntry(string name, User author, string item) {
if (Owns(name, author)) {
FileManagerEntry entry;
entries.TryGetValue(name, out entry);
return entry.RemoveFile(item);
} else {
return false;
}
}
public bool RemoveFromEntry(int index, User author, string item) {
if (index >= entries.Count) {
return false;
} else {
return RemoveFromEntry(entries.ElementAt(index).Key, author, item);
}
}
public bool RemoveFromEntry(string name, User author, int itemIndex) {
if (Owns(name, author)) {
FileManagerEntry entry;
entries.TryGetValue(name, out entry);
return entry.RemoveFile(itemIndex);
} else {
return false;
}
}
public bool RemoveFromEntry(int index, User author, int itemIndex) {
if (index >= entries.Count) {
return false;
} else {
return RemoveFromEntry(entries.ElementAt(index).Key, author, itemIndex);
}
}
public bool Rename(string file, User author, string newName) {
if (Owns(file, author)) {
FileManagerEntry entry;
entries.TryGetValue(file, out entry);
entries.Remove(file);
entry.name = newName;
entries.Add(newName, entry);
return true;
} else {
return false;
}
}
public bool Rename(int index, User author, string newName) {
if (index >= entries.Count) {
return false;
} else {
return Rename(entries.ElementAt(index).Key, author, newName);
}
}
public bool QuickAdd(string file, User author) {
if (entries.ContainsKey(file)) {
return false;
} else {
FileManagerEntry entry = new FileManagerEntry(file, author.Id);
entry.AddFile(file);
entries.Add(file, entry);
return true;
}
}
public List<string> GetEntries() {
return new List<string>(entries.Keys);
}
public List<string> GetFiles(string file) {
if (entries.ContainsKey(file)) {
FileManagerEntry entry;
entries.TryGetValue(file, out entry);
return entry.files;
} else {
return null;
}
}
public List<string> GetFiles(int index) {
if (index >= entries.Count) {
return null;
} else {
return GetFiles(entries.ElementAt(index).Key);
}
}
}
}
<Window x:Class="BlendoBot.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BlendoBot"
mc:Ignorable="d"
Title="BlendoBot Console" Height="350" Width="525"
Icon="https://cdn.discordapp.com/attachments/239933234216042496/242426431118901259/7bd38548ba5955410698a312ee4662cc.jpg"
Closing="Window_Closing">
<Grid>
<TextBox x:Name="inputBox" TextWrapping="NoWrap" Text="" Height="23" VerticalAlignment="Bottom" KeyDown="inputBox_KeyDown" MaxLength="2000"/>
<ScrollViewer Margin="0,0,0,23">
<TextBox x:Name="consoleBox" TextWrapping="Wrap" Text="" IsReadOnly="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</ScrollViewer>
</Grid>
</Window>
using Discord;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BlendoBot {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
private DiscordClient client;
private Channel lastChannelReceived;
private FileManager fileManager;
public MainWindow() {
fileManager = new FileManager("Files.xml");
InitializeComponent();
StartDiscordClient();
}
/// <summary>
/// This is the start of the Discord client program. It attaches all of the actions, then
/// commences a connection.
/// </summary>
public void StartDiscordClient() {
client = new DiscordClient();
client.Log.Message += (s, e) => {
Dispatcher.Invoke(() => {
if (consoleBox.Text != "") {
consoleBox.Text += "\n";
}
consoleBox.Text += $"({DateTime.Now.ToString("hh:mm:ss tt")}) [{e.Severity.ToString()}] {e.Source}: {e.Message}";
});
Console.WriteLine($"[{e.Severity}] {e.Source}: {e.Message}");
};
client.MessageReceived += (s, e) => {
lastChannelReceived = e.Channel;
if (!e.Message.IsAuthor) {
client.Log.Log(LogSeverity.Info, e.Message.User.Nickname, e.Message.Text);
if (DoesTextMentionMe(e.Message)) {
ParseMessage(e.Message);
}
}
};
client.ServerUnavailable += (s, e) => {
PrintInfo("Server unavailable");
};
client.JoinedServer += (s, e) => {
};
client.Ready += (s, e) => {
client.SetGame(new Game("Bastion Main"));
PrintInfo("Connected as: " + client.CurrentUser.Name);
};
// Finish the setup by commencing a connection.
client.Connect("PUT YOUR KEY HERE", TokenType.Bot);
}
private void PrintInfo(string message) {
client.Log.Info("Program", message);
}
private bool DoesTextMentionMe(Message message) {
foreach (User u in message.MentionedUsers) {
if (u.Id == client.CurrentUser.Id) return true;
}
return false;
}
private void ParseMessage(Message message) {
if (Regex.IsMatch(message.Text, "!help")) {
PrintHelp(message.Channel);
} else if (Regex.IsMatch(message.Text, "!file")) {
ParseFileMessage(message);
}
}
private async void ParseFileMessage(Message message) {
List<string> splitString = Regex.Matches(message.Text, @"[\""].+?[\""]|[^ ]+").Cast<Match>().Select(m => m.Value).ToList();
splitString.RemoveAt(0); // @-tag
splitString.RemoveAt(0); // !file
bool success;
try {
if (splitString[0] == "new") {
success = fileManager.NewEntry(splitString[1], message.User);
if (success) {
await SendMessage(lastChannelReceived, "New entry: " + splitString[1]);
} else {
await SendMessage(lastChannelReceived, "I couldn't make a new entry");
}
} else if (splitString[0] == "delete") {
int index;
bool indexSuccess = int.TryParse(splitString[1], out index);
if (indexSuccess) {
success = fileManager.RemoveEntry(index, message.User);
} else {
success = fileManager.RemoveEntry(splitString[1], message.User);
}
if (success) {
await SendMessage(lastChannelReceived, "Entry removed");
} else {
await SendMessage(lastChannelReceived, "I couldn't remove an entry");
}
} else if (splitString[0] == "add") {
if (splitString.Count >= 3) {
int index;
bool indexSuccess = int.TryParse(splitString[1], out index);
if (indexSuccess) {
success = fileManager.AddToEntry(index, message.User, splitString[2]);
} else {
success = fileManager.AddToEntry(splitString[1], message.User, splitString[2]);
}
if (success) {
await SendMessage(lastChannelReceived, "Inserted " + splitString[2] + " into " + splitString[1]);
} else {
await SendMessage(lastChannelReceived, "I couldn't add a file");
}
} else {
await SendMessage(lastChannelReceived, "Invalid arguments");
}
} else if (splitString[0] == "remove") {
if (splitString.Count >= 3) {
int index;
bool indexSuccess = int.TryParse(splitString[1], out index);
List<string> files;
if (indexSuccess) {
files = fileManager.GetFiles(index);
} else {
files = fileManager.GetFiles(splitString[1]);
}
if (files != null) {
int itemIndex;
bool itemIndexSuccess = int.TryParse(splitString[2], out itemIndex);
if (indexSuccess && itemIndexSuccess) {
success = fileManager.RemoveFromEntry(index, message.User, itemIndex);
} else if (!indexSuccess && itemIndexSuccess) {
success = fileManager.RemoveFromEntry(splitString[1], message.User, itemIndex);
} else if (indexSuccess && !itemIndexSuccess) {
success = fileManager.RemoveFromEntry(index, message.User, splitString[2]);
} else {
success = fileManager.RemoveFromEntry(splitString[1], message.User, splitString[2]);
}
if (success) {
await SendMessage(lastChannelReceived, "Removed " + splitString[2] + " from " + splitString[1]);
} else {
await SendMessage(lastChannelReceived, "I couldn't remove that file");
}
} else {
await SendMessage(lastChannelReceived, "That entry doesn't exist");
}
} else {
await SendMessage(lastChannelReceived, "Invalid arguments");
}
} else if (splitString[0] == "rename") {
if (splitString.Count >= 3) {
int index;
bool indexSuccess = int.TryParse(splitString[1], out index);
if (indexSuccess) {
success = fileManager.Rename(index, message.User, splitString[2]);
} else {
success = fileManager.Rename(splitString[1], message.User, splitString[2]);
}
if (success) {
await SendMessage(lastChannelReceived, "Renamed " + splitString[1] + " to " + splitString[2]);
} else {
await SendMessage(lastChannelReceived, "I couldn't add a file");
}
} else {
await SendMessage(lastChannelReceived, "Invalid arguments");
}
} else if (splitString[0] == "quickadd") {
success = fileManager.QuickAdd(splitString[1], message.User);
if (success) {
await SendMessage(lastChannelReceived, "Quickly added new entry: " + splitString[1]);
} else {
await SendMessage(lastChannelReceived, "I couldn't make a new entry");
}
} else if (splitString[0] == "list") {
List<string> entries = fileManager.GetEntries();
string outputMessage = $"{entries.Count} entries total:\n";
if (entries.Count == 0) {
outputMessage = "No entries";
}
for (int i = 0; i < entries.Count; ++i) {
outputMessage += $"{i.ToString().PadLeft(3, ' ')}. {entries.ElementAt(i)}";
if (i != entries.Count && i % 10 == 9) {
await SendMessage(lastChannelReceived, outputMessage);
outputMessage = "";
} else {
if (i != entries.Count) {
outputMessage += "\n";
}
}
}
await SendMessage(lastChannelReceived, outputMessage);
} else if (splitString[0] == "view") {
List<string> files;
int index;
bool indexSuccess = int.TryParse(splitString[1], out index);
if (indexSuccess) {
files = fileManager.GetFiles(index);
} else {
files = fileManager.GetFiles(splitString[1]);
}
if (files != null) {
string outputMessage = $"{files.Count} files total:\n";
for (int i = 0; i < files.Count; ++i) {
outputMessage += $"{i.ToString().PadLeft(3, ' ')}. {files.ElementAt(i)}";
if (i != files.Count && i % 10 == 9) {
await SendMessage(lastChannelReceived, outputMessage);
outputMessage = "";
} else {
if (i != files.Count) {
outputMessage += "\n";
}
}
}
await SendMessage(lastChannelReceived, outputMessage);
} else {
await SendMessage(lastChannelReceived, "I couldn't find an entry");
}
} else if (splitString[0] == "help") {
await PrintFileHelp(lastChannelReceived);
}
} catch (Exception e) {
client.Log.Error("Program", e);
await PrintFileHelp(lastChannelReceived);
}
}
private async Task SendMessage(Channel channel, string message) {
await channel.SendMessage(message);
client.Log.Log(LogSeverity.Info, client.CurrentUser.Name, message);
}
private async Task PrintHelp(Channel channel) {
string helpMessage = "";
helpMessage += "The following commands are available:\n";
helpMessage += "**!file** - Accesses the file management system";
helpMessage += "\n";
helpMessage += "Thanks for using Blendo Bot. Your call is important to us.";
await SendMessage(channel, helpMessage);
}
private async Task PrintFileHelp(Channel channel) {
string helpMessage = "";
helpMessage += "The following commands are available:\n";
helpMessage += "**!file help** - Shows this prompt\n";
helpMessage += "**!file list** - Displays all available entries\n";
helpMessage += "**!file view [index / name]** - Displays all files in a given entry\n";
helpMessage += "**!file new [name]** - Creates a new entry with the given name\n";
helpMessage += "**!file delete [index / name]** - Deletes this entry\n";
helpMessage += "**!file add [index / name] [filePath]** - Creates a new file in the given entry\n";
helpMessage += "**!file remove [index / name] [fileIndex / fileName]** - Removes a file in the given entry\n";
helpMessage += "**!file quickadd [filePath]** - Quickly makes an entry, with the file as the only file\n";
helpMessage += "**!file rename [index / name] [newName]** - Renames an entry\n";
helpMessage += "~~**!file bulkadd [name]** - Creates a new entry, and all future posts (by you) will be added~~\n";
helpMessage += "~~**!file bulkstop** - Stops the current bulkadd~~";
await SendMessage(lastChannelReceived, helpMessage);
}
private async void SendInputBoxMessage() {
if (lastChannelReceived != null) {
await SendMessage(lastChannelReceived, inputBox.Text);
ClearInputBox();
}
}
private void ClearInputBox() {
Dispatcher.Invoke(() => {
inputBox.Text = "";
});
}
private void inputBox_KeyDown(object sender, KeyEventArgs e) {
if (e.Key == Key.Return) {
SendInputBoxMessage();
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
fileManager.Save();
client.Disconnect();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment