Merge remote-tracking branch 'refs/remotes/Kwoth/dev' into dev

This commit is contained in:
samvaio 2017-01-31 22:49:33 +05:30
commit 604f8b260d
17 changed files with 216 additions and 58 deletions

@ -1 +1 @@
Subproject commit 4506fc5a54fe31d826649dc413467c52a3cd7896
Subproject commit 80384323790471d254c7db5c237a49dc62624378

View File

@ -9,6 +9,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.WebSocket;
using NadekoBot.Services.Database;
namespace NadekoBot.Modules.Gambling
{
@ -19,15 +21,27 @@ namespace NadekoBot.Modules.Gambling
{
public enum CurrencyEvent
{
FlowerReaction
FlowerReaction,
SneakyGameStatus
}
//flower reaction event
public static readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
private static readonly char[] _sneakyGameStatusChars = Enumerable.Range(48, 10)
.Concat(Enumerable.Range(65, 26))
.Concat(Enumerable.Range(97, 26))
.Select(x => (char)x)
.ToArray();
public static readonly ConcurrentHashSet<ulong> _sneakyGameAwardedUsers = new ConcurrentHashSet<ulong>();
private static string _secretCode = String.Empty;
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task StartEvent(CurrencyEvent e)
public async Task StartEvent(CurrencyEvent e, int arg = -1)
{
var channel = (ITextChannel)Context.Channel;
try
@ -38,6 +52,9 @@ namespace NadekoBot.Modules.Gambling
case CurrencyEvent.FlowerReaction:
await FlowerReactionEvent(Context).ConfigureAwait(false);
break;
case CurrencyEvent.SneakyGameStatus:
await SneakyGameStatusEvent(Context, arg).ConfigureAwait(false);
break;
default:
break;
}
@ -45,6 +62,63 @@ namespace NadekoBot.Modules.Gambling
catch { }
}
public static async Task SneakyGameStatusEvent(CommandContext Context, int? arg)
{
int num;
if (arg == null || arg < 5)
num = 60;
else
num = arg.Value;
if (_secretCode != String.Empty)
return;
var rng = new NadekoRandom();
for (int i = 0; i < 5; i++)
{
_secretCode += _sneakyGameStatusChars[rng.Next(0, _sneakyGameStatusChars.Length)];
}
await NadekoBot.Client.SetGameAsync($"type {_secretCode} for " + NadekoBot.BotConfig.CurrencyPluralName)
.ConfigureAwait(false);
try
{
await Context.Channel.SendConfirmAsync($"SneakyGameStatus event started",
$"Users must type a secret code to get 100 currency.\n" +
$"Lasts {num} seconds. Don't tell anyone. Shhh.")
.ConfigureAwait(false);
}
catch { }
NadekoBot.Client.MessageReceived += SneakyGameMessageReceivedEventHandler;
await Task.Delay(num * 1000);
NadekoBot.Client.MessageReceived -= SneakyGameMessageReceivedEventHandler;
_sneakyGameAwardedUsers.Clear();
_secretCode = String.Empty;
await NadekoBot.Client.SetGameAsync($"SneakyGame event ended.")
.ConfigureAwait(false);
}
private static Task SneakyGameMessageReceivedEventHandler(SocketMessage arg)
{
if (arg.Content == _secretCode &&
_sneakyGameAwardedUsers.Add(arg.Author.Id))
{
var _ = Task.Run(async () =>
{
await CurrencyHandler.AddCurrencyAsync(arg.Author, "Sneaky Game Event", 100, false)
.ConfigureAwait(false);
try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); }
catch { }
});
}
return Task.Delay(0);
}
public static async Task FlowerReactionEvent(CommandContext Context)
{

View File

@ -506,7 +506,7 @@ namespace NadekoBot.Modules.Gambling
title = AffinityTitles.Sloot;
else if (count < 17)
title = AffinityTitles.Depraved;
else if (count < 20)
else
title = AffinityTitles.Harlot;
return new WaifuProfileTitle(count, title.ToString().Replace('_', ' '));

View File

@ -74,7 +74,7 @@ namespace NadekoBot.Modules.Gambling
return;
}
await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {Context.User.Username} ({Context.User.Id}).", amount, true).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} successfully sent {amount} {(amount == 1 ? CurrencyName : CurrencyPluralName)} to {receiver}!").ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} gifted {amount}{CurrencySign} to {Format.Bold(receiver.ToString())}!").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -94,7 +94,7 @@ namespace NadekoBot.Modules.Gambling
await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} awarded {amount} {(amount == 1 ? CurrencyName : CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} awarded {amount}{CurrencySign} to <@{usrId}>!").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Games
[NadekoModule("Games", ">")]
public partial class Games : DiscordModule
{
private static IEnumerable<string> _8BallResponses { get; } = NadekoBot.BotConfig.EightBallResponses.Select(ebr => ebr.Text);
private static string[] _8BallResponses { get; } = NadekoBot.BotConfig.EightBallResponses.Select(ebr => ebr.Text).ToArray();
[NadekoCommand, Usage, Description, Aliases]
@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Games
await Context.Channel.EmbedAsync(new EmbedBuilder().WithColor(NadekoBot.OkColor)
.AddField(efb => efb.WithName("❓ Question").WithValue(question).WithIsInline(false))
.AddField(efb => efb.WithName("🎱 8Ball").WithValue(_8BallResponses.Shuffle().FirstOrDefault()).WithIsInline(false)));
.AddField(efb => efb.WithName("🎱 8Ball").WithValue(_8BallResponses[new NadekoRandom().Next(0, _8BallResponses.Length)]).WithIsInline(false)));
}
[NadekoCommand, Usage, Description, Aliases]

