Initial commit

Enjoy
This commit is contained in:
Master Kwoth 2015-12-05 11:27:00 +01:00
parent 81642424aa
commit a909d69e4a
30 changed files with 2773 additions and 0 deletions

231
.gitignore vendored Normal file
View File

@ -0,0 +1,231 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Azure Emulator
ecf/
rcf/
# Windows Store app package directory
AppPackages/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/

25
NadekoBot.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot", "NadekoBot\NadekoBot.csproj", "{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
FullDebug|Any CPU = FullDebug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

14
NadekoBot/App.config Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

155
NadekoBot/Classes/Cards.cs Normal file
View File

@ -0,0 +1,155 @@
using System.Collections.Generic;
using System.Linq;
using System;
public class Cards
{
private static Dictionary<int, string> cardNames = new Dictionary<int, string>() {
{ 1, "Ace" },
{ 2, "Two" },
{ 3, "Three" },
{ 4, "Four" },
{ 5, "Five" },
{ 6, "Six" },
{ 7, "Seven" },
{ 8, "Eight" },
{ 9, "Nine" },
{ 10, "Ten" },
{ 11, "Jack" },
{ 12, "Queen" },
{ 13, "King" },
};
public enum CARD_SUIT
{
Spades = 1,
Hearts = 2,
Diamonds = 3,
Clubs = 4
}
public class Card
{
public CARD_SUIT suit;
public int number;
public string Path
{
get
{
string str = "";
if (number <= 10 && number > 1)
{
str += number;
}
else
{
str += GetName().ToLower();
}
return @"images/cards/" + str + "_of_" + suit.ToString().ToLower() + ".jpg";
}
}
public Card(CARD_SUIT s, int card_num) {
this.suit = s;
this.number = card_num;
}
public string GetName() {
return cardNames[number];
}
public override string ToString()
{
return cardNames[number] + " Of " + suit;
}
}
private List<Card> cardPool;
public List<Card> CardPool
{
get { return cardPool; }
set { cardPool = value; }
}
/// <summary>
/// Creates a new instance of the BlackJackGame, this allows you to create multiple games running at one time.
/// </summary>
public Cards()
{
cardPool = new List<Card>(52);
RefillPool();
}
/// <summary>
/// Restart the game of blackjack. It will only refill the pool for now. Probably wont be used, unless you want to have only 1 bjg running at one time,
/// then you will restart the same game every time.
/// </summary>
public void Restart()
{
// you dont have to uncover what is actually happening anda da hood
RefillPool();
}
/// <summary>
/// Removes all cards from the pool and refills the pool with all of the possible cards. NOTE: I think this is too expensive.
/// We should probably make it so it copies another premade list with all the cards, or something.
/// </summary>
private void RefillPool()
{
cardPool.Clear();
//foreach suit
for (int j = 1; j < 14; j++)
{
// and number
for (int i = 1; i < 5; i++)
{
//generate a card of that suit and number and add it to the pool
// the pool will go from ace of spades,hears,diamonds,clubs all the way to the king of spades. hearts, ...
cardPool.Add(new Card((CARD_SUIT)i, j));
}
}
}
/// <summary>
/// Take a card from the pool, you either take it from the top if the deck is shuffled, or from a random place if the deck is in the default order.
/// </summary>
/// <returns>A card from the pool</returns>
public Card DrawACard()
{
if (CardPool.Count > 0)
{
//you can either do this if your deck is not shuffled
Random r = new Random((int)DateTime.Now.Ticks);
int num = r.Next(0, cardPool.Count);
Card c = cardPool[num];
cardPool.RemoveAt(num);
return c;
// if you want to shuffle when you fill, then take the first one
/*
Card c = cardPool[0];
cardPool.RemoveAt(0);
return c;
*/
}
else {
//for now return null
Restart();
return null;
}
}
/// <summary>
/// Shuffles the deck. Use this if you want to take cards from the top of the deck, instead of randomly. See DrawACard method.
/// </summary>
private void Shuffle() {
if (cardPool.Count > 1)
{
Random r = new Random();
cardPool.OrderBy(x => r.Next());
}
}
//public override string ToString() => string.Join("", cardPool.Select(c => c.ToString())) + Environment.NewLine;
public override string ToString() => string.Join("", cardPool.Select(c => c.ToString())) + Environment.NewLine;
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace NadekoBot
{
public static class Extensions
{
public static void Shuffle<T>(this IList<T> list)
{
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot
{
class ImageHandler
{
/// <summary>
/// Merges Images into 1 Image and returns a bitmap.
/// </summary>
/// <param name="images">The Images you want to merge.</param>
/// <returns>Merged bitmap</returns>
public static Bitmap MergeImages(Image[] images)
{
int width = images.Sum(i => i.Width);
int height = images[0].Height;
Bitmap bitmap = new Bitmap(width, height);
var r = new Random();
int offsetx = 0;
foreach (var img in images)
{
Bitmap bm = new Bitmap(img);
for (int w = 0; w < img.Width; w++)
{
for (int h = 0; h < img.Height; h++)
{
bitmap.SetPixel(w + offsetx, h, bm.GetPixel(w, h));
}
}
offsetx += img.Width;
}
return bitmap;
}
}
}

315
NadekoBot/Classes/Trivia.cs Normal file
View File

@ -0,0 +1,315 @@
using Discord;
using Discord.Commands;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace NadekoBot
{
public class Trivia : DiscordCommand
{
public static Dictionary<long, TriviaGame> runningTrivias;
public Trivia() : base() {
runningTrivias = new Dictionary<long, TriviaGame>();
}
public static TriviaGame StartNewGame(CommandEventArgs e) {
if (runningTrivias.ContainsKey(e.User.Server.Id))
return null;
var tg = new TriviaGame(e, NadekoBot.client);
runningTrivias.Add(e.Server.Id, tg);
return tg;
}
public TriviaQuestion GetCurrentQuestion(long serverId) {
return runningTrivias[serverId].currentQuestion;
}
public override Func<CommandEventArgs, Task> DoFunc()
{
return async e =>
{
TriviaGame tg;
if ((tg = StartNewGame(e))!=null)
{
await client.SendMessage(e.Channel, "**Trivia game started!** It is bound to this channel. But only 1 game can run per server. \n First player to get to 10 points wins! You have 30 seconds per question.\nUse command [tq] if game was started by accident.");
}
else
await client.SendMessage(e.Channel, "Trivia game is already running on this server. The question is:\n**"+GetCurrentQuestion(e.Server.Id).Question+"**\n[tq quits trivia]\n[@NadekoBot clr clears my messages]"); // TODO type x to be reminded of the question
};
}
private Func<CommandEventArgs, Task> LbFunc()
{
return async e =>
{
if (runningTrivias.ContainsKey(e.Server.Id))
{
var lb = runningTrivias[e.User.Server.Id].GetLeaderboard();
await client.SendMessage(e.Channel, lb);
}
else
await client.SendMessage(e.Channel, "Trivia game is not running on this server."); // TODO type x to be reminded of the question
};
}
private Func<CommandEventArgs, Task> RepeatFunc()
{
return async e =>
{
if (runningTrivias.ContainsKey(e.Server.Id))
{
var lb = runningTrivias[e.User.Server.Id].GetLeaderboard();
await client.SendMessage(e.Channel, lb);
}
else
await client.SendMessage(e.Channel, "Trivia game is not running on this server."); // TODO type x to be reminded of the question
};
}
public override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("t")
.Description("Starts a game of trivia. Questions suck and repeat a lot atm.")
.Alias("-t")
.Do(DoFunc());
cgb.CreateCommand("tl")
.Description("Shows a current trivia leaderboard.")
.Alias("-tl")
.Alias("tlb")
.Alias("-tlb")
.Do(LbFunc());
cgb.CreateCommand("tq")
.Description("Quits current trivia after current question.")
.Alias("-tq")
.Do(QuitFunc());
}
private Func<CommandEventArgs, Task> QuitFunc()
{
return async e =>
{
if (runningTrivias.ContainsKey(e.Server.Id) && runningTrivias[e.Server.Id].ChannelId ==e.Channel.Id)
{
await client.SendMessage(e.Channel, "Trivia will stop after this question. Run [**@NadekoBot clr**] to remove this bot's messages from the channel.");
runningTrivias[e.Server.Id].StopGame();
}
else await client.SendMessage(e.Channel, "No trivias are running on this channel.");
};
}
internal static void FinishGame(TriviaGame triviaGame)
{
runningTrivias.Remove(runningTrivias.Where(kvp => kvp.Value == triviaGame).First().Key);
}
}
public class TriviaGame {
private DiscordClient client;
private long _serverId;
private long _channellId;
public long ChannelId
{
get
{
return _channellId;
}
}
private Dictionary<long, int> users;
public List<string> oldQuestions;
public TriviaQuestion currentQuestion = null;
private bool active = false;
private Timer timeout;
private bool isQuit = false;
public TriviaGame(CommandEventArgs starter, DiscordClient client) {
this.users = new Dictionary<long, int>();
this.client = client;
this._serverId = starter.Server.Id;
this._channellId= starter.Channel.Id;
oldQuestions = new List<string>();
client.MessageReceived += PotentialGuess;
timeout = new Timer();
timeout.Interval = 30000;
timeout.Elapsed += (s, e) => { TimeUp(); };
LoadNextRound();
}
private async void PotentialGuess(object sender, MessageEventArgs e)
{
if (e.Server.Id != _serverId || !active)
return;
if (e.Message.Text.ToLower() == currentQuestion.Answer.ToLower())
{
active = false; //start pause between rounds
timeout.Enabled = false;
if (!users.ContainsKey(e.User.Id))
users.Add(e.User.Id, 1);
else
{
users[e.User.Id]++;
}
await client.SendMessage(e.Channel, Mention.User(e.User) + " Guessed it!\n The answer was: **" + currentQuestion.Answer + "**");
if (users[e.User.Id] >= 10) {
await client.SendMessage(e.Channel, " We have a winner! It's " + Mention.User(e.User)+"\n"+GetLeaderboard()+"\n To start a new game type '@NadekoBot t'");
FinishGame();
return;
}
//if it still didnt return, we can safely start another round :D
LoadNextRound();
}
}
public void StopGame() {
isQuit = true;
}
private void LoadNextRound()
{
Channel ch = client.GetChannel(_channellId);
if(currentQuestion!=null)
oldQuestions.Add(currentQuestion.Question);
currentQuestion = TriviaQuestionsPool.Instance.GetRandomQuestion(oldQuestions);
if (currentQuestion == null || isQuit)
{
client.SendMessage(ch, "Trivia bot stopping. :\\\n" + GetLeaderboard());
FinishGame();
return;
}
Timer t = new Timer();
t.Interval = 2500;
t.Enabled = true;
t.Elapsed += async (s, ev) => {
active = true;
await client.SendMessage(ch, "QUESTION\n**" + currentQuestion.Question + " **");
t.Enabled = false;
timeout.Enabled = true;//starting countdown of the next question
};
return;
}
private async void TimeUp() {
await client.SendMessage(client.GetChannel(_channellId), "**Time's up.**\nCorrect answer was: **" + currentQuestion.Answer+"**\n**[tq quits trivia][tl shows leaderboard][@NadekoBot clr clears my messages]**");
LoadNextRound();
}
public void FinishGame() {
isQuit = true;
active = false;
client.MessageReceived -= PotentialGuess;
timeout.Enabled = false;
timeout.Dispose();
Trivia.FinishGame(this);
}
public string GetLeaderboard() {
if (users.Count == 0)
return "";
string str = "**Leaderboard:**\n-----------\n";
if(users.Count>1)
users.OrderBy(kvp => kvp.Value);
foreach (var KeyValuePair in users)
{
str += "**" + client.GetUser(client.GetServer(_serverId), KeyValuePair.Key).Name + "** has " +KeyValuePair.Value + (KeyValuePair.Value == 1 ? "point." : "points.") + Environment.NewLine;
}
return str;
}
}
public class TriviaQuestion {
public string Question;
public string Answer;
public TriviaQuestion(string q, string a) {
this.Question = q;
this.Answer = a;
}
public override string ToString()
{
return this.Question;
}
}
public class TriviaQuestionsPool {
private static TriviaQuestionsPool instance = null;
public static TriviaQuestionsPool Instance
{
get {
if (instance == null)
instance = new TriviaQuestionsPool();
return instance;
}
private set { instance = value; }
}
public List<TriviaQuestion> pool;
private Random _r;
public TriviaQuestionsPool() {
_r = new Random();
pool = new List<TriviaQuestion>();
var httpClient = new System.Net.Http.HttpClient();
var r = httpClient.GetAsync("http://jservice.io/api/clues?category=19").Result;
string str = r.Content.ReadAsStringAsync().Result;
dynamic obj = JArray.Parse(str);
foreach (var item in obj)
{
pool.Add(new TriviaQuestion((string)item.question,(string)item.answer));
}
}
public TriviaQuestion GetRandomQuestion(List<string> exclude) {
if (pool.Count == 0)
return null;
TriviaQuestion tq = pool[_r.Next(0, pool.Count)];
if (exclude.Count > 0 && exclude.Count < pool.Count)
{
while (exclude.Contains(tq.Question))
{
tq = pool[_r.Next(0, pool.Count)];
}
}
return tq;
}
}
}

View File

@ -0,0 +1,56 @@
namespace NadekoBot
{
public class Credentials
{
public string Username;
public string Password;
public string BotMention;
public string GoogleAPIKey;
public long OwnerID;
public bool Crawl;
public string ParseID;
public string ParseKey;
}
class AnimeResult
{
public int id;
public string airing_status;
public string title_english;
public int total_episodes;
public string description;
public string image_url_lge;
public override string ToString()
{
return "`Title:` **" + title_english +
"**\n`Status:` " + airing_status +
"\n`Episodes:` " + total_episodes +
"\n`Link:` http://anilist.co/anime/" + id +
"\n`Synopsis:` " + description.Substring(0, description.Length > 500 ? 500 : description.Length) + "..." +
"\n`img:` " + image_url_lge;
}
}
class MangaResult
{
public int id;
public string publishing_status;
public string image_url_lge;
public string title_english;
public int total_chapters;
public int total_volumes;
public string description;
public override string ToString()
{
return "`Title:` **" + title_english +
"**\n`Status:` " + publishing_status +
"\n`Chapters:` " + total_chapters +
"\n`Volumes:` " + total_volumes +
"\n`Link:` http://anilist.co/manga/" + id +
"\n`Synopsis:` " + description.Substring(0, description.Length > 500 ? 500 : description.Length) + "..." +
"\n`img:` " + image_url_lge;
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
namespace NadekoBot
{
class CopyCommand : DiscordCommand
{
private List<long> CopiedUsers;
public CopyCommand() : base()
{
CopiedUsers = new List<long>();
client.MessageReceived += Client_MessageReceived;
}
private async void Client_MessageReceived(object sender, Discord.MessageEventArgs e)
{
if (CopiedUsers.Contains(e.User.Id)) {
await client.SendMessage(e.Channel, e.Message.Text);
}
}
public override Func<CommandEventArgs, Task> DoFunc()
{
return async e =>
{
if (CopiedUsers.Contains(e.User.Id)) return;
CopiedUsers.Add(e.User.Id);
await client.SendMessage(e.Channel, " I'll start copying you now.");
return;
};
}
public override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("copyme")
.Alias("cm")
.Description("Nadeko starts copying everything you say. Disable with cs")
.Do(DoFunc());
cgb.CreateCommand("cs")
.Alias("copystop")
.Description("Nadeko stops copying you")
.Do(StopCopy());
}
private Func<CommandEventArgs, Task> StopCopy()
{
return async e =>
{
if (!CopiedUsers.Contains(e.User.Id)) return;
CopiedUsers.Remove(e.User.Id);
await client.SendMessage(e.Channel, " I wont copy anymore.");
return;
};
}
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.Modules;
using Discord;
using System.Drawing;
namespace NadekoBot
{
class DiceRollCommand : DiscordCommand
{
public DiceRollCommand() : base() { }
public override Func<CommandEventArgs, Task> DoFunc()
{
Random r = new Random();
return async e => {
if (e.Args[0] == "")
{
int num1 = r.Next(0, 10);
int num2 = r.Next(0, 10);
Console.WriteLine(num1+"|"+num2);
Image[] images;
if (num1 == 0 && num2 == 0 && r.Next(0, 2) == 1)
{
images = new Image[3] { GetDice(1), GetDice(0), GetDice(0) };
}
else
{
images = new Image[2] { GetDice(num1), GetDice(num2) };
}
Bitmap bitmap = ImageHandler.MergeImages(images);
bitmap.Save("dices.png");
await client.SendFile(e.Channel, "dices.png");
return;
}
else
{
try
{
int num = int.Parse(e.Args[0]);
if (num < 1) num = 1;
if (num > 30)
{
await client.SendMessage(e.Channel, "You can roll up to 30 dies at a time.");
num = 30;
}
List<Image> dices = new List<Image>(num);
List<int> values = new List<int>(num);
for (int i = 0; i < num; i++)
{
int randomNumber = r.Next(1, 7);
int toInsert = dices.Count;
if (randomNumber == 6 || dices.Count==0)
toInsert = 0;
else if (randomNumber!=1)
for (int j = 0; j < dices.Count; j++) {
if (values[j] < randomNumber)
{
toInsert = j;
break;
}
}
dices.Insert(toInsert, GetDice(randomNumber));
values.Insert(toInsert, randomNumber);
}
Bitmap bitmap = ImageHandler.MergeImages(dices.ToArray());
bitmap.Save("dices.png");
await client.SendMessage(e.Channel, values.Count + " Dies rolled. Total: **"+values.Sum()+"** Average: **"+(values.Sum()/(1.0f*values.Count)).ToString("N2")+"**");
await client.SendFile(e.Channel, "dices.png");
}
catch (Exception)
{
await client.SendMessage(e.Channel, "Please enter a number of dices to roll.");
return;
}
}
};
}
private Image GetDice(int num) {
return Image.FromFile("images/dice/"+num+".png");
}
public override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("$roll")
.Description("Rolls 2 dice from 0-10. If you supply a number [x] it rolls up to 30 normal dice.\nUsage: $roll [x]")
.Parameter("num", ParameterType.Optional)
.Do(DoFunc());
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
namespace NadekoBot
{
/// <summary>
/// Base DiscordCommand Class.
/// Inherit this class to create your own command.
/// </summary>
public abstract class DiscordCommand
{
/// <summary>
/// Client at the moment of creating this object
/// </summary>
public DiscordClient client { get; set; }
/// <summary>
/// Constructor of the base class
/// </summary>
/// <param name="cb">CommandBuilder which will be modified</param>
protected DiscordCommand()
{
client = NadekoBot.client;
}
/// <summary>
/// Function containing the behaviour of the command.
/// </summary>
/// <param name="client">Client who will handle the message sending, etc, if any.</param>
/// <returns></returns>
public abstract Func<CommandEventArgs,Task> DoFunc();
/// <summary>
/// Initializes the CommandBuilder with values
/// </summary>
public abstract void Init(CommandGroupBuilder cgb);
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord;
using System.Drawing;
namespace NadekoBot
{
class DrawCommand : DiscordCommand
{
private Cards cards = null;
public DrawCommand() : base() { }
public override Func<CommandEventArgs,Task> DoFunc() {
return async (e) =>
{
if (cards == null)
{
cards = new Cards();
await client.SendMessage(e.Channel, "Shuffling cards...");
}
try
{
int num = int.Parse(e.Args[0]);
if (num > 5)
{
num = 5;
}
else if (num < 1)
{
num = 1;
}
Image[] images = new Image[num];
for (int i = 0; i < num; i++)
{
if (cards.CardPool.Count == 0)
{
await client.SendMessage(e.Channel, "No more cards in a deck...\nGetting a new deck...\nShuffling cards...");
}
images[i] = Image.FromFile(cards.DrawACard().Path);
}
Bitmap bitmap = ImageHandler.MergeImages(images);
bitmap.Save("cards.png");
await client.SendFile(e.Channel, "cards.png");
}
catch (Exception) {
Console.WriteLine("Error drawing (a) card(s)");
}
};
}
public override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("$draw")
.Description("Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck.\nUsage: $draw [x]")
.Parameter("count", ParameterType.Multiple)
.Do(DoFunc());
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Threading.Tasks;
using Discord.Commands;
namespace NadekoBot
{
class FlipCoinCommand : DiscordCommand
{
private Random _r;
public FlipCoinCommand() : base()
{
_r = new Random();
}
public override Func<CommandEventArgs, Task> DoFunc()
{
return async e => {
int num = _r.Next(0, 2);
if (num == 1)
{
await client.SendFile(e.Channel, @"images/coins/heads.png");
}
else
{
await client.SendFile(e.Channel, @"images/coins/tails.png");
}
};
}
public override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("$flip")
.Description("Flips a coin, heads or tails, and shows an image of it.")
.Do(DoFunc());
}
}
}

View File

@ -0,0 +1,585 @@
using Discord;
using Discord.Commands;
using Discord.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Drawing;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Text;
namespace NadekoBot.Modules
{
class Conversations : DiscordModule
{
private string firestr = "🔥 ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้ 🔥";
public Conversations() : base()
{
commands.Add(new CopyCommand());
}
private CommandBuilder CreateCommand(CommandGroupBuilder cbg, string txt)
{
CommandBuilder cb = cbg.CreateCommand(txt);
return AliasCommand(cb, txt);
}
private CommandBuilder AliasCommand(CommandBuilder cb, string txt)
{
return cb.Alias(new string[] { "," + txt, "-" + txt });
}
public override void Install(ModuleManager manager)
{
Random rng = new Random();
manager.CreateCommands("", cgb =>
{
var client = manager.Client;
cgb.CreateCommand("\\o\\")
.Description("Nadeko replies with /o/")
.Do(async e =>
{
await client.SendMessage(e.Channel, Mention.User(e.User) + "/o/");
});
cgb.CreateCommand("/o/")
.Description("Nadeko replies with \\o\\")
.Do(async e =>
{
await client.SendMessage(e.Channel, Mention.User(e.User) + "\\o\\");
});
});
manager.CreateCommands(NadekoBot.botMention, cgb =>
{
var client = manager.Client;
commands.ForEach(cmd => cmd.Init(cgb));
CreateCommand(cgb, "do you love me")
.Description("Replies with positive answer only to the bot owner.")
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
await client.SendMessage(e.Channel, Mention.User(e.User) + ", Of course I do, my Master.");
else
await client.SendMessage(e.Channel, Mention.User(e.User) + ", Don't be silly.");
});
CreateCommand(cgb, "die")
.Description("Works only for the owner. Shuts the bot down.")
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
{
Timer t = new Timer();
t.Interval = 2000;
t.Elapsed += (s, ev) => { Environment.Exit(0); };
t.Start();
await client.SendMessage(e.Channel, Mention.User(e.User) + ", Yes, my love.");
}
else
await client.SendMessage(e.Channel, Mention.User(e.User) + ", No.");
});
CreateCommand(cgb, "how are you")
.Description("Replies positive only if bot owner is online.")
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " I am great as long as you are here.");
}
else
{
var kw = client.GetUser(e.Server, NadekoBot.OwnerID);
if (kw != null && kw.Status == UserStatus.Online)
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " I am great as long as " + Mention.User(kw) + " is with me.");
}
else
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " I am sad. My Master is not with me.");
}
}
});
CreateCommand(cgb, "insult")
.Parameter("mention", ParameterType.Required)
.Description("Only works for owner. Insults @X person.\nUsage: @NadekoBot insult @X.")
.Do(async e =>
{
List<string> insults = new List<string> { " you are a poop.", " you jerk.", " i will eat you when i get my powers back." };
Random r = new Random();
var u = e.Message.MentionedUsers.Last();
if (u.Id == NadekoBot.OwnerID)
{
await client.SendMessage(e.Channel, "I would never insult my master <3");
}
else if (e.User.Id == NadekoBot.OwnerID)
{
await client.SendMessage(e.Channel, Mention.User(u) + insults[r.Next(0, insults.Count)]);
}
else
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " Eww, why would i do that for you ?!");
}
});
CreateCommand(cgb, "praise")
.Description("Only works for owner. Praises @X person.\nUsage: @NadekoBot insult @X.")
.Parameter("mention", ParameterType.Required)
.Do(async e =>
{
List<string> praises = new List<string> { " You are cool.", " You are nice... But don't get any wrong ideas.", " You did a good job." };
Random r = new Random();
var u = e.Message.MentionedUsers.First();
if (e.User.Id == NadekoBot.OwnerID)
{
if (u.Id != NadekoBot.OwnerID)
await client.SendMessage(e.Channel, Mention.User(u) + praises[r.Next(0, praises.Count)]);
else
{
await client.SendMessage(e.Channel, Mention.User(u) + " No need, you know I love you <3");
}
}
else
{
if (u.Id == NadekoBot.OwnerID)
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " I don't need your permission to praise my beloved Master <3");
}
else
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " Yeah... No.");
}
}
});
CreateCommand(cgb, "are you real")
.Description("Useless.")
.Do(async e =>
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " I will be soon.");
});
cgb.CreateCommand("are you there")
.Description("Checks if nadeko is operational.")
.Alias(new string[] { "!", "?", "??", "???", "!!", "!!!" })
.Do(SayYes());
CreateCommand(cgb, "draw")
.Description("Nadeko instructs you to type $draw. Gambling functions start with $")
.Do(async e =>
{
await client.SendMessage(e.Channel, "Sorry i dont gamble, type $draw for that function.");
});
CreateCommand(cgb, "uptime")
.Description("Shows how long is Nadeko running for.")
.Do(async e =>
{
var time = (DateTime.Now - Process.GetCurrentProcess().StartTime);
string str = "I am online for " + time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes.";
await client.SendMessage(e.Channel, str);
});
CreateCommand(cgb, "fire")
.Description("Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire.\nUsage: @NadekoBot fire [x]")
.Parameter("times", ParameterType.Optional)
.Do(async e =>
{
int count = 0;
if (e.Args?.Length > 0)
int.TryParse(e.Args[0], out count);
if (count < 1)
count = 1;
else if (count > 12)
count = 12;
string str = "";
for (int i = 0; i < count; i++)
{
str += firestr;
}
await client.SendMessage(e.Channel, str);
});
CreateCommand(cgb, "rip")
.Description("Shows a grave image.Optional parameter [@X] instructs her to put X's name on the grave.\nUsage: @NadekoBot rip [@X]")
.Parameter("all", ParameterType.Unparsed)
.Do(async e =>
{
if (e.Message.MentionedUsers.Count() == 1)
{
await client.SendFile(e.Channel, @"images\rip.png");
}
else
{
foreach (User u in e.Message.MentionedUsers)
{
if (u.Name == "NadekoBot") continue;
RipName(u.Name);
await client.SendFile(e.Channel, @"images\ripnew.png");
}
}
});
cgb.CreateCommand("j")
.Description("Joins a server using a code. Obsolete, since nadeko will autojoin any valid code in chat.")
.Parameter("id", ParameterType.Required)
.Do(async e =>
{
try
{
await client.AcceptInvite(client.GetInvite(e.Args[0]).Result);
await client.SendMessage(e.Channel, "I got in!");
}
catch (Exception)
{
await client.SendMessage(e.Channel, "Invalid code.");
}
});
cgb.CreateCommand("i")
.Description("Pulls a first image using a search parameter.\nUsage: @NadekoBot img Multiword_search_parameter")
.Alias("img")
.Parameter("all", ParameterType.Unparsed)
.Do(async e =>
{
var httpClient = new System.Net.Http.HttpClient();
string str = e.Args[0];
var r = httpClient.GetAsync("http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=" + Uri.EscapeDataString(str) + "&start=0").Result;
dynamic obj = JObject.Parse(r.Content.ReadAsStringAsync().Result);
if (obj.responseData.results.Count == 0)
{
await client.SendMessage(e.Channel, "No results found for that keyword :\\");
return;
}
string s = Searches.ShortenUrl(obj.responseData.results[0].url.ToString());
await client.SendMessage(e.Channel, s);
});
cgb.CreateCommand("ir")
.Description("Pulls a random image using a search parameter.\nUsage: @NadekoBot img Multiword_search_parameter")
.Alias("imgrandom")
.Parameter("all", ParameterType.Unparsed)
.Do(async e =>
{
var httpClient = new System.Net.Http.HttpClient();
string str = e.Args[0];
var r = httpClient.GetAsync("http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=" + Uri.EscapeDataString(str) + "&start=" + rng.Next(0, 30)).Result;
dynamic obj = JObject.Parse(r.Content.ReadAsStringAsync().Result);
if (obj.responseData.results.Count == 0)
{
await client.SendMessage(e.Channel, "No results found for that keyword :\\");
return;
}
int rnd = rng.Next(0, obj.responseData.results.Count);
string s = Searches.ShortenUrl(obj.responseData.results[rnd].url.ToString());
await client.SendMessage(e.Channel, s);
});
AliasCommand(CreateCommand(cgb, "save"), "s")
.Description("Saves something for the owner in a file.")
.Parameter("all", ParameterType.Unparsed)
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
{
string m = "";
try
{
FileStream f = File.OpenWrite("saves.txt");
m = e.Args[0];
byte[] b = Encoding.ASCII.GetBytes(m + "\n");
f.Seek(f.Length, SeekOrigin.Begin);
f.Write(b, 0, b.Length);
f.Close();
}
catch (Exception)
{
await client.SendMessage(e.Channel, "Error saving. Sorry :(");
}
if (m.Length > 0)
await client.SendMessage(e.Channel, "I saved this for you: " + Environment.NewLine + "```" + m + "```");
else
await client.SendMessage(e.Channel, "No point in saving empty message...");
}
else await client.SendMessage(e.Channel, "Not for you, only my Master <3");
});
CreateCommand(cgb, "ls")
.Description("Shows all saved items.")
.Do(async e =>
{
FileStream f = File.OpenRead("saves.txt");
if (f.Length == 0)
{
await client.SendMessage(e.Channel, "Saves are empty.");
return;
}
byte[] b = new byte[f.Length / sizeof(byte)];
f.Read(b, 0, b.Length);
f.Close();
string str = Encoding.ASCII.GetString(b);
await client.SendPrivateMessage(e.User, "```" + (str.Length < 1950 ? str : str.Substring(0, 1950)) + "```");
});
CreateCommand(cgb, "cs")
.Description("Deletes all saves")
.Do(async e =>
{
File.Delete("saves.txt");
await client.SendMessage(e.Channel, "Cleared all saves.");
});
CreateCommand(cgb, "bb")
.Description("Says bye to someone.\nUsage: @NadekoBot bb @X")
.Parameter("ppl", ParameterType.Unparsed)
.Do(async e =>
{
string str = "Bye";
foreach (var u in e.Message.MentionedUsers)
{
str += " " + Mention.User(u);
}
await client.SendMessage(e.Channel, str);
});
AliasCommand(CreateCommand(cgb, "req"), "request")
.Description("Requests a feature for nadeko.\nUsage: @NadekoBot req Mutliword_feature_request")
.Parameter("all", ParameterType.Unparsed)
.Do(async e =>
{
string str = e.Args[0];
try
{
StatsCollector.SaveRequest(e, str);
}
catch (Exception)
{
await client.SendMessage(e.Channel, "Something went wrong.");
return;
}
await client.SendMessage(e.Channel, "Thank you for your request.");
});
CreateCommand(cgb, "lr")
.Description("PMs the user all current nadeko requests.")
.Do(async e =>
{
string str = StatsCollector.GetRequests();
if (str.Trim().Length > 110)
await client.SendPrivateMessage(e.User, str);
else
await client.SendPrivateMessage(e.User, "No requests atm.");
});
CreateCommand(cgb, "dr")
.Description("Deletes a request. Only owner is able to do this.")
.Parameter("reqNumber", ParameterType.Required)
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
{
try
{
if (StatsCollector.DeleteRequest(int.Parse(e.Args[0])))
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " Request deleted.");
}
else
{
await client.SendMessage(e.Channel, "No request on that number.");
}
}
catch
{
await client.SendMessage(e.Channel, "Error deleting request, probably NaN error.");
}
}
else await client.SendMessage(e.Channel, "You don't have permission to do that.");
});
CreateCommand(cgb, "rr")
.Description("Resolves a request. Only owner is able to do this.")
.Parameter("reqNumber", ParameterType.Required)
.Do(async e =>
{
if (e.User.Id == NadekoBot.OwnerID)
{
try
{
var sc = StatsCollector.ResolveRequest(int.Parse(e.Args[0]));
if (sc != null)
{
await client.SendMessage(e.Channel, Mention.User(e.User) + " Request resolved, notice sent.");
await client.SendPrivateMessage(client.GetUser(client.GetServer(sc.ServerId), sc.Id), "**This request of yours has been resolved:**\n" + sc.Text);
}
else
{
await client.SendMessage(e.Channel, "No request on that number.");
}
}
catch
{
await client.SendMessage(e.Channel, "Error resolving request, probably NaN error.");
}
}
else await client.SendMessage(e.Channel, "You don't have permission to do that.");
});
CreateCommand(cgb, "clr")
.Description("Clears some of nadeko's messages from the current channel.")
.Do(async e =>
{
try
{
if (e.Channel.Messages.Count() < 50)
{
await client.DownloadMessages(e.Channel, 100);
}
await client.DeleteMessages(e.Channel.Messages.Where(msg => msg.User.Id == client.CurrentUser.Id));
}
catch (Exception)
{
await client.SendMessage(e.Channel, "I cant do it :(");
}
});
CreateCommand(cgb, "call")
.Description("Useless. Writes calling @X to chat.\nUsage: @NadekoBot call @X ")
.Parameter("who", ParameterType.Required)
.Do(async e =>
{
await client.SendMessage(e.Channel, "Calling " + e.Args[0] + "...");
});
cgb.CreateCommand("cid")
.Description("Shows current channel id")
.Do(async e =>
{
await client.SendMessage(e.Channel, "This channel's id is " + e.Channel.Id);
});
cgb.CreateCommand("sid")
.Description("Shows current server id")
.Do(async e =>
{
await client.SendMessage(e.Channel, "This server's id is " + e.Server.Id);
});
CreateCommand(cgb, "hide")
.Description("Hides nadeko in plain sight!11!!")
.Do(async e =>
{
try
{
using (MemoryStream ms = new MemoryStream())
using (Image img = Image.FromFile("images/hidden.png"))
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
await client.EditProfile("", null, null, null, ms, ImageType.Png);
}
}
catch (Exception ex)
{
StatsCollector.DEBUG_LOG(ex.ToString());
}
});
CreateCommand(cgb, "unhide")
.Description("Hides nadeko in plain sight!11!!")
.Do(async e =>
{
try
{
using (MemoryStream ms = new MemoryStream())
using (Image img = Image.FromFile("images/nadeko.jpg"))
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
await client.EditProfile("", null, null, null,ms, ImageType.Jpeg);
}
}
catch (Exception ex)
{
StatsCollector.DEBUG_LOG(ex.ToString());
}
});
CreateCommand(cgb, "stats")
.Description("Shows some basic stats for nadeko")
.Do(async e =>
{
int serverCount = client.AllServers.Count();
int uniqueUserCount = client.AllUsers.Count();
var time = (DateTime.Now - Process.GetCurrentProcess().StartTime);
string uptime = " " + time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes.";
await client.SendMessage(e.Channel, String.Format("```Servers: {0}\nUnique Users: {1}\nUptime: {2}\nMy id is: {3}```", serverCount, uniqueUserCount, uptime, client.CurrentUserId));
});
//TODO add eval
/*
cgb.CreateCommand(">")
.Parameter("code", ParameterType.Unparsed)
.Do(async e =>
{
if (e.Message.User.Id == NadekoBot.OwnerId)
{
var result = await CSharpScript.EvaluateAsync(e.Args[0]);
await client.SendMessage(e.Channel, result?.ToString() ?? "null");
return;
}
});*/
});
}
public void RipName(string name)
{
Bitmap bm = new Bitmap(Image.FromFile(@"images\rip.png"));
int offset = name.Length * 5;
int fontSize = 20;
if (name.Length > 10)
{
fontSize -= (name.Length - 10) / 2;
}
//TODO use measure string
Graphics g = Graphics.FromImage(bm);
g.DrawString(name, new Font("Comic Sans MS", fontSize, FontStyle.Bold), Brushes.Black, 100 - offset, 200);
g.DrawString("? - " + DateTime.Now.Year, new Font("Consolas", 12, FontStyle.Bold), Brushes.Black, 80, 235);
g.Flush();
g.Dispose();
bm.Save(@"images\ripnew.png");
}
private Func<CommandEventArgs, Task> SayYes()
{
return async e =>
{
await NadekoBot.client.SendMessage(e.Channel, "Yes. :)");
};
}
}
}

