Initial commit
Enjoy
This commit is contained in:
parent
81642424aa
commit
a909d69e4a
231
.gitignore
vendored
Normal file
231
.gitignore
vendored
Normal 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
25
NadekoBot.sln
Normal 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
14
NadekoBot/App.config
Normal 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
155
NadekoBot/Classes/Cards.cs
Normal 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;
|
||||
}
|
||||
|
29
NadekoBot/Classes/Extensions.cs
Normal file
29
NadekoBot/Classes/Extensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
NadekoBot/Classes/ImageHandler.cs
Normal file
39
NadekoBot/Classes/ImageHandler.cs
Normal 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
315
NadekoBot/Classes/Trivia.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
56
NadekoBot/Classes/_JSONModels.cs
Normal file
56
NadekoBot/Classes/_JSONModels.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
64
NadekoBot/Commands/CopyCommand.cs
Normal file
64
NadekoBot/Commands/CopyCommand.cs
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
101
NadekoBot/Commands/DiceRollCommand.cs
Normal file
101
NadekoBot/Commands/DiceRollCommand.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
42
NadekoBot/Commands/DiscordCommand.cs
Normal file
42
NadekoBot/Commands/DiscordCommand.cs
Normal 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);
|
||||
}
|
||||
}
|
66
NadekoBot/Commands/DrawCommand.cs
Normal file
66
NadekoBot/Commands/DrawCommand.cs
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
38
NadekoBot/Commands/FlipCoinCommand.cs
Normal file
38
NadekoBot/Commands/FlipCoinCommand.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
585
NadekoBot/Modules/Conversations.cs
Normal file
585
NadekoBot/Modules/Conversations.cs
Normal 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. :)");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
20
NadekoBot/Modules/DiscordModule.cs
Normal file
20
NadekoBot/Modules/DiscordModule.cs
Normal 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);
|
||||
}
|
||||
}
|
23
NadekoBot/Modules/Gambling.cs
Normal file
23
NadekoBot/Modules/Gambling.cs
Normal 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
24
NadekoBot/Modules/Games.cs
Normal file
24
NadekoBot/Modules/Games.cs
Normal 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
230
NadekoBot/Modules/Music.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
197
NadekoBot/Modules/Searches.cs
Normal file
197
NadekoBot/Modules/Searches.cs
Normal 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
151
NadekoBot/NadekoBot.cs
Normal 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
117
NadekoBot/NadekoBot.csproj
Normal 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>
|
36
NadekoBot/Properties/AssemblyInfo.cs
Normal file
36
NadekoBot/Properties/AssemblyInfo.cs
Normal 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
207
NadekoBot/StatsCollector.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
8
NadekoBot/packages.config
Normal file
8
NadekoBot/packages.config
Normal 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>
|
BIN
dlls/Discord.Net.Commands.dll
Normal file
BIN
dlls/Discord.Net.Commands.dll
Normal file
Binary file not shown.
BIN
dlls/Discord.Net.Modules.dll
Normal file
BIN
dlls/Discord.Net.Modules.dll
Normal file
Binary file not shown.
BIN
dlls/Discord.Net.dll
Normal file
BIN
dlls/Discord.Net.dll
Normal file
Binary file not shown.
BIN
dlls/lib/libsodium.dll
Normal file
BIN
dlls/lib/libsodium.dll
Normal file
Binary file not shown.
BIN
dlls/lib/opus.dll
Normal file
BIN
dlls/lib/opus.dll
Normal file
Binary file not shown.
BIN
dlls/websocket-sharp.dll
Normal file
BIN
dlls/websocket-sharp.dll
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user