Merge pull request #60 from Kwoth/dev

ups
This commit is contained in:
samvaio 2017-01-16 15:36:43 +05:30 committed by GitHub
commit f70a60d0c8
43 changed files with 695 additions and 250 deletions

@ -1 +1 @@
Subproject commit b9f767337d2b7c07ed76eb83c3bc5030109d5238
Subproject commit f27cce0854abc42b92d29f9040625238a8991999

View File

@ -28,15 +28,21 @@ If you entered your Droplets IP address correctly, it should show **login as:**
![img1](https://cdn.discordapp.com/attachments/251504306010849280/251504416019054592/git.gif)
Ubuntu:
`sudo apt-get install git -y`
CentOS:
`yum -y install git`
**NOTE:** If the command is not being initiated, hit **Enter**
####Installing .NET Core SDK
![img2](https://cdn.discordapp.com/attachments/251504306010849280/251504746987388938/dotnet.gif)
Go to [this link](https://www.microsoft.com/net/core#ubuntu) provided by microsoft for instructions on how to get the most up to date version of the dotnet core sdk!
Go to [this link](https://www.microsoft.com/net/core#ubuntu) (for Ubuntu) or to [this link](https://www.microsoft.com/net/core#linuxcentos) (for CentOS) provided by microsoft for instructions on how to get the most up to date version of the dotnet core sdk!
Make sure that you're on the correct page for your distribution of linux as the guides are different for the various distributions
We'll go over the steps here for Ubuntu 16.04 anyway (these will **only** work on Ubuntu 16.04), accurate as of 25/11/2016
@ -53,14 +59,29 @@ sudo apt-get update && sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177 -
![img3](https://cdn.discordapp.com/attachments/251504306010849280/251505294654308353/libopus.gif)
Ubuntu:
`sudo apt-get install libopus0 opus-tools libopus-dev libsodium-dev -y`
CentOS:
`yum -y install opus opus-devel`
####Installing FFMPEG
![img4](https://cdn.discordapp.com/attachments/251504306010849280/251505443111829505/ffmpeg.gif)
Ubuntu:
`apt-get install ffmpeg -y`
Centos:
```
yum -y install http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm epel-release
yum -y install ffmpeg
```
**NOTE:** If you are running **UBUNTU 14.04**, you must run these first:
```
@ -84,8 +105,14 @@ sudo apt-get update && sudo apt-get install ffmpeg -y
![img5](https://cdn.discordapp.com/attachments/251504306010849280/251505519758409728/tmux.gif)
Ubuntu:
`sudo apt-get install tmux -y`
Centos:
`yum -y install tmux`
####Getting NadekoBot
Use the following command to get and run `linuxAIO.sh`:

View File

@ -12,37 +12,37 @@ namespace NadekoBot.Migrations
name: "BetflipMultiplier",
table: "BotConfig",
nullable: false,
defaultValue: 0f);
defaultValue: 1.8f);
migrationBuilder.AddColumn<float>(
name: "Betroll100Multiplier",
table: "BotConfig",
nullable: false,
defaultValue: 0f);
defaultValue: 10f);
migrationBuilder.AddColumn<float>(
name: "Betroll67Multiplier",
table: "BotConfig",
nullable: false,
defaultValue: 0f);
defaultValue: 2f);
migrationBuilder.AddColumn<float>(
name: "Betroll91Multiplier",
table: "BotConfig",
nullable: false,
defaultValue: 0f);
defaultValue: 3f);
migrationBuilder.AddColumn<int>(
name: "CurrencyDropAmount",
table: "BotConfig",
nullable: false,
defaultValue: 0);
defaultValue: 1);
migrationBuilder.AddColumn<int>(
name: "MinimumBetAmount",
table: "BotConfig",
nullable: false,
defaultValue: 0);
defaultValue: 3);
migrationBuilder.AddColumn<int>(
name: "TriviaCurrencyReward",

View File

@ -4,8 +4,6 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using NadekoBot.Modules.Music.Classes;
namespace NadekoBot.Migrations
{

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Administration
{
private const string clockEmojiUrl = "https://cdn.discordapp.com/attachments/155726317222887425/258309524966866945/clock.png";
private static ShardedDiscordClient _client { get; }
private static DiscordShardedClient _client { get; }
private static Logger _log { get; }
private static string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
@ -81,7 +81,7 @@ namespace NadekoBot.Modules.Administration
_client.UserPresenceUpdated += _client_UserPresenceUpdated;
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
_client.GuildUserUpdated += _client_GuildUserUpdated;
_client.GuildMemberUpdated += _client_GuildUserUpdated;
#if !GLOBAL_NADEKO
_client.UserUpdated += _client_UserUpdated;
#endif
@ -94,7 +94,7 @@ namespace NadekoBot.Modules.Administration
MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
}
private static async void _client_UserUpdated(SocketUser before, SocketUser uAfter)
private static async Task _client_UserUpdated(SocketUser before, SocketUser uAfter)
{
try
{
@ -162,7 +162,7 @@ namespace NadekoBot.Modules.Administration
{ }
}
private static async void _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
private static async Task _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{
try
{
@ -317,7 +317,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_GuildUserUpdated(SocketGuildUser before, SocketGuildUser after)
private static async Task _client_GuildUserUpdated(SocketGuildUser before, SocketGuildUser after)
{
try
{
@ -360,7 +360,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
private static async Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
{
try
{
@ -403,7 +403,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_ChannelDestroyed(IChannel ich)
private static async Task _client_ChannelDestroyed(IChannel ich)
{
try
{
@ -430,7 +430,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_ChannelCreated(IChannel ich)
private static async Task _client_ChannelCreated(IChannel ich)
{
try
{
@ -456,7 +456,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); }
}
private static async void _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
private static async Task _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{
try
{
@ -498,7 +498,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_UserPresenceUpdated(Optional<SocketGuild> optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
private static async Task _client_UserPresenceUpdated(Optional<SocketGuild> optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
{
try
{
@ -532,7 +532,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_UserLeft(IGuildUser usr)
private static async Task _client_UserLeft(IGuildUser usr)
{
try
{
@ -556,7 +556,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_UserJoined(IGuildUser usr)
private static async Task _client_UserJoined(IGuildUser usr)
{
try
{
@ -580,7 +580,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); }
}
private static async void _client_UserUnbanned(IUser usr, IGuild guild)
private static async Task _client_UserUnbanned(IUser usr, IGuild guild)
{
try
{
@ -604,7 +604,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); }
}
private static async void _client_UserBanned(IUser usr, IGuild guild)
private static async Task _client_UserBanned(IUser usr, IGuild guild)
{
try
{
@ -627,7 +627,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); }
}
private static async void _client_MessageDeleted(ulong arg1, Optional<SocketMessage> imsg)
private static async Task _client_MessageDeleted(ulong arg1, Optional<SocketMessage> imsg)
{
try
@ -664,7 +664,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void _client_MessageUpdated(Optional<SocketMessage> optmsg, SocketMessage imsg2)
private static async Task _client_MessageUpdated(Optional<SocketMessage> optmsg, SocketMessage imsg2)
{
try
{

View File

@ -89,54 +89,66 @@ namespace NadekoBot.Modules.Administration
db.Open();
var com = db.CreateCommand();
com.CommandText = "SELECT * FROM Announcement";
var reader = com.ExecuteReader();
var i = 0;
while (reader.Read())
try
{
var gid = (ulong)(long)reader["ServerId"];
var greet = (long)reader["Greet"] == 1;
var greetDM = (long)reader["GreetPM"] == 1;
var greetChannel = (ulong)(long)reader["GreetChannelId"];
var greetMsg = (string)reader["GreetText"];
var bye = (long)reader["Bye"] == 1;
var byeDM = (long)reader["ByePM"] == 1;
var byeChannel = (ulong)(long)reader["ByeChannelId"];
var byeMsg = (string)reader["ByeText"];
var grdel = false;
var byedel = grdel;
var gc = uow.GuildConfigs.For(gid, set => set);
com.CommandText = "SELECT * FROM Announcement";
if (greetDM)
gc.SendDmGreetMessage = greet;
else
gc.SendChannelGreetMessage = greet;
gc.GreetMessageChannelId = greetChannel;
gc.ChannelGreetMessageText = greetMsg;
var reader = com.ExecuteReader();
while (reader.Read())
{
var gid = (ulong)(long)reader["ServerId"];
var greet = (long)reader["Greet"] == 1;
var greetDM = (long)reader["GreetPM"] == 1;
var greetChannel = (ulong)(long)reader["GreetChannelId"];
var greetMsg = (string)reader["GreetText"];
var bye = (long)reader["Bye"] == 1;
var byeDM = (long)reader["ByePM"] == 1;
var byeChannel = (ulong)(long)reader["ByeChannelId"];
var byeMsg = (string)reader["ByeText"];
var grdel = false;
var byedel = grdel;
var gc = uow.GuildConfigs.For(gid, set => set);
gc.SendChannelByeMessage = bye;
gc.ByeMessageChannelId = byeChannel;
gc.ChannelByeMessageText = byeMsg;
if (greetDM)
gc.SendDmGreetMessage = greet;
else
gc.SendChannelGreetMessage = greet;
gc.GreetMessageChannelId = greetChannel;
gc.ChannelGreetMessageText = greetMsg;
gc.AutoDeleteGreetMessagesTimer = gc.AutoDeleteByeMessagesTimer = grdel ? 30 : 0;
_log.Info(++i);
gc.SendChannelByeMessage = bye;
gc.ByeMessageChannelId = byeChannel;
gc.ChannelByeMessageText = byeMsg;
gc.AutoDeleteGreetMessagesTimer = gc.AutoDeleteByeMessagesTimer = grdel ? 30 : 0;
_log.Info(++i);
}
}
catch {
_log.Warn("Greet/bye messages won't be migrated");
}
var com2 = db.CreateCommand();
com.CommandText = "SELECT * FROM CurrencyState GROUP BY UserId";
i = 0;
var reader2 = com.ExecuteReader();
while (reader2.Read())
try
{
_log.Info(++i);
var curr = new Currency()
var reader2 = com.ExecuteReader();
while (reader2.Read())
{
Amount = (long)reader2["Value"],
UserId = (ulong)(long)reader2["UserId"]
};
uow.Currency.Add(curr);
_log.Info(++i);
var curr = new Currency()
{
Amount = (long)reader2["Value"],
UserId = (ulong)(long)reader2["UserId"]
};
uow.Currency.Add(curr);
}
}
catch
{
_log.Warn("Currency won't be migrated");
}
db.Close();
try { File.Move("data/nadekobot.sqlite", "data/DELETE_ME_nadekobot.sqlite"); } catch { }

View File

@ -37,8 +37,7 @@ namespace NadekoBot.Modules.Administration
static MuteCommands()
{
var _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
var configs = NadekoBot.AllGuildConfigs;
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
.Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName))
@ -50,12 +49,9 @@ namespace NadekoBot.Modules.Administration
));
NadekoBot.Client.UserJoined += Client_UserJoined;
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
}
private static async void Client_UserJoined(IGuildUser usr)
private static async Task Client_UserJoined(IGuildUser usr)
{
try
{

View File

@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Administration
if (string.IsNullOrWhiteSpace(status))
continue;
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value()));
await NadekoBot.Client.SetGame(status);
await NadekoBot.Client.SetGameAsync(status).ConfigureAwait(false);
}
}
catch (Exception ex)
@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Administration
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
new Dictionary<string, Func<string>> {
{"%servers%", () => NadekoBot.Client.GetGuildsCount().ToString()},
{"%servers%", () => NadekoBot.Client.GetGuildCount().ToString()},
{"%users%", () => NadekoBot.Client.GetGuilds().Sum(s => s.Users.Count).ToString()},
{"%playing%", () => {
var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);

View File

@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration
await Context.Channel.SendErrorAsync("⚠️ Cannot find that server").ConfigureAwait(false);
return;
}
if (server.OwnerId != NadekoBot.Client.CurrentUser().Id)
if (server.OwnerId != NadekoBot.Client.CurrentUser.Id)
{
await server.LeaveAsync().ConfigureAwait(false);
await Context.Channel.SendConfirmAsync("✅ Left server " + server.Name).ConfigureAwait(false);
@ -57,7 +57,7 @@ namespace NadekoBot.Modules.Administration
if (string.IsNullOrWhiteSpace(newName))
return;
await NadekoBot.Client.CurrentUser().ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
await NadekoBot.Client.CurrentUser.ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"Bot name changed to **{newName}**").ConfigureAwait(false);
}
@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly]
public async Task SetStatus([Remainder] SettableUserStatus status)
{
await NadekoBot.Client.SetStatus(status);
await NadekoBot.Client.SetStatusAsync(SettableUserStatusToUserStatus(status)).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"Bot status changed to **{status}**").ConfigureAwait(false);
}
@ -86,7 +86,7 @@ namespace NadekoBot.Modules.Administration
await sr.CopyToAsync(imgStream);
imgStream.Position = 0;
await NadekoBot.Client.CurrentUser().ModifyAsync(u => u.Avatar = new Image(imgStream)).ConfigureAwait(false);
await NadekoBot.Client.CurrentUser.ModifyAsync(u => u.Avatar = new Image(imgStream)).ConfigureAwait(false);
}
}
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly]
public async Task SetGame([Remainder] string game = null)
{
await NadekoBot.Client.SetGame(game).ConfigureAwait(false);
await NadekoBot.Client.SetGameAsync(game).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync("👾 **New game set.**").ConfigureAwait(false);
}
@ -108,7 +108,7 @@ namespace NadekoBot.Modules.Administration
{
name = name ?? "";
await NadekoBot.Client.SetStream(name, url).ConfigureAwait(false);
await NadekoBot.Client.SetGameAsync(name, url, StreamType.Twitch).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync(" **New stream set.**").ConfigureAwait(false);
}
@ -169,6 +169,23 @@ namespace NadekoBot.Modules.Administration
await Context.Channel.SendConfirmAsync("🆗").ConfigureAwait(false);
}
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
{
switch (sus)
{
case SettableUserStatus.Online:
return UserStatus.Online;
case SettableUserStatus.Invisible:
return UserStatus.Invisible;
case SettableUserStatus.Idle:
return UserStatus.AFK;
case SettableUserStatus.Dnd:
return UserStatus.DoNotDisturb;
}
return UserStatus.Online;
}
}
}
}

View File

@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Administration
_log = LogManager.GetCurrentClassLogger();
}
//todo optimize ASAP
private static async void UserLeft(IGuildUser user)
private static async Task UserLeft(IGuildUser user)
{
try
{
@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Administration
catch { }
}
private static async void UserJoined(IGuildUser user)
private static async Task UserJoined(IGuildUser user)
{
try
{

View File

@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Administration
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
}
private static async void UserUpdatedEventHandler(SocketUser iuser, SocketVoiceState before, SocketVoiceState after)
private static async Task UserUpdatedEventHandler(SocketUser iuser, SocketVoiceState before, SocketVoiceState after)
{
var user = (iuser as SocketGuildUser);
var guild = user?.Guild;

View File

@ -18,7 +18,7 @@ namespace NadekoBot.Modules.CustomReactions
public static Dictionary<string, Func<IUserMessage, string>> placeholders = new Dictionary<string, Func<IUserMessage, string>>()
{
{"%mention%", (ctx) => { return $"<@{NadekoBot.Client.CurrentUser().Id}>"; } },
{"%mention%", (ctx) => { return $"<@{NadekoBot.Client.CurrentUser.Id}>"; } },
{"%user%", (ctx) => { return ctx.Author.Mention; } },
{"%rnduser%", (ctx) => {
var ch = ctx.Channel as ITextChannel;

View File

@ -207,15 +207,15 @@ namespace NadekoBot.Modules.Gambling
}
private void Client_MessageReceived(SocketMessage imsg)
private Task Client_MessageReceived(SocketMessage imsg)
{
var msg = imsg as SocketUserMessage;
if (msg == null)
return;
return Task.CompletedTask;
if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel)
return;
return Task.CompletedTask;
messagesSinceGameStarted++;
return;
return Task.CompletedTask;
}
private async Task CheckForFullGameAsync(CancellationToken cancelToken)

View File

@ -0,0 +1,84 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Gambling
{
public partial class Gambling
{
[Group]
public class CurrencyEvents : ModuleBase
{
public enum CurrencyEvent
{
FlowerReaction
}
//flower reaction event
public static readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartEvent(CurrencyEvent e)
{
var channel = (ITextChannel)Context.Channel;
try
{
switch (e)
{
case CurrencyEvent.FlowerReaction:
await FlowerReactionEvent(Context).ConfigureAwait(false);
break;
default:
break;
}
}
catch { }
}
public static async Task FlowerReactionEvent(CommandContext Context)
{
var msg = await Context.Channel.SendConfirmAsync("Flower reaction event started!",
"Add 🌸 reaction to this message to get 100" + NadekoBot.BotConfig.CurrencySign,
footer: "This event is active for 24 hours.")
.ConfigureAwait(false);
try { await msg.AddReactionAsync("🌸").ConfigureAwait(false); }
catch
{
try { await msg.AddReactionAsync("🌸").ConfigureAwait(false); }
catch
{
try { await msg.DeleteAsync().ConfigureAwait(false); }
catch { }
}
}
using (msg.OnReaction(async (r) =>
{
try
{
if (r.Emoji.Name == "🌸" && r.User.IsSpecified && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
{
try { await CurrencyHandler.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", 100, false).ConfigureAwait(false); } catch { }
}
}
catch { }
}))
{
await Task.Delay(TimeSpan.FromHours(24)).ConfigureAwait(false);
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
_flowerReactionAwardedUsers.Clear();
}
}
}
}
}

View File

@ -168,7 +168,7 @@ namespace NadekoBot.Modules.Games
await End().ConfigureAwait(false);
}
private async void PotentialAcro(SocketMessage arg)
private async Task PotentialAcro(SocketMessage arg)
{
try
{

View File

@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Games
if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out cleverbot))
return false;
var nadekoId = NadekoBot.Client.CurrentUser().Id;
var nadekoId = NadekoBot.Client.CurrentUser.Id;
var normalMention = $"<@{nadekoId}> ";
var nickMention = $"<@!{nadekoId}> ";
string message;

View File

@ -114,7 +114,7 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
await GameChannel.EmbedAsync(embed.WithOkColor()).ConfigureAwait(false);
}
private async void PotentialGuess(SocketMessage msg)
private async Task PotentialGuess(SocketMessage msg)
{
try
{

View File

@ -51,7 +51,7 @@ namespace NadekoBot.Modules.Games
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
}
private static async void PotentialFlowerGeneration(SocketMessage imsg)
private static async Task PotentialFlowerGeneration(SocketMessage imsg)
{
try
{

View File

@ -153,7 +153,7 @@ namespace NadekoBot.Modules.Games
await originalMessage.Channel.EmbedAsync(GetStats("POLL CLOSED")).ConfigureAwait(false);
}
private async void Vote(SocketMessage imsg)
private async Task Vote(SocketMessage imsg)
{
try
{

View File

@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Games
NadekoBot.Client.MessageReceived += AnswerReceived;
}
private async void AnswerReceived(SocketMessage imsg)
private async Task AnswerReceived(SocketMessage imsg)
{
try
{

View File

@ -56,7 +56,9 @@ namespace NadekoBot.Modules.Games.Trivia
// load question
CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
if (CurrentQuestion == null)
if (CurrentQuestion == null ||
string.IsNullOrWhiteSpace(CurrentQuestion.Answer) ||
string.IsNullOrWhiteSpace(CurrentQuestion.Question))
{
await channel.SendErrorAsync("Trivia Game", "Failed loading a question.").ConfigureAwait(false);
return;
@ -74,7 +76,9 @@ namespace NadekoBot.Modules.Games.Trivia
questionMessage = await channel.EmbedAsync(questionEmbed).ConfigureAwait(false);
}
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound ||
ex.StatusCode == System.Net.HttpStatusCode.Forbidden ||
ex.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
return;
}
@ -143,7 +147,7 @@ namespace NadekoBot.Modules.Games.Trivia
try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
}
private async void PotentialGuess(SocketMessage imsg)
private async Task PotentialGuess(SocketMessage imsg)
{
try
{

View File

@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Games
else if ((pick == 0 && nadekoPick == 1) ||
(pick == 1 && nadekoPick == 2) ||
(pick == 2 && nadekoPick == 0))
msg = $"{NadekoBot.Client.CurrentUser().Mention} won! {GetRPSPick(nadekoPick)} beats {GetRPSPick(pick)}";
msg = $"{NadekoBot.Client.CurrentUser.Mention} won! {GetRPSPick(nadekoPick)} beats {GetRPSPick(pick)}";
else
msg = $"{Context.User.Mention} won! {GetRPSPick(pick)} beats {GetRPSPick(nadekoPick)}";

View File

@ -137,7 +137,7 @@ namespace NadekoBot.Modules.Help
}
helpstr.AppendLine($"{string.Join(" ", com.Aliases.Select(a => "`" + a + "`"))} | {string.Format(com.Summary, com.Module.GetPrefix())} {GetCommandRequirements(com)} | {string.Format(com.Remarks, com.Module.GetPrefix())}");
}
helpstr = helpstr.Replace(NadekoBot.Client.CurrentUser().Username , "@BotName");
helpstr = helpstr.Replace(NadekoBot.Client.CurrentUser.Username , "@BotName");
File.WriteAllText("../../docs/Commands List.md", helpstr.ToString());
await Context.Channel.SendConfirmAsync("Commandlist Regenerated").ConfigureAwait(false);
}

View File

@ -140,9 +140,15 @@ namespace NadekoBot.Modules.Music.Classes
RemoveSongAt(index, true);
OnStarted(this, CurrentSong);
await CurrentSong.Play(audioClient, cancelToken);
OnCompleted(this, CurrentSong);
try
{
await CurrentSong.Play(audioClient, cancelToken);
}
catch(OperationCanceledException)
{
OnCompleted(this, CurrentSong);
}
if (RepeatPlaylist)
AddSong(CurrentSong, CurrentSong.QueuerName);
@ -151,7 +157,6 @@ namespace NadekoBot.Modules.Music.Classes
AddSong(CurrentSong, 0);
}
catch (OperationCanceledException) { }
catch (Exception ex)
{
Console.WriteLine("Music thread almost crashed.");
@ -337,13 +342,13 @@ namespace NadekoBot.Modules.Music.Classes
});
}
public Task MoveToVoiceChannel(IVoiceChannel voiceChannel)
{
if (audioClient?.ConnectionState != ConnectionState.Connected)
throw new InvalidOperationException("Can't move while bot is not connected to voice channel.");
PlaybackVoiceChannel = voiceChannel;
return PlaybackVoiceChannel.ConnectAsync();
}
//public async Task MoveToVoiceChannel(IVoiceChannel voiceChannel)
//{
// if (audioClient?.ConnectionState != ConnectionState.Connected)
// throw new InvalidOperationException("Can't move while bot is not connected to voice channel.");
// PlaybackVoiceChannel = voiceChannel;
// audioClient = await voiceChannel.ConnectAsync().ConfigureAwait(false);
//}
public bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;

View File

@ -37,30 +37,49 @@ namespace NadekoBot.Modules.Music
Directory.CreateDirectory(MusicDataPath);
}
private static async void Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
private static Task Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
{
var usr = iusr as SocketGuildUser;
if (usr == null ||
oldState.VoiceChannel == newState.VoiceChannel)
return;
return Task.CompletedTask;
MusicPlayer player;
if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player))
return;
return Task.CompletedTask;
try
{
var users = await player.PlaybackVoiceChannel.GetUsersAsync().Flatten().ConfigureAwait(false);
//if bot moved
if ((player.PlaybackVoiceChannel == oldState.VoiceChannel) &&
usr.Id == NadekoBot.Client.CurrentUser.Id)
{
if (player.Paused && newState.VoiceChannel.Users.Count > 1) //unpause if there are people in the new channel
player.TogglePause();
else if (!player.Paused && newState.VoiceChannel.Users.Count <= 1) // pause if there are no users in the new channel
player.TogglePause();
return Task.CompletedTask;
}
//if some other user moved
if ((player.PlaybackVoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause
player.Paused &&
users.Count() == 2) || // keep in mind bot is in the channel (+1)
newState.VoiceChannel.Users.Count == 2) || // keep in mind bot is in the channel (+1)
(player.PlaybackVoiceChannel == oldState.VoiceChannel && // if left last, and player unpaused, pause
!player.Paused &&
users.Count() == 1))
oldState.VoiceChannel.Users.Count == 1))
{
player.TogglePause();
return Task.CompletedTask;
}
}
catch { }
return Task.CompletedTask;
}
[NadekoCommand, Usage, Description, Aliases]
@ -192,7 +211,7 @@ namespace NadekoBot.Modules.Music
int startAt = itemsPerPage * (curPage - 1);
var number = 0 + startAt;
var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName($"Player Queue")
.WithAuthor(eab => eab.WithName($"Player Queue - Page {curPage}/{lastPage + 1}")
.WithMusicIcon())
.WithDescription(string.Join("\n", musicPlayer.Playlist
.Skip(startAt)
@ -217,7 +236,7 @@ namespace NadekoBot.Modules.Music
}
return embed;
};
await Context.Channel.SendPaginatedConfirmAsync(page, printAction, lastPage).ConfigureAwait(false);
await Context.Channel.SendPaginatedConfirmAsync(page, printAction, lastPage, false).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -448,17 +467,17 @@ namespace NadekoBot.Modules.Music
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Move()
{
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task Move()
//{
MusicPlayer musicPlayer;
var voiceChannel = ((IGuildUser)Context.User).VoiceChannel;
if (voiceChannel == null || voiceChannel.Guild != Context.Guild || !MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return;
await musicPlayer.MoveToVoiceChannel(voiceChannel);
}
// MusicPlayer musicPlayer;
// var voiceChannel = ((IGuildUser)Context.User).VoiceChannel;
// if (voiceChannel == null || voiceChannel.Guild != Context.Guild || !MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
// return;
// await musicPlayer.MoveToVoiceChannel(voiceChannel);
//}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
@ -814,7 +833,7 @@ namespace NadekoBot.Modules.Music
.WithFooter(ef => ef.WithText(song.PrettyInfo)))
.ConfigureAwait(false);
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.ProviderType == MusicType.Normal)
{
await QueueSong(await queuer.Guild.GetCurrentUserAsync(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
}

View File

@ -20,6 +20,7 @@ namespace NadekoBot.Modules.NSFW
public class NSFW : DiscordModule
{
private static ConcurrentDictionary<ulong, Timer> AutoHentaiTimers { get; } = new ConcurrentDictionary<ulong, Timer>();
private static ConcurrentHashSet<ulong> _hentaiBombBlacklist { get; } = new ConcurrentHashSet<ulong>();
private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
{
@ -56,7 +57,8 @@ namespace NadekoBot.Modules.NSFW
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithImageUrl(link)
.WithDescription("Tag: " + tag)).ConfigureAwait(false);
.WithDescription("Tag: " + tag))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -90,7 +92,7 @@ namespace NadekoBot.Modules.NSFW
if (tagsArr == null || tagsArr.Length == 0)
await InternalHentai(Context.Channel, null, true).ConfigureAwait(false);
else
await InternalHentai(Context.Channel, tagsArr[new NadekoRandom().Next(0, tagsArr.Length)], true);
await InternalHentai(Context.Channel, tagsArr[new NadekoRandom().Next(0, tagsArr.Length)], true).ConfigureAwait(false);
}
catch { }
}, null, interval * 1000, interval * 1000);
@ -101,29 +103,39 @@ namespace NadekoBot.Modules.NSFW
return t;
});
await Context.Channel.SendConfirmAsync($"Autohentai started. Reposting every {interval}s with one of the following tags:\n{string.Join(", ", tagsArr)}").ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"Autohentai started. Reposting every {interval}s with one of the following tags:\n{string.Join(", ", tagsArr)}")
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
public async Task HentaiBomb([Remainder] string tag = null)
{
tag = tag?.Trim() ?? "";
tag = "rating%3Aexplicit+" + tag;
var links = await Task.WhenAll(GetGelbooruImageLink(tag),
GetDanbooruImageLink(tag),
GetKonachanImageLink(tag),
GetYandereImageLink(tag)).ConfigureAwait(false);
var linksEnum = links?.Where(l => l != null);
if (links == null || !linksEnum.Any())
{
await Context.Channel.SendErrorAsync("No results found.").ConfigureAwait(false);
if (!_hentaiBombBlacklist.Add(Context.User.Id))
return;
}
try
{
tag = tag?.Trim() ?? "";
tag = "rating%3Aexplicit+" + tag;
await Context.Channel.SendMessageAsync(String.Join("\n\n", linksEnum)).ConfigureAwait(false);
var links = await Task.WhenAll(GetGelbooruImageLink(tag),
GetDanbooruImageLink(tag),
GetKonachanImageLink(tag),
GetYandereImageLink(tag)).ConfigureAwait(false);
var linksEnum = links?.Where(l => l != null);
if (links == null || !linksEnum.Any())
{
await Context.Channel.SendErrorAsync("No results found.").ConfigureAwait(false);
return;
}
await Context.Channel.SendMessageAsync(String.Join("\n\n", linksEnum)).ConfigureAwait(false);
}
finally {
await Task.Delay(5000).ConfigureAwait(false);
_hentaiBombBlacklist.TryRemove(Context.User.Id);
}
}
@ -135,12 +147,13 @@ namespace NadekoBot.Modules.NSFW
var url = await GetDanbooruImageLink(tag).ConfigureAwait(false);
if (url == null)
await Context.Channel.SendErrorAsync(Context.User.Mention + " No results.");
await Context.Channel.SendErrorAsync(Context.User.Mention + " No results.").ConfigureAwait(false);
else
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(Context.User.Mention + " " + tag)
.WithImageUrl(url)
.WithFooter(efb => efb.WithText("Danbooru"))).ConfigureAwait(false);
.WithFooter(efb => efb.WithText("Danbooru")))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -172,7 +185,8 @@ namespace NadekoBot.Modules.NSFW
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(Context.User.Mention + " " + tag)
.WithImageUrl(url)
.WithFooter(efb => efb.WithText("e621"))).ConfigureAwait(false);
.WithFooter(efb => efb.WithText("e621")))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -217,14 +231,14 @@ namespace NadekoBot.Modules.NSFW
}
}
public static async Task<string> GetDanbooruImageLink(string tag)
public static Task<string> GetDanbooruImageLink(string tag) => Task.Run(async () =>
{
try
{
using (var http = new HttpClient())
{
http.AddFakeHeaders();
var data = await http.GetStreamAsync("https://danbooru.donmai.us/posts.xml?limit=100&tags=" + tag);
var data = await http.GetStreamAsync("https://danbooru.donmai.us/posts.xml?limit=100&tags=" + tag).ConfigureAwait(false);
var doc = new XmlDocument();
doc.Load(data);
var nodes = doc.GetElementsByTagName("file-url");
@ -237,17 +251,17 @@ namespace NadekoBot.Modules.NSFW
{
return null;
}
}
});
public static async Task<string> GetE621ImageLink(string tag)
public static Task<string> GetE621ImageLink(string tag) => Task.Run(async () =>
{
try
{
using (var http = new HttpClient())
{
http.AddFakeHeaders();
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + tag);
var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + tag).ConfigureAwait(false);
var doc = new XmlDocument();
doc.Load(data);
var nodes = doc.GetElementsByTagName("file_url");
@ -260,7 +274,7 @@ namespace NadekoBot.Modules.NSFW
{
return null;
}
}
});
public static Task<string> GetYandereImageLink(string tag) =>
Searches.Searches.InternalDapiSearch(tag, Searches.Searches.DapiSearchType.Yandere);

View File

@ -0,0 +1,101 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Permissions
{
public partial class Permissions
{
[Group]
public class CommandCostCommands : ModuleBase
{
private static readonly ConcurrentDictionary<string, int> _commandCosts = new ConcurrentDictionary<string, int>();
public static IReadOnlyDictionary<string, int> CommandCosts => _commandCosts;
static CommandCostCommands()
{
//_commandCosts = new ConcurrentDictionary<string, int>(NadekoBot.BotConfig.CommandCosts.ToDictionary(
// x => x.CommandName.Trim().ToUpperInvariant(),
// x => x.Cost));
}
[NadekoCommand, Usage, Description, Aliases]
public async Task CmdCosts(int page = 1)
{
var prices = _commandCosts.ToList();
if (!prices.Any())
{
await Context.Channel.SendConfirmAsync("No costs set.").ConfigureAwait(false);
return;
}
await Context.Channel.SendPaginatedConfirmAsync(page, (curPage) => {
var embed = new EmbedBuilder().WithOkColor()
.WithTitle("Command Costs");
var current = prices.Skip((curPage - 1) * 9)
.Take(9);
foreach (var price in current)
{
embed.AddField(efb => efb.WithName(price.Key).WithValue(price.Value.ToString()).WithIsInline(true));
}
return embed;
}, prices.Count / 9).ConfigureAwait(false);
}
//[NadekoCommand, Usage, Description, Aliases]
//public async Task CommandCost(int cost, CommandInfo cmd)
//{
// if (cost < 0)
// return;
// var cmdName = cmd.Aliases.First().ToLowerInvariant();
// var cmdPrice = new CommandCost()
// {
// CommandName = cmdName,
// Cost = cost
// };
// using (var uow = DbHandler.UnitOfWork())
// {
// var bc = uow.BotConfig.GetOrCreate();
// if (cost != 0)
// {
// var elem = bc.CommandCosts.Where(cc => cc.CommandName == cmdPrice.CommandName).FirstOrDefault();
// if (elem == null)
// bc.CommandCosts.Add(cmdPrice);
// else
// elem.Cost = cost;
// _commandCosts.AddOrUpdate(cmdName, cost, (key, old) => cost);
// }
// else
// {
// bc.CommandCosts.RemoveAt(bc.CommandCosts.IndexOf(cmdPrice));
// int throwaway;
// _commandCosts.TryRemove(cmdName, out throwaway);
// }
// await uow.CompleteAsync().ConfigureAwait(false);
// }
// if (cost == 0)
// await Context.Channel.SendConfirmAsync($"Removed the cost from the {Format.Bold(cmd.Name)} command.").ConfigureAwait(false);
// else
// await Context.Channel.SendConfirmAsync($"{Format.Bold(cmd.Name)} now costs {cost}{NadekoBot.BotConfig.CurrencySign} to run.").ConfigureAwait(false);
//}
}
}
}

View File

@ -517,7 +517,8 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(eab => eab.WithUrl(link)
.WithIconUrl("http://res.cloudinary.com/urbandictionary/image/upload/a_exif,c_fit,h_200,w_200/v1394975045/b8oszuu3tbq7ebyo7vo1.jpg")
.WithName(query))
.WithDescription(desc));
.WithDescription(desc))
.ConfigureAwait(false);
}
catch
{
@ -572,9 +573,9 @@ namespace NadekoBot.Modules.Searches
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query));
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
if (data.Query.Pages[0].Missing)
await Context.Channel.SendErrorAsync("That page could not be found.");
await Context.Channel.SendErrorAsync("That page could not be found.").ConfigureAwait(false);
else
await Context.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl);
await Context.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl).ConfigureAwait(false);
}
}
@ -588,7 +589,7 @@ namespace NadekoBot.Modules.Searches
img.BackgroundColor(new ImageSharp.Color(color));
await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png");
await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png").ConfigureAwait(false); ;
}
[NadekoCommand, Usage, Description, Aliases]
@ -642,7 +643,7 @@ namespace NadekoBot.Modules.Searches
var response = $@"`Title:` {found["title"].ToString()}
`Quality:` {found["quality"]}
`URL:` {await NadekoBot.Google.ShortenUrl(found["url"].ToString()).ConfigureAwait(false)}";
await Context.Channel.SendMessageAsync(response);
await Context.Channel.SendMessageAsync(response).ConfigureAwait(false);
}
catch
{
@ -774,20 +775,24 @@ namespace NadekoBot.Modules.Searches
}
try
{
using (var http = new HttpClient())
var toReturn = await Task.Run(async () =>
{
http.AddFakeHeaders();
var data = await http.GetStreamAsync(website);
var doc = new XmlDocument();
doc.Load(data);
using (var http = new HttpClient())
{
http.AddFakeHeaders();
var data = await http.GetStreamAsync(website).ConfigureAwait(false);
var doc = new XmlDocument();
doc.Load(data);
var node = doc.LastChild.ChildNodes[new NadekoRandom().Next(0, doc.LastChild.ChildNodes.Count)];
var node = doc.LastChild.ChildNodes[new NadekoRandom().Next(0, doc.LastChild.ChildNodes.Count)];
var url = node.Attributes["file_url"].Value;
if (!url.StartsWith("http"))
url = "https:" + url;
return url;
}
var url = node.Attributes["file_url"].Value;
if (!url.StartsWith("http"))
url = "https:" + url;
return url;
}
}).ConfigureAwait(false);
return toReturn;
}
catch
{

View File

@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Utility
var channel = imsg.Channel as ITextChannel;
if (channel == null)
return;
if (msg.Author.Id == NadekoBot.Client.CurrentUser().Id) return;
if (msg.Author.Id == NadekoBot.Client.CurrentUser.Id) return;
foreach (var subscriber in Subscribers)
{
var set = subscriber.Value;

View File

@ -277,27 +277,25 @@ namespace NadekoBot.Modules.Utility
.WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg"))
.AddField(efb => efb.WithName(Format.Bold("Author")).WithValue(stats.Author).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Library")).WithValue(stats.Library).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.CurrentUser().Id.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.CurrentUser.Id.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Commands Ran")).WithValue(stats.CommandsRan.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Messages")).WithValue($"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)").WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Owner ID(s)")).WithValue(string.Join("\n", NadekoBot.Credentials.OwnerIds)).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Uptime")).WithValue(stats.GetUptimeString("\n")).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuildsCount()} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuildCount()} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true))
#if !GLOBAL_NADEKO
.WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued."))
#endif
);
}
private Regex emojiFinder { get; } = new Regex(@"<:(?<name>.+?):(?<id>\d*)>", RegexOptions.Compiled);
[NadekoCommand, Usage, Description, Aliases]
public async Task Showemojis([Remainder] string emojis)
{
var matches = emojiFinder.Matches(emojis);
var tags = Context.Message.Tags.Where(t => t.Type == TagType.Emoji).Select(t => (Emoji)t.Value);
var result = string.Join("\n", matches.Cast<Match>()
.Select(m => $"**Name:** {m.Groups["name"]} **Link:** http://discordapp.com/api/emojis/{m.Groups["id"]}.png"));
var result = string.Join("\n", tags.Select(m => $"**Name:** {m} **Link:** {m.Url}"));
if (string.IsNullOrWhiteSpace(result))
await Context.Channel.SendErrorAsync("No special emojis found.");

View File

@ -28,7 +28,7 @@ namespace NadekoBot
public static CommandService CommandService { get; private set; }
public static CommandHandler CommandHandler { get; private set; }
public static ShardedDiscordClient Client { get; private set; }
public static DiscordShardedClient Client { get; private set; }
public static BotCredentials Credentials { get; private set; }
public static GoogleApiService Google { get; private set; }
@ -59,7 +59,7 @@ namespace NadekoBot
_log.Info("Starting NadekoBot v" + StatsService.BotVersion);
//create client
Client = new ShardedDiscordClient(new DiscordSocketConfig
Client = new DiscordShardedClient(new DiscordSocketConfig
{
AudioMode = Discord.Audio.AudioMode.Outgoing,
MessageCacheSize = 10,
@ -67,6 +67,9 @@ namespace NadekoBot
TotalShards = Credentials.TotalShards,
ConnectionTimeout = int.MaxValue
});
#if GLOBAL_NADEKO
Client.Log += Client_Log;
#endif
//initialize Services
CommandService = new CommandService(new CommandServiceConfig() {
@ -93,9 +96,8 @@ namespace NadekoBot
//connect
await Client.LoginAsync(TokenType.Bot, Credentials.Token).ConfigureAwait(false);
await Client.ConnectAsync().ConfigureAwait(false);
#if !GLOBAL_NADEKO
await Client.DownloadAllUsersAsync().ConfigureAwait(false);
#endif
Stats.Initialize();
_log.Info("Connected");
@ -104,6 +106,7 @@ namespace NadekoBot
ModulePrefixes = new ConcurrentDictionary<string, string>(NadekoBot.BotConfig.ModulePrefixes.OrderByDescending(mp => mp.Prefix.Length).ToDictionary(m => m.ModuleName, m => m.Prefix));
// start handling messages received in commandhandler
await CommandHandler.StartHandling().ConfigureAwait(false);
await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly).ConfigureAwait(false);
@ -114,6 +117,15 @@ namespace NadekoBot
Console.WriteLine(await Stats.Print().ConfigureAwait(false));
}
private Task Client_Log(LogMessage arg)
{
_log.Warn(arg.Source + " | " + arg.Message);
if (arg.Exception != null)
_log.Warn(arg.Exception);
return Task.CompletedTask;
}
public async Task RunAndBlockAsync(params string[] args)
{
await RunAsync(args).ConfigureAwait(false);

View File

@ -1760,6 +1760,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to cmdcosts.
/// </summary>
public static string cmdcosts_cmd {
get {
return ResourceManager.GetString("cmdcosts_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a list of command costs. Paginated with 9 command per page..
/// </summary>
public static string cmdcosts_desc {
get {
return ResourceManager.GetString("cmdcosts_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}cmdcosts` or `{0}cmdcosts 2`.
/// </summary>
public static string cmdcosts_usage {
get {
return ResourceManager.GetString("cmdcosts_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to color clr.
/// </summary>
@ -1787,6 +1814,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to commandcost cmdcost.
/// </summary>
public static string commandcost_cmd {
get {
return ResourceManager.GetString("commandcost_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sets a price for a command. Running that command will take currency from users. Set 0 to remove the price..
/// </summary>
public static string commandcost_desc {
get {
return ResourceManager.GetString("commandcost_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}cmdcost 0 !!q` or `{0}cmdcost 1 &gt;8ball`.
/// </summary>
public static string commandcost_usage {
get {
return ResourceManager.GetString("commandcost_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to commands cmds.
/// </summary>
@ -7241,6 +7295,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to startevent.
/// </summary>
public static string startevent_cmd {
get {
return ResourceManager.GetString("startevent_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Starts one of the events seen on public nadeko..
/// </summary>
public static string startevent_desc {
get {
return ResourceManager.GetString("startevent_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}startevent flowerreaction`.
/// </summary>
public static string startevent_usage {
get {
return ResourceManager.GetString("startevent_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to startwar sw.
/// </summary>

View File

@ -2925,4 +2925,31 @@
<data name="antispamignore_usage" xml:space="preserve">
<value>`{0}antispamignore`</value>
</data>
<data name="cmdcosts_cmd" xml:space="preserve">
<value>cmdcosts</value>
</data>
<data name="cmdcosts_desc" xml:space="preserve">
<value>Shows a list of command costs. Paginated with 9 command per page.</value>
</data>
<data name="cmdcosts_usage" xml:space="preserve">
<value>`{0}cmdcosts` or `{0}cmdcosts 2`</value>
</data>
<data name="commandcost_cmd" xml:space="preserve">
<value>commandcost cmdcost</value>
</data>
<data name="commandcost_desc" xml:space="preserve">
<value>Sets a price for a command. Running that command will take currency from users. Set 0 to remove the price.</value>
</data>
<data name="commandcost_usage" xml:space="preserve">
<value>`{0}cmdcost 0 !!q` or `{0}cmdcost 1 &gt;8ball`</value>
</data>
<data name="startevent_cmd" xml:space="preserve">
<value>startevent</value>
</data>
<data name="startevent_desc" xml:space="preserve">
<value>Starts one of the events seen on public nadeko.</value>
</data>
<data name="startevent_usage" xml:space="preserve">
<value>`{0}startevent flowerreaction`</value>
</data>
</root>

View File

@ -32,9 +32,9 @@ namespace NadekoBot.Services
{
public const int GlobalCommandsCooldown = 1500;
private ShardedDiscordClient _client;
private CommandService _commandService;
private Logger _log;
private readonly DiscordShardedClient _client;
private readonly CommandService _commandService;
private readonly Logger _log;
private List<IDMChannel> ownerChannels { get; set; }
@ -46,7 +46,7 @@ namespace NadekoBot.Services
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
private Timer clearUsersOnShortCooldown { get; }
public CommandHandler(ShardedDiscordClient client, CommandService commandService)
public CommandHandler(DiscordShardedClient client, CommandService commandService)
{
_client = client;
_commandService = commandService;
@ -100,8 +100,8 @@ namespace NadekoBot.Services
BlacklistCommands.BlacklistedChannels.Contains(usrMsg.Channel.Id) ||
BlacklistCommands.BlacklistedUsers.Contains(usrMsg.Author.Id);
private async Task LogSuccessfulExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, Stopwatch sw)
const float oneThousandth = 1.0f / 1000;
private async Task LogSuccessfulExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, int ticks)
{
await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
_log.Info("Command Executed after {4}s\n\t" +
@ -113,10 +113,10 @@ namespace NadekoBot.Services
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
usrMsg.Content, // {3}
sw.Elapsed.TotalSeconds);
ticks * oneThousandth);
}
private void LogErroredExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, Stopwatch sw)
private void LogErroredExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, int ticks)
{
_log.Warn("Command Errored after {5}s\n\t" +
"User: {0}\n\t" +
@ -129,7 +129,7 @@ namespace NadekoBot.Services
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
usrMsg.Content,// {3}
exec.Result.ErrorReason, // {4}
sw.Elapsed.TotalSeconds // {5}
ticks * oneThousandth // {5}
);
}
@ -180,13 +180,15 @@ namespace NadekoBot.Services
return false;
}
private async void MessageReceivedHandler(SocketMessage msg)
private async Task MessageReceivedHandler(SocketMessage msg)
{
try
{
if (msg.Author.IsBot || !NadekoBot.Ready) //no bots, wait until bot connected and initialized
return;
var execTime = Environment.TickCount;
var usrMsg = msg as SocketUserMessage;
if (usrMsg == null) //has to be an user message, not system/other messages.
return;
@ -226,17 +228,16 @@ namespace NadekoBot.Services
string messageContent = usrMsg.Content;
// execute the command and measure the time it took
var sw = Stopwatch.StartNew();
var exec = await ExecuteCommand(new CommandContext(_client.MainClient, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best);
sw.Stop();
var exec = await ExecuteCommand(new CommandContext(_client, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best);
execTime = Environment.TickCount - execTime;
if (exec.Result.IsSuccess)
{
await LogSuccessfulExecution(usrMsg, exec, channel, sw).ConfigureAwait(false);
await LogSuccessfulExecution(usrMsg, exec, channel, execTime).ConfigureAwait(false);
}
else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand)
{
LogErroredExecution(usrMsg, exec, channel, sw);
LogErroredExecution(usrMsg, exec, channel, execTime);
if (guild != null && exec.CommandInfo != null && exec.Result.Error == CommandError.Exception)
{
if (exec.PermissionCache != null && exec.PermissionCache.Verbose)
@ -354,6 +355,16 @@ namespace NadekoBot.Services
return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
}
}
int price;
if (Permissions.CommandCostCommands.CommandCosts.TryGetValue(cmd.Aliases.First().Trim().ToLowerInvariant(), out price) && price > 0)
{
var success = await CurrencyHandler.RemoveCurrencyAsync(context.User.Id, $"Running {cmd.Name} command.", price).ConfigureAwait(false);
if (!success)
{
return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
}
}
}

View File

@ -31,6 +31,11 @@ namespace NadekoBot.Services.Database.Models
public float Betroll67Multiplier { get; set; } = 2;
public float Betroll91Multiplier { get; set; } = 3;
public float Betroll100Multiplier { get; set; } = 10;
//public HashSet<CommandCost> CommandCosts { get; set; } = new HashSet<CommandCost>();
/// <summary>
/// I messed up, don't use
/// </summary>
public HashSet<CommandPrice> CommandPrices { get; set; } = new HashSet<CommandPrice>();

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Models
{
public class CommandCost : DbEntity
{
public int Cost { get; set; }
public string CommandName { get; set; }
public override int GetHashCode() =>
CommandName.GetHashCode();
public override bool Equals(object obj)
{
var instance = obj as CommandCost;
if (instance == null)
return false;
return instance.CommandName == CommandName;
}
}
}

View File

@ -11,18 +11,5 @@ namespace NadekoBot.Services.Database.Models
public int Price { get; set; }
//this is unique
public string CommandName { get; set; }
public override int GetHashCode() =>
CommandName.GetHashCode();
public override bool Equals(object obj)
{
var instance = obj as CommandPrice;
if (instance == null)
return false;
return instance.CommandName == CommandName;
}
}
}

View File

@ -235,9 +235,14 @@ namespace NadekoBot.Services.Database
#endregion
#region CommandPrice
//well, i failed
modelBuilder.Entity<CommandPrice>()
.HasIndex(cp => cp.Price)
.IsUnique();
//modelBuilder.Entity<CommandCost>()
// .HasIndex(cp => cp.CommandName)
// .IsUnique();
#endregion
}
}

View File

@ -17,6 +17,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.Include(bc => bc.Blacklist)
.Include(bc => bc.EightBallResponses)
.Include(bc => bc.ModulePrefixes)
//.Include(bc => bc.CommandCosts)
.FirstOrDefault();
if (config == null)

View File

@ -26,7 +26,7 @@ namespace NadekoBot.Services.Discord
NadekoBot.Client.ReactionsCleared += Discord_ReactionsCleared;
}
private void Discord_ReactionsCleared(ulong messageId, Optional<SocketUserMessage> reaction)
private Task Discord_ReactionsCleared(ulong messageId, Optional<SocketUserMessage> reaction)
{
try
{
@ -34,9 +34,11 @@ namespace NadekoBot.Services.Discord
OnReactionsCleared?.Invoke();
}
catch { }
return Task.CompletedTask;
}
private void Discord_ReactionRemoved(ulong messageId, Optional<SocketUserMessage> arg2, SocketReaction reaction)
private Task Discord_ReactionRemoved(ulong messageId, Optional<SocketUserMessage> arg2, SocketReaction reaction)
{
try
{
@ -44,9 +46,11 @@ namespace NadekoBot.Services.Discord
OnReactionRemoved?.Invoke(reaction);
}
catch { }
return Task.CompletedTask;
}
private void Discord_ReactionAdded(ulong messageId, Optional<SocketUserMessage> message, SocketReaction reaction)
private Task Discord_ReactionAdded(ulong messageId, Optional<SocketUserMessage> message, SocketReaction reaction)
{
try
{
@ -54,6 +58,8 @@ namespace NadekoBot.Services.Discord
OnReactionAdded?.Invoke(reaction);
}
catch { }
return Task.CompletedTask;
}
public void UnsubAll()

View File

@ -1,4 +1,5 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
using System;
using System.Collections.Generic;
@ -11,10 +12,10 @@ namespace NadekoBot.Services.Impl
{
public class StatsService : IStatsService
{
private ShardedDiscordClient client;
private DiscordShardedClient client;
private DateTime started;
public const string BotVersion = "1.1.0";
public const string BotVersion = "1.1.1";
public string Author => "Kwoth#2560";
public string Library => "Discord.Net";
@ -30,7 +31,7 @@ namespace NadekoBot.Services.Impl
Timer carbonitexTimer { get; }
public StatsService(ShardedDiscordClient client, CommandHandler cmdHandler)
public StatsService(DiscordShardedClient client, CommandHandler cmdHandler)
{
this.client = client;
@ -39,21 +40,14 @@ namespace NadekoBot.Services.Impl
this.client.MessageReceived += _ => Task.FromResult(MessageCounter++);
cmdHandler.CommandExecuted += (_, e) => Task.FromResult(CommandsRan++);
this.client.Disconnected += _ => Reset();
this.client.Connected += () =>
{
var guilds = this.client.GetGuilds();
_textChannels = guilds.Sum(g => g.Channels.Where(cx => cx is ITextChannel).Count());
_voiceChannels = guilds.Sum(g => g.Channels.Count) - _textChannels;
};
this.client.ChannelCreated += (c) =>
{
if (c is ITextChannel)
++_textChannels;
else if (c is IVoiceChannel)
++_voiceChannels;
return Task.CompletedTask;
};
this.client.ChannelDestroyed += (c) =>
@ -62,6 +56,8 @@ namespace NadekoBot.Services.Impl
--_textChannels;
else if (c is IVoiceChannel)
--_voiceChannels;
return Task.CompletedTask;
};
this.client.JoinedGuild += (g) =>
@ -70,6 +66,8 @@ namespace NadekoBot.Services.Impl
var vc = g.Channels.Count - tc;
_textChannels += tc;
_voiceChannels += vc;
return Task.CompletedTask;
};
this.client.LeftGuild += (g) =>
@ -78,6 +76,8 @@ namespace NadekoBot.Services.Impl
var vc = g.Channels.Count - tc;
_textChannels -= tc;
_voiceChannels -= vc;
return Task.CompletedTask;
};
this.carbonitexTimer = new Timer(async (state) =>
@ -90,7 +90,7 @@ namespace NadekoBot.Services.Impl
{
using (var content = new FormUrlEncodedContent(
new Dictionary<string, string> {
{ "servercount", this.client.GetGuildsCount().ToString() },
{ "servercount", this.client.GetGuildCount().ToString() },
{ "key", NadekoBot.Credentials.CarbonKey }}))
{
content.Headers.Clear();
@ -103,16 +103,24 @@ namespace NadekoBot.Services.Impl
catch { }
}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
}
public void Initialize()
{
var guilds = this.client.GetGuilds();
_textChannels = guilds.Sum(g => g.Channels.Where(cx => cx is ITextChannel).Count());
_voiceChannels = guilds.Sum(g => g.Channels.Count) - _textChannels;
}
public Task<string> Print()
{
var curUser = client.CurrentUser();
var curUser = client.CurrentUser;
return Task.FromResult($@"
Author: [{Author}] | Library: [{Library}]
Bot Version: [{BotVersion}]
Bot ID: {curUser.Id}
Owner ID(s): {string.Join(", ", NadekoBot.Credentials.OwnerIds)}
Uptime: {GetUptimeString()}
Servers: {client.GetGuildsCount()} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
Servers: {client.GetGuildCount()} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
Commands Ran this session: {CommandsRan}
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
}

View File

@ -60,7 +60,8 @@ namespace NadekoBot
client.MessageReceived += arg1 =>
{
if (arg1.Author == null || arg1.Author.IsBot)
return Task.CompletedTask; MessageReceived(arg1);
return Task.CompletedTask;
MessageReceived(arg1);
return Task.CompletedTask;
};
client.UserLeft += arg1 => { UserLeft(arg1); return Task.CompletedTask; };
@ -107,7 +108,7 @@ namespace NadekoBot
public DiscordSocketClient MainClient =>
Clients[0];
public SocketSelfUser CurrentUser() =>
public SocketSelfUser CurrentUser =>
Clients[0].CurrentUser;
public IEnumerable<SocketGuild> GetGuilds() =>
@ -178,26 +179,9 @@ namespace NadekoBot
public Task SetGame(string game) => Task.WhenAll(Clients.Select(ms => ms.SetGameAsync(game)));
public Task SetStream(string name, string url) => Task.WhenAll(Clients.Select(ms => ms.SetGameAsync(name, url, StreamType.NotStreaming)));
public Task SetStream(string name, string url) => Task.WhenAll(Clients.Select(ms => ms.SetGameAsync(name, url, StreamType.Twitch)));
public Task SetStatus(SettableUserStatus status) => Task.WhenAll(Clients.Select(ms => ms.SetStatusAsync(SettableUserStatusToUserStatus(status))));
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
{
switch (sus)
{
case SettableUserStatus.Online:
return UserStatus.Online;
case SettableUserStatus.Invisible:
return UserStatus.Invisible;
case SettableUserStatus.Idle:
return UserStatus.AFK;
case SettableUserStatus.Dnd:
return UserStatus.DoNotDisturb;
}
return UserStatus.Online;
}
//public Task SetStatus(SettableUserStatus status) => Task.WhenAll(Clients.Select(ms => ms.SetStatusAsync(SettableUserStatusToUserStatus(status))));
}
public enum SettableUserStatus

View File

@ -24,10 +24,13 @@ namespace NadekoBot.Extensions
/// <summary>
/// danny kamisama
/// </summary>
public static async Task SendPaginatedConfirmAsync(this IMessageChannel channel, int currentPage, Func<int, EmbedBuilder> pageFunc, int? lastPage = null)
public static async Task SendPaginatedConfirmAsync(this IMessageChannel channel, int currentPage, Func<int, EmbedBuilder> pageFunc, int? lastPage = null, bool addPaginatedFooter = true)
{
lastPage += 1;
var embed = pageFunc(currentPage).AddPaginatedFooter(currentPage, lastPage);
var embed = pageFunc(currentPage);
if(addPaginatedFooter)
embed.AddPaginatedFooter(currentPage, lastPage);
var msg = await channel.EmbedAsync(embed) as IUserMessage;
@ -47,12 +50,20 @@ namespace NadekoBot.Extensions
{
if (currentPage == 1)
return;
await msg.ModifyAsync(x => x.Embed = pageFunc(--currentPage).AddPaginatedFooter(currentPage, lastPage).Build()).ConfigureAwait(false);
var toSend = pageFunc(--currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
await msg.ModifyAsync(x => x.Embed = toSend.Build()).ConfigureAwait(false);
}
else if (r.Emoji.Name == arrow_right)
{
if (lastPage == null || lastPage > currentPage)
await msg.ModifyAsync(x => x.Embed = pageFunc(++currentPage).AddPaginatedFooter(currentPage, lastPage).Build()).ConfigureAwait(false);
{
var toSend = pageFunc(++currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
await msg.ModifyAsync(x => x.Embed = toSend.Build()).ConfigureAwait(false);
}
}
}
catch (Exception ex) { Console.WriteLine(ex); }
@ -192,7 +203,7 @@ namespace NadekoBot.Extensions
await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(fileStream, fileName, caption, isTTS).ConfigureAwait(false);
public static bool IsAuthor(this IUserMessage msg) =>
NadekoBot.Client.CurrentUser().Id == msg.Author.Id;
NadekoBot.Client.CurrentUser.Id == msg.Author.Id;
public static IEnumerable<IUser> Members(this IRole role) =>
role.Guild.GetUsersAsync().GetAwaiter().GetResult().Where(u => u.RoleIds.Contains(role.Id)) ?? Enumerable.Empty<IUser>();