View File

@ -0,0 +1,20 @@
using Discord.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules
{
abstract class DiscordModule : IModule
{
public List<DiscordCommand> commands;
protected DiscordModule() {
commands = new List<DiscordCommand>();
}
public abstract void Install(ModuleManager manager);
}
}

View File

@ -0,0 +1,23 @@
using Discord.Commands;
using Discord.Modules;
namespace NadekoBot.Modules
{
class Gambling : DiscordModule
{
public Gambling() {
commands.Add(new DrawCommand());
commands.Add(new FlipCoinCommand());
commands.Add(new DiceRollCommand());
}
public override void Install(ModuleManager manager)
{
manager.CreateCommands("", cgb =>
{
commands.ForEach(com => com.Init(cgb));
});
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Modules;
namespace NadekoBot.Modules
{
class Games : DiscordModule
{
public Games() : base() {
commands.Add(new Trivia());
}
public override void Install(ModuleManager manager)
{
manager.CreateCommands("", cgb =>
{
commands.ForEach(cmd => cmd.Init(cgb));
});
}
}
}

230
NadekoBot/Modules/Music.cs Normal file
View File

@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Modules;
using Discord.Commands;
using System.IO;
using Discord;
using Discord.Audio;
using System.Collections.Concurrent;
using VideoLibrary;
using System.Threading;
using System.Diagnostics;
namespace NadekoBot.Modules
{
class Music : DiscordModule
{
private static bool exit = true;
public static bool NextSong = false;
public static IDiscordVoiceClient Voice;
public static Channel VoiceChannel;
public static bool Pause = false;
public static List<YouTubeVideo> SongQueue = new List<YouTubeVideo>();
public static YouTubeVideo CurrentSong;
public static bool Exit
{
get { return exit; }
set { exit = value;} // if i set this to true, break the song and exit the main loop
}
public Music() : base() {
//commands.Add(new PlayMusic());
}
//m r,radio - init
//m n,next - next in que
//m p,pause - pauses, call again to unpause
//m yq [key_words] - queue from yt by keywords
//m s,stop - stop
//m sh - shuffle songs
//m pl - current playlist
public override void Install(ModuleManager manager)
{
var client = NadekoBot.client;
manager.CreateCommands("!m", cgb =>
{
//queue all more complex commands
commands.ForEach(cmd => cmd.Init(cgb));
cgb.CreateCommand("n")
.Alias("next")
.Description("Goes to the next song in the queue.")
.Do(e =>
{
if (Voice != null && Exit == false)
{
NextSong = true;
}
});
cgb.CreateCommand("s")
.Alias("stop")
.Description("Completely stops the music and unbinds the bot from the channel.")
.Do(e =>
{
if (Voice != null && Exit == false)
{
Exit = true;
SongQueue = new List<YouTubeVideo>();
}
});
cgb.CreateCommand("p")
.Alias("pause")
.Description("Pauses the song")
.Do(async e =>
{
if (Voice != null && Exit == false && CurrentSong != null)
{
Pause = !Pause;
if (Pause)
{
await client.SendMessage(e.Channel, "Pausing. Run the command again to resume.");
}
else
{
await client.SendMessage(e.Channel, "Resuming...");
}
}
});
cgb.CreateCommand("q")
.Alias("yq")
.Description("Queue a song using a multi/single word name.\nUsage: `!m q Dream Of Venice`")
.Parameter("Query", ParameterType.Unparsed)
.Do(async e =>
{
var youtube = YouTube.Default;
var video = youtube.GetAllVideos(Searches.FindYoutubeUrlByKeywords(e.Args[0]))
.Where(v => v.AdaptiveKind == AdaptiveKind.Audio)
.OrderByDescending(v => v.AudioBitrate).FirstOrDefault();
if (video?.Uri != "" && video.Uri != null)
{
SongQueue.Add(video);
await client.SendMessage(e.Channel, "**Queued** " + video.FullName);
}
});
cgb.CreateCommand("lq")
.Alias("ls").Alias("lp")
.Description("Lists up to 10 currently queued songs.")
.Do(async e =>
{
await client.SendMessage(e.Channel, SongQueue.Count + " videos currently queued.");
await client.SendMessage(e.Channel, string.Join("\n", SongQueue.Select(v => v.FullName).Take(10)));
});
cgb.CreateCommand("sh")
.Description("Shuffles the current playlist.")
.Do(async e =>
{
if (SongQueue.Count < 2)
{
await client.SendMessage(e.Channel, "Not enough songs in order to perform the shuffle.");
return;
}
SongQueue.Shuffle();
await client.SendMessage(e.Channel, "Songs shuffled!");
});
cgb.CreateCommand("radio")
.Alias("music")
.Description("Binds to a voice and text channel in order to play music.")
.Parameter("ChannelName", ParameterType.Unparsed)
.Do(async e =>
{
if (Voice != null) return;
VoiceChannel = client.FindChannels(e.Server, e.GetArg("ChannelName").Trim(), ChannelType.Voice).FirstOrDefault();
Voice = await client.JoinVoiceServer(VoiceChannel);
Exit = false;
NextSong = false;
Pause = false;
try
{
while (true)
{
if (Exit) break;
if (SongQueue.Count == 0 || Pause) { Thread.Sleep(100); continue; }
if (!LoadNextSong()) break;
await Task.Run(async () =>
{
if (Exit)
{
Voice = null;
Exit = false;
await client.SendMessage(e.Channel, "Exiting...");
return;
}
int blockSize = 1920;
byte[] buffer = new byte[1920];
//float multiplier = 1.0f / 48000 / 2;
var msg = await client.SendMessage(e.Channel, "Playing " + Music.CurrentSong.FullName + " [00:00]");
int counter = 0;
int byteCount;
using (var stream = GetAudioFileStream(Music.CurrentSong.Uri))
{
while ((byteCount = stream.Read(buffer, 0, blockSize)) > 0)
{
Voice.SendVoicePCM(buffer, byteCount);
counter += blockSize;
if (NextSong)
{
NextSong = false;
break;
}
if (Exit)
{
Exit = false;
return;
}
while (Pause) Thread.Sleep(100);
}
}
});
}
await Voice.WaitVoice();
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
await client.LeaveVoiceServer(VoiceChannel.Server);
Voice = null;
VoiceChannel = null;
});
});
}
private Stream GetAudioFileStream(string file)
{
Process p = Process.Start(new ProcessStartInfo()
{
FileName = "ffmpeg",
Arguments = "-i \"" + Uri.EscapeUriString(file) + "\" -f s16le -ar 48000 -af volume=1 -ac 1 pipe:1 ",
UseShellExecute = false,
RedirectStandardOutput = true
});
return p.StandardOutput.BaseStream;
}
private bool LoadNextSong()
{
if (SongQueue.Count == 0) {
CurrentSong = null;
return false;
}
CurrentSong = SongQueue[0];
SongQueue.RemoveAt(0);
return true;
}
}
}

View File

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Modules;
using System.Net;
using System.IO;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Xml;
using Newtonsoft.Json;
using System.Net.Http;
namespace NadekoBot.Modules
{
class Searches : DiscordModule
{
public Searches() : base()
{
}
public override void Install(ModuleManager manager)
{
var client = NadekoBot.client;
manager.CreateCommands("",cgb =>
{
cgb.CreateCommand("~av")
.Parameter("mention", Discord.Commands.ParameterType.Required)
.Do(async e =>
{
if (e.Message.MentionedUsers.Count() == 0) {
await client.SendMessage(e.Channel, "You need to mention a person");
return;
}
string av = e.Message.MentionedUsers.First().AvatarUrl;
await client.SendMessage(e.Channel, ShortenUrl("http://www.discordapp.com/api/" + av));
});
cgb.CreateCommand("~yt")
.Parameter("query",Discord.Commands.ParameterType.Unparsed)
.Description("Queries youtubes and embeds the first result")
.Do(async e =>
{
if (!(await ValidateQuery(e.Channel, e.GetArg("query")))) return;
var str = ShortenUrl(FindYoutubeUrlByKeywords(e.GetArg("query")));
if (str == null || str.Trim().Length < 5)
{
await client.SendMessage(e.Channel, "Query failed");
return;
}
await client.SendMessage(e.Channel, str);
});
cgb.CreateCommand("~ani")
.Alias("~anime").Alias("~aq")
.Parameter("query", Discord.Commands.ParameterType.Unparsed)
.Description("Queries anilist for an anime and shows the first result.")
.Do(async e =>
{
if (!(await ValidateQuery(e.Channel, e.GetArg("query")))) return;
var result = GetAnimeQueryResultLink(e.GetArg("query"));
if (result == null) {
await client.SendMessage(e.Channel, "Failed to find that anime.");
return;
}
await client.SendMessage(e.Channel,result.ToString());
});
cgb.CreateCommand("~mang")
.Alias("~manga").Alias("~mq")
.Parameter("query", Discord.Commands.ParameterType.Unparsed)
.Description("Queries anilist for a manga and shows the first result.")
.Do(async e =>
{
if (!(await ValidateQuery(e.Channel, e.GetArg("query")))) return;
var result = GetMangaQueryResultLink(e.GetArg("query"));
if (result == null)
{
await client.SendMessage(e.Channel, "Failed to find that anime.");
return;
}
await client.SendMessage(e.Channel, result.ToString());
});
});
}
private string token = "";
private AnimeResult GetAnimeQueryResultLink(string query)
{
try
{
var cl = new RestSharp.RestClient("https://anilist.co/api");
var rq = new RestSharp.RestRequest("/auth/access_token", RestSharp.Method.POST);
RefreshToken();
rq = new RestSharp.RestRequest("/anime/search/" + Uri.EscapeUriString(query));
rq.AddParameter("access_token", token);
var smallObj = JArray.Parse(cl.Execute(rq).Content)[0];
rq = new RestSharp.RestRequest("anime/" + smallObj["id"]);
rq.AddParameter("access_token", token);
return JsonConvert.DeserializeObject<AnimeResult>(cl.Execute(rq).Content);
}
catch (Exception)
{
return null;
}
}
private MangaResult GetMangaQueryResultLink(string query)
{
try
{
RefreshToken();
var cl = new RestSharp.RestClient("https://anilist.co/api");
var rq = new RestSharp.RestRequest("/auth/access_token", RestSharp.Method.POST);
rq = new RestSharp.RestRequest("/manga/search/"+Uri.EscapeUriString(query));
rq.AddParameter("access_token", token);
var smallObj = JArray.Parse(cl.Execute(rq).Content)[0];
rq = new RestSharp.RestRequest("manga/" + smallObj["id"]);
rq.AddParameter("access_token", token);
return JsonConvert.DeserializeObject<MangaResult> (cl.Execute(rq).Content);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return null;
}
}
private void RefreshToken()
{
var cl = new RestSharp.RestClient("https://anilist.co/api");
var rq = new RestSharp.RestRequest("/auth/access_token", RestSharp.Method.POST);
rq.AddParameter("grant_type", "client_credentials");
rq.AddParameter("client_id", "kwoth-w0ki9");
rq.AddParameter("client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z");
token = JObject.Parse(cl.Execute(rq).Content)["access_token"].ToString();
}
private static async Task<bool> ValidateQuery(Discord.Channel ch,string query) {
if (query == null || query.Trim().Length == 0)
{
await NadekoBot.client.SendMessage(ch, "Please specify search parameters.");
return false;
}
return true;
}
public static string FindYoutubeUrlByKeywords(string v)
{
WebRequest wr = WebRequest.Create("https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q=" + Uri.EscapeDataString(v) + "&key=" + NadekoBot.GoogleAPIKey);
var sr = new StreamReader(wr.GetResponse().GetResponseStream());
dynamic obj = JObject.Parse(sr.ReadToEnd());
return "http://www.youtube.com/watch?v=" + obj.items[0].id.videoId.ToString();
}
public static string ShortenUrl(string url)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url?key=" + NadekoBot.GoogleAPIKey);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"longUrl\":\"" + url + "\"}";
streamWriter.Write(json);
}
try
{
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
string MATCH_PATTERN = @"""id"": ?""(?<id>.+)""";
return Regex.Match(responseText, MATCH_PATTERN).Groups["id"].Value;
}
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); return ""; }
}
}
}