View File

@ -71,6 +71,7 @@ namespace NadekoBot.Modules.Music.Classes
public event Action<bool> OnPauseChanged = delegate { };
public IVoiceChannel PlaybackVoiceChannel { get; private set; }
public ITextChannel OutputTextChannel { get; set; }
private bool Destroyed { get; set; } = false;
public bool RepeatSong { get; private set; } = false;
@ -84,10 +85,12 @@ namespace NadekoBot.Modules.Music.Classes
public event Action<Song, int> SongRemoved = delegate { };
public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume)
public MusicPlayer(IVoiceChannel startingVoiceChannel, ITextChannel outputChannel, float? defaultVolume)
{
if (startingVoiceChannel == null)
throw new ArgumentNullException(nameof(startingVoiceChannel));
OutputTextChannel = outputChannel;
Volume = defaultVolume ?? 1.0f;
PlaybackVoiceChannel = startingVoiceChannel;

View File

@ -797,6 +797,23 @@ namespace NadekoBot.Modules.Music
await Context.Channel.SendConfirmAsync("✅ Autoplay enabled.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task SetMusicChannel()
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
{
await Context.Channel.SendErrorAsync("Music must be playing before you set an ouput channel.").ConfigureAwait(false);
return;
}
musicPlayer.OutputTextChannel = (ITextChannel)Context.Channel;
await Context.Channel.SendConfirmAsync("I will now output playing, finished, paused and removed songs in this channel.").ConfigureAwait(false);
}
public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
{
if (voiceCh == null || voiceCh.Guild != textCh.Guild)
@ -815,7 +832,7 @@ namespace NadekoBot.Modules.Music
{
vol = uow.GuildConfigs.For(textCh.Guild.Id, set => set).DefaultMusicVolume;
}
var mp = new MusicPlayer(voiceCh, vol);
var mp = new MusicPlayer(voiceCh, textCh, vol);
IUserMessage playingMessage = null;
IUserMessage lastFinishedMessage = null;
mp.OnCompleted += async (s, song) =>
@ -825,7 +842,7 @@ namespace NadekoBot.Modules.Music
if (lastFinishedMessage != null)
lastFinishedMessage.DeleteAfter(0);
lastFinishedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
lastFinishedMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Finished Song").WithMusicIcon())
.WithDescription(song.PrettyName)
.WithFooter(ef => ef.WithText(song.PrettyInfo)))
@ -833,7 +850,14 @@ namespace NadekoBot.Modules.Music
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);
var relatedVideos = (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList();
if(relatedVideos.Count > 0)
await QueueSong(await queuer.Guild.GetCurrentUserAsync(),
textCh,
voiceCh,
relatedVideos[new NadekoRandom().Next(0, relatedVideos.Count)],
silent,
musicType).ConfigureAwait(false);
}
}
catch { }
@ -850,7 +874,7 @@ namespace NadekoBot.Modules.Music
if (playingMessage != null)
playingMessage.DeleteAfter(0);
playingMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
playingMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Playing Song").WithMusicIcon())
.WithDescription(song.PrettyName)
.WithFooter(ef => ef.WithText(song.PrettyInfo)))
@ -864,9 +888,9 @@ namespace NadekoBot.Modules.Music
{
IUserMessage msg;
if (paused)
msg = await textCh.SendConfirmAsync("🎵 Music playback **paused**.").ConfigureAwait(false);
msg = await mp.OutputTextChannel.SendConfirmAsync("🎵 Music playback **paused**.").ConfigureAwait(false);
else
msg = await textCh.SendConfirmAsync("🎵 Music playback **resumed**.").ConfigureAwait(false);
msg = await mp.OutputTextChannel.SendConfirmAsync("🎵 Music playback **resumed**.").ConfigureAwait(false);
if (msg != null)
msg.DeleteAfter(10);
@ -874,7 +898,6 @@ namespace NadekoBot.Modules.Music
catch { }
};
mp.SongRemoved += async (song, index) =>
{
try
@ -885,7 +908,7 @@ namespace NadekoBot.Modules.Music
.WithFooter(ef => ef.WithText(song.PrettyInfo))
.WithErrorColor();
await textCh.EmbedAsync(embed).ConfigureAwait(false);
await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false);
}
catch { }