151
NadekoBot/NadekoBot.cs Normal file
View File

@ -0,0 +1,151 @@
using Discord;
using System;
using System.IO;
using Newtonsoft.Json;
using Discord.Commands;
using Discord.Modules;
using System.Text.RegularExpressions;
using Parse;
using NadekoBot.Modules;
using System.Timers;
namespace NadekoBot
{
class NadekoBot
{
public static DiscordClient client;
public static StatsCollector sc;
public static string botMention;
public static string GoogleAPIKey;
public static long OwnerID;
static void Main(string[] args)
{
//load credentials from credentials.json
Credentials c;
try
{
c = JsonConvert.DeserializeObject<Credentials>(File.ReadAllText("credentials.json"));
botMention = c.BotMention;
GoogleAPIKey = c.GoogleAPIKey;
OwnerID = c.OwnerID;
}
catch (Exception)
{
Console.WriteLine("Failed to load stuff from credentials.json, RTFM");
Console.ReadKey();
return;
}
//init parse
if (c.ParseKey != null && c.ParseID != null)
ParseClient.Initialize(c.ParseID,c.ParseKey);
//create new discord client
client = new DiscordClient(new DiscordClientConfig() {
VoiceMode = DiscordVoiceMode.Outgoing,
});
//create a command service
var commandService = new CommandService(new CommandServiceConfig
{
CommandChar = null,
HelpMode = HelpMode.Disable
});
//monitor commands for logging
sc = new StatsCollector(commandService);
//add command service
var commands = client.AddService(commandService);
//help command
commands.CreateCommand("-h")
.Alias(new string[]{"-help",NadekoBot.botMention+" help", NadekoBot.botMention+" h"})
.Description("Help command")
.Do(async e =>
{
string helpstr = "";
foreach (var com in client.Commands().AllCommands) {
helpstr += "&###**#" + com.Category + "#**\n";
helpstr += PrintCommandHelp(com);
}
while (helpstr.Length > 2000) {
var curstr = helpstr.Substring(0, 2000);
await client.SendPrivateMessage(e.User, curstr.Substring(0,curstr.LastIndexOf("&")));
helpstr = curstr.Substring(curstr.LastIndexOf("&")) + helpstr.Substring(2000);
}
await client.SendPrivateMessage(e.User, helpstr);
});
//create module service
var modules = client.AddService(new ModuleService());
//install modules
modules.Install(new Conversations(), "Conversation", FilterType.Unrestricted);
modules.Install(new Gambling(), "Gambling", FilterType.Unrestricted);
modules.Install(new Games(), "Games", FilterType.Unrestricted);
modules.Install(new Music(), "Music", FilterType.Unrestricted);
modules.Install(new Searches(), "Searches", FilterType.Unrestricted);
commands.CommandError += Commands_CommandError;
//run the bot
client.Run(async () =>
{
Console.WriteLine("Trying to connect...");
try
{
await client.Connect(c.Username, c.Password);
Console.WriteLine("Connected!");
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
});
Console.WriteLine("Exiting...");
Console.ReadKey();
}
private static void Commands_CommandError(object sender, CommandErrorEventArgs e)
{
if (e.Command != null)
client.SendMessage(e.Channel, Mention.User(e.User) + " Command failed. See help (-h).");
}
private static string PrintCommandHelp(Command com)
{
var str = "`" + com.Text + "`\n";
foreach (var a in com.Aliases)
str += "`" + a + "`\n";
str += "Description: " + com.Description + "\n";
return str;
}
/* removed
private static void Crawl()
{
Timer t = new Timer();
t.Interval = 5000; // start crawling after 5 seconds
t.Elapsed += (s, e) => {
var wc = new WebCrawler.WebCrawler();
WebCrawler.WebCrawler.OnFoundInvite += inv => { TryJoin(inv); };
t.Stop();
};
t.Start();
}
*/
private static async void TryJoin(string code)
{
try
{
await NadekoBot.client.AcceptInvite(await NadekoBot.client.GetInvite(code));
File.AppendAllText("invites.txt", code + "\n");
}
catch (Exception)
{
StatsCollector.DEBUG_LOG("Failed to join " + code);
}
}
}
}

117
NadekoBot/NadekoBot.csproj Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NadekoBot</RootNamespace>
<AssemblyName>NadekoBot</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Discord.Net">
<HintPath>E:\Ostalo\Discord.Net\src\Discord.Net.Modules.Net45\bin\Debug\Discord.Net.dll</HintPath>
</Reference>
<Reference Include="Discord.Net.Commands">
<HintPath>E:\Ostalo\Discord.Net\src\Discord.Net.Modules.Net45\bin\Debug\Discord.Net.Commands.dll</HintPath>
</Reference>
<Reference Include="Discord.Net.Modules">
<HintPath>E:\Ostalo\Discord.Net\src\Discord.Net.Modules.Net45\bin\Debug\Discord.Net.Modules.dll</HintPath>
</Reference>
<Reference Include="libvideo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\VideoLibrary.1.3.1\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\libvideo.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.8.0.1-beta3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Parse, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Parse.1.6.2\lib\net45\Parse.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Parse.NetFx45, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Parse.1.6.2\lib\net45\Parse.NetFx45.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="policy.2.0.taglib-sharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=db62eba44689b5b0, processorArchitecture=MSIL">
<HintPath>..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.105.2.3\lib\net452\RestSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="taglib-sharp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=db62eba44689b5b0, processorArchitecture=MSIL">
<HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Classes\_JSONModels.cs" />
<Compile Include="Classes\Cards.cs" />
<Compile Include="Classes\Extensions.cs" />
<Compile Include="Classes\ImageHandler.cs" />
<Compile Include="Classes\Trivia.cs" />
<Compile Include="Commands\CopyCommand.cs" />
<Compile Include="Commands\DiceRollCommand.cs" />
<Compile Include="Commands\DiscordCommand.cs" />
<Compile Include="Commands\DrawCommand.cs" />
<Compile Include="Commands\FlipCoinCommand.cs" />
<Compile Include="Modules\Conversations.cs" />
<Compile Include="Modules\DiscordModule.cs" />
<Compile Include="Modules\Gambling.cs" />
<Compile Include="Modules\Games.cs" />
<Compile Include="Modules\Music.cs" />
<Compile Include="Modules\Searches.cs" />
<Compile Include="NadekoBot.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StatsCollector.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NadekoBot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NadekoBot")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("27a886f5-cdda-4f4a-81ee-6dafcce9de46")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