View File

@ -320,10 +320,10 @@ namespace NadekoBot.Modules.Searches
.ConfigureAwait(false);
try
{
var items = JArray.Parse(response).Shuffle().ToList();
if (items == null)
var items = JArray.Parse(response).ToArray();
if (items == null || items.Length == 0)
throw new KeyNotFoundException("Cannot find a card by that name");
var item = items[0];
var item = items[new NadekoRandom().Next(0, items.Length)];
var storeUrl = await NadekoBot.Google.ShortenUrl(item["store_url"].ToString());
var cost = item["cost"].ToString();
var desc = item["text"].ToString();
@ -378,6 +378,8 @@ namespace NadekoBot.Modules.Searches
if (items == null)
throw new KeyNotFoundException("Cannot find a card by that name");
foreach (var item in items.Where(item => item.HasValues && item["img"] != null).Take(4))
{
await Task.Run(async () =>
{
using (var sr = await http.GetStreamAsync(item["img"].ToString()))
{
@ -386,6 +388,7 @@ namespace NadekoBot.Modules.Searches
imgStream.Position = 0;
images.Add(new ImageSharp.Image(imgStream));
}
}).ConfigureAwait(false);
}
string msg = null;
if (items.Count > 4)
@ -393,7 +396,7 @@ namespace NadekoBot.Modules.Searches
msg = "⚠ Found over 4 images. Showing random 4.";
}
var ms = new MemoryStream();
images.AsEnumerable().Merge().SaveAsPng(ms);
await Task.Run(() => images.AsEnumerable().Merge().SaveAsPng(ms));
ms.Position = 0;
await Context.Channel.SendFileAsync(ms, arg + ".png", msg).ConfigureAwait(false);
}

View File

@ -97,8 +97,10 @@ namespace NadekoBot.Modules.Utility
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count - 1})** - {string.Join("\n", user.GetRoles().Where(r => r.Id != r.Guild.EveryoneRole.Id).Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
.WithThumbnailUrl(user.RealAvatarUrl())
.WithColor(NadekoBot.OkColor);
if (user.AvatarId != null)
embed.WithThumbnailUrl(user.RealAvatarUrl());
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
}
}

View File