207
NadekoBot/StatsCollector.cs Normal file
View File

@ -0,0 +1,207 @@
using Discord;
using Discord.Commands;
using Discord.Modules;
using Parse;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Timers;
namespace NadekoBot
{
public class StatsCollector
{
private CommandService _service;
string lastMention = "";
string lastMessage = "No messages.";
int commandsRan = 0;
string dataLastSent = "Data last sent at: NEVER";
List<string> messages = new List<string>();
public StatsCollector(CommandService service)
{
this._service = service;
_service.RanCommand += StatsCollector_RanCommand;
NadekoBot.client.MessageReceived += Client_MessageReceived;
/*
Timer t = new Timer();
t.Interval = 5000;
t.Elapsed += (s,e) =>
{
FillConsole();
};
t.Start();
*/
StartCollecting();
}
private void FillConsole() {
Console.Clear();
var time = (DateTime.Now - Process.GetCurrentProcess().StartTime);
string str = "Online for " + time.Days + "d, " + time.Hours + "h, " + time.Minutes + "m, "+time.Seconds+"s.";
Console.SetCursorPosition(0, 0);
Console.Write(str);
Console.SetCursorPosition(0, 1);
Console.Write(dataLastSent);
Console.SetCursorPosition(0, 2);
Console.Write("Commands ran since start: " +commandsRan);
Console.SetCursorPosition(0, 3);
Console.Write(lastMention);
Console.SetCursorPosition(0, 4);
Console.WriteLine(lastMessage);
}
private void Client_MessageReceived(object sender, MessageEventArgs e)
{
lastMessage = "[" + e.User.Name + "] on [" + e.Server.Name + "] server, channel: [" + e.Channel.Name + "] \n" + "Body: " + e.Message.Text + " ";
if (e.Message.MentionedUsers.Where(u => u.Id == NadekoBot.OwnerID).Count() > 0)
{
lastMention = "You were last mentioned in '" + e.Server.Name + "' server, channel '" + e.Channel.Name + "', by " + e.User.Name;
}
}
private async void TryJoin(MessageEventArgs e, string code) {
try
{
await NadekoBot.client.AcceptInvite(await NadekoBot.client.GetInvite(code));
await NadekoBot.client.SendMessage(e.Channel, Mention.User(e.User) + " I joined it, thanks :)");
DEBUG_LOG("Sucessfuly joined server with code " + code);
DEBUG_LOG("Here is a link for you: discord.gg/" + code);
}
catch (Exception ex) {
DEBUG_LOG("Failed to join " + code);
DEBUG_LOG("Reason: " + ex.ToString());
}
}
public static void DEBUG_LOG(string text) {
NadekoBot.client.SendMessage(NadekoBot.client.GetChannel(119365591852122112), text);
}
private void StartCollecting() {
Timer t = new Timer();
t.Interval = 3600000;
t.Enabled = true;
t.Elapsed += (s, e) =>
{
var obj = new ParseObject("Stats");
dataLastSent = "Data last sent at: "+DateTime.Now.Hour+":"+DateTime.Now.Minute;
obj["OnlineUsers"] = NadekoBot.client.AllUsers.Count();
obj["ConnectedServers"] = NadekoBot.client.AllServers.Count();
obj.SaveAsync();
};
Console.WriteLine("Server stats sent.");
}
public static void SaveRequest(CommandEventArgs e, string text) {
var obj = new ParseObject("Requests");
obj["ServerId"] = e.Server.Id;
obj["ServerName"] = e.Server.Name;
obj["UserId"] = e.User.Id;
obj["UserName"] = e.User.Name;
obj["Request"] = text;
obj.SaveAsync();
}
public static string GetRequests() {
var task = ParseObject.GetQuery("Requests")
.FindAsync().Result;
string str = "Here are all current requests for NadekoBot:\n\n";
int i = 1;
foreach (var reqObj in task)
{
str += (i++) + ". by **" + reqObj["UserName"] +"** from **" + reqObj["ServerName"] + "** at "+ reqObj.CreatedAt.Value.ToLocalTime() + "\n";
str+= "**"+reqObj["Request"]+"**\n----------\n";
}
return str+"\n__Type [@NadekoBot clr] to clear all of my messages.__";
}
public static bool DeleteRequest(int requestNumber) {
var task = ParseObject.GetQuery("Requests")
.FindAsync().Result;
int i = 1;
foreach (var reqObj in task)
{
if (i == requestNumber)
{
reqObj.DeleteAsync();
return true;
}
i++;
}
return false;
}
/// <summary>
/// Resolves a request with a number and returns that users id.
/// </summary>
/// <returns>RequestObject of the request. Null if none</returns>
public static ResolveRequestObject ResolveRequest(int requestNumber) {
var task = ParseObject.GetQuery("Requests")
.FindAsync().Result;
int i = 1;
foreach (var reqObj in task)
{
if (i == requestNumber) {
var txt = reqObj.Get<string>("Request");
var id = reqObj.Get<long>("UserId");
var sid = reqObj.Get<long>("ServerId");
reqObj.DeleteAsync();
return new ResolveRequestObject { Id = id, Text = txt, ServerId=sid };
}
i++;
}
return null;
}
public class ResolveRequestObject {
public long Id;
public long ServerId;
public string Text;
}
private void StatsCollector_RanCommand(object sender, CommandEventArgs e)
{
commandsRan++;
var obj = new ParseObject("CommandsRan");
obj["ServerId"] = e.Server.Id;
obj["ServerName"] = e.Server.Name;
obj["ChannelId"] = e.Channel.Id;
obj["ChannelName"] = e.Channel.Name;
obj["UserId"] = e.User.Id;
obj["UserName"] = e.User.Name;
obj["CommandName"] = e.Command.Text;
obj.SaveAsync();
}
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="8.0.1-beta3" targetFramework="net452" />
<package id="Parse" version="1.6.2" targetFramework="net452" />
<package id="RestSharp" version="105.2.3" targetFramework="net452" />
<package id="taglib" version="2.1.0.0" targetFramework="net452" />
<package id="VideoLibrary" version="1.3.1" targetFramework="net452" />
</packages>

Binary file not shown.

Binary file not shown.

BIN
dlls/Discord.Net.dll Normal file

Binary file not shown.

BIN
dlls/lib/libsodium.dll Normal file

Binary file not shown.

BIN
dlls/lib/opus.dll Normal file

Binary file not shown.

BIN
dlls/websocket-sharp.dll Normal file

Binary file not shown.