@ -93,24 +93,31 @@ namespace NadekoBot.Modules.Utility
var isAdmin = ((IGuildUser)Context.Message.Author).GuildPermissions.Administrator;
keyword = keyword.ToUpperInvariant();
var sucess = false;
string response;
using (var uow = DbHandler.UnitOfWork())
{
var qs = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword);
var qs = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword)?.Where(elem => isAdmin || elem.AuthorId == Context.Message.Author.Id).ToArray();
if (qs == null || !qs.Any())
{
await Context.Channel.SendErrorAsync("No quotes found.").ConfigureAwait(false);
return;
sucess = false;
response = "No quotes found which you can remove.";
}
var q = qs.Shuffle().FirstOrDefault(elem => isAdmin || elem.AuthorId == Context.Message.Author.Id);
else
{
var q = qs[new NadekoRandom().Next(0, qs.Length)];
uow.Quotes.Remove(q);
await uow.CompleteAsync().ConfigureAwait(false);
sucess = true;
response = "🗑 **Deleted a random quote.**";
}
}
if(sucess)
await Context.Channel.SendConfirmAsync(response);
else
await Context.Channel.SendErrorAsync(response);
}
[NadekoCommand, Usage, Description, Aliases]
@ -126,7 +133,7 @@ namespace NadekoBot.Modules.Utility
using (var uow = DbHandler.UnitOfWork())
{
var quotes = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword);
//todo kwoth please don't be complete retard
uow.Quotes.RemoveRange(quotes.ToArray());//wtf?!
await uow.CompleteAsync();

View File

@ -15,6 +15,8 @@ using System.Threading;
using ImageSharp;
using System.Collections.Generic;
using Newtonsoft.Json;
using Discord.WebSocket;
using NadekoBot.Services;
namespace NadekoBot.Modules.Utility
{
@ -113,17 +115,25 @@ namespace NadekoBot.Modules.Utility
game = game.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(game))
return;
var arr = (await (Context.Channel as IGuildChannel).Guild.GetUsersAsync())
var socketGuild = Context.Guild as SocketGuild;
if (socketGuild == null) {
_log.Warn("Can't cast guild to socket guild.");
return;
}
var rng = new NadekoRandom();
var arr = await Task.Run(() => socketGuild.Users
.Where(u => u.Game?.Name?.ToUpperInvariant() == game)
.Select(u => u.Username)
.Shuffle()
.OrderBy(x => rng.Next())
.Take(60)
.ToList();
.ToArray()).ConfigureAwait(false);
int i = 0;
if (!arr.Any())
if (arr.Length == 0)
await Context.Channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
else {
else
{
await Context.Channel.SendConfirmAsync("```css\n" + string.Join("\n", arr.GroupBy(item => (i++) / 2)
.Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```")
.ConfigureAwait(false);

View File

@ -6782,6 +6782,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to setmusicchannel smch.
/// </summary>
public static string setmusicchannel_cmd {
get {
return ResourceManager.GetString("setmusicchannel_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sets the current channel as the default music output channel. This will output playing, finished, paused and removed songs to that channel instead of the channel where the first song was queued in..
/// </summary>
public static string setmusicchannel_desc {
get {
return ResourceManager.GetString("setmusicchannel_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}smch`.
/// </summary>
public static string setmusicchannel_usage {
get {
return ResourceManager.GetString("setmusicchannel_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to setmuterole.
/// </summary>
@ -8340,7 +8367,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to `{0}voice+text`.
/// Looks up a localized string similar to `{0}v+t`.
/// </summary>
public static string voiceplustext_usage {
get {

View File

@ -340,7 +340,7 @@
<value>Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless.</value>
</data>
<data name="voiceplustext_usage" xml:space="preserve">
<value>`{0}voice+text`</value>
<value>`{0}v+t`</value>
</data>
<data name="scsc_cmd" xml:space="preserve">
<value>scsc</value>
@ -3033,4 +3033,13 @@
<data name="mal_usage" xml:space="preserve">
<value>`{0}mal straysocks`</value>
</data>
<data name="setmusicchannel_cmd" xml:space="preserve">
<value>setmusicchannel smch</value>
</data>
<data name="setmusicchannel_desc" xml:space="preserve">
<value>Sets the current channel as the default music output channel. This will output playing, finished, paused and removed songs to that channel instead of the channel where the first song was queued in.</value>
</data>
<data name="setmusicchannel_usage" xml:space="preserve">
<value>`{0}smch`</value>
</data>
</root>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.