Added .clubadmin
, .autoboobs
and .autobutts
, cleaned up SongBuffer.
This commit is contained in:
parent
16fd835d4b
commit
4841418cff
1951
src/NadekoBot/Migrations/20170915034808_club-admins.Designer.cs
generated
Normal file
1951
src/NadekoBot/Migrations/20170915034808_club-admins.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
src/NadekoBot/Migrations/20170915034808_club-admins.cs
Normal file
25
src/NadekoBot/Migrations/20170915034808_club-admins.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class clubadmins : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsClubAdmin",
|
||||||
|
table: "DiscordUser",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsClubAdmin",
|
||||||
|
table: "DiscordUser");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -462,9 +462,11 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Discriminator");
|
b.Property<string>("Discriminator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClubAdmin");
|
||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
b.Property<DateTime>("LastLevelUp")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 906, DateTimeKind.Local));
|
.HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 660, DateTimeKind.Local));
|
||||||
|
|
||||||
b.Property<DateTime>("LastXpGain");
|
b.Property<DateTime>("LastXpGain");
|
||||||
|
|
||||||
@ -1364,7 +1366,7 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
b.Property<DateTime>("LastLevelUp")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 910, DateTimeKind.Local));
|
.HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 665, DateTimeKind.Local));
|
||||||
|
|
||||||
b.Property<int>("NotifyOnLevelUp");
|
b.Property<int>("NotifyOnLevelUp");
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music.Common
|
namespace NadekoBot.Modules.Music.Common
|
||||||
{
|
{
|
||||||
@ -18,27 +17,16 @@ namespace NadekoBot.Modules.Music.Common
|
|||||||
|
|
||||||
public string SongUri { get; private set; }
|
public string SongUri { get; private set; }
|
||||||
|
|
||||||
//private volatile bool restart = false;
|
|
||||||
|
|
||||||
public SongBuffer(string songUri, string skipTo, bool isLocal)
|
public SongBuffer(string songUri, string skipTo, bool isLocal)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
//_log.Warn(songUri);
|
|
||||||
this.SongUri = songUri;
|
this.SongUri = songUri;
|
||||||
this._isLocal = isLocal;
|
this._isLocal = isLocal;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.p = StartFFmpegProcess(SongUri, 0);
|
this.p = StartFFmpegProcess(SongUri, 0);
|
||||||
var t = Task.Run(() =>
|
|
||||||
{
|
|
||||||
this.p.BeginErrorReadLine();
|
|
||||||
this.p.ErrorDataReceived += P_ErrorDataReceived;
|
|
||||||
this.p.WaitForExit();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._outStream = this.p.StandardOutput.BaseStream;
|
this._outStream = this.p.StandardOutput.BaseStream;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (System.ComponentModel.Win32Exception)
|
catch (System.ComponentModel.Win32Exception)
|
||||||
{
|
{
|
||||||
@ -68,113 +56,14 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
Arguments = args,
|
Arguments = args,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(e.Data))
|
|
||||||
return;
|
|
||||||
_log.Error(">>> " + e.Data);
|
|
||||||
if (e.Data?.Contains("Error in the pull function") == true)
|
|
||||||
{
|
|
||||||
_log.Error("Ignore this.");
|
|
||||||
//restart = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly object locker = new object();
|
private readonly object locker = new object();
|
||||||
private readonly bool _isLocal;
|
private readonly bool _isLocal;
|
||||||
|
|
||||||
public Task<bool> StartBuffering(CancellationToken cancelToken)
|
|
||||||
{
|
|
||||||
var toReturn = new TaskCompletionSource<bool>();
|
|
||||||
var _ = Task.Run(() =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
////int maxLoopsPerSec = 25;
|
|
||||||
//var sw = Stopwatch.StartNew();
|
|
||||||
////var delay = 1000 / maxLoopsPerSec;
|
|
||||||
//int currentLoops = 0;
|
|
||||||
//int _bytesSent = 0;
|
|
||||||
//try
|
|
||||||
//{
|
|
||||||
// //do
|
|
||||||
// //{
|
|
||||||
// // if (restart)
|
|
||||||
// // {
|
|
||||||
// // var cur = _bytesSent / 3840 / (1000 / 20.0f);
|
|
||||||
// // _log.Info("Restarting");
|
|
||||||
// // try { this.p.StandardOutput.Dispose(); } catch { }
|
|
||||||
// // try { this.p.Dispose(); } catch { }
|
|
||||||
// // this.p = StartFFmpegProcess(SongUri, cur);
|
|
||||||
// // }
|
|
||||||
// // restart = false;
|
|
||||||
// ++currentLoops;
|
|
||||||
// byte[] buffer = new byte[readSize];
|
|
||||||
// int bytesRead = 1;
|
|
||||||
// while (!cancelToken.IsCancellationRequested && !this.p.HasExited)
|
|
||||||
// {
|
|
||||||
// bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, readSize, cancelToken).ConfigureAwait(false);
|
|
||||||
// _bytesSent += bytesRead;
|
|
||||||
// if (bytesRead == 0)
|
|
||||||
// break;
|
|
||||||
// bool written;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// lock (locker)
|
|
||||||
// written = _outStream.Write(buffer, 0, bytesRead);
|
|
||||||
// if (!written)
|
|
||||||
// await Task.Delay(2000, cancelToken);
|
|
||||||
// }
|
|
||||||
// while (!written && !cancelToken.IsCancellationRequested);
|
|
||||||
// lock (locker)
|
|
||||||
// if (_outStream.Length > 200_000 || bytesRead == 0)
|
|
||||||
// if (toReturn.TrySetResult(true))
|
|
||||||
// _log.Info("Prebuffering finished in {0}", sw.Elapsed.TotalSeconds.ToString("F2"));
|
|
||||||
|
|
||||||
// //_log.Info(_outStream.Length);
|
|
||||||
// await Task.Delay(10);
|
|
||||||
// }
|
|
||||||
// //if (cancelToken.IsCancellationRequested)
|
|
||||||
// // _log.Info("Song canceled");
|
|
||||||
// //else if (p.HasExited)
|
|
||||||
// // _log.Info("Song buffered completely (FFmpeg exited)");
|
|
||||||
// //else if (bytesRead == 0)
|
|
||||||
// // _log.Info("Nothing read");
|
|
||||||
// //}
|
|
||||||
// //while (restart && !cancelToken.IsCancellationRequested);
|
|
||||||
//return Task.CompletedTask;
|
|
||||||
toReturn.TrySetResult(true);
|
|
||||||
}
|
|
||||||
catch (System.ComponentModel.Win32Exception)
|
|
||||||
{
|
|
||||||
_log.Error(@"You have not properly installed or configured FFMPEG.
|
|
||||||
Please install and configure FFMPEG to play music.
|
|
||||||
Check the guides for your platform on how to setup ffmpeg correctly:
|
|
||||||
Windows Guide: https://goo.gl/OjKk8F
|
|
||||||
Linux Guide: https://goo.gl/ShjCUo");
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) { }
|
|
||||||
catch (InvalidOperationException) { } // when ffmpeg is disposed
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Info(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (toReturn.TrySetResult(false))
|
|
||||||
_log.Info("Prebuffering failed");
|
|
||||||
}
|
|
||||||
}, cancelToken);
|
|
||||||
|
|
||||||
return toReturn.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Read(byte[] b, int offset, int toRead)
|
public int Read(byte[] b, int offset, int toRead)
|
||||||
{
|
{
|
||||||
lock (locker)
|
lock (locker)
|
||||||
@ -204,214 +93,3 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//namespace NadekoBot.Services.Music
|
|
||||||
//{
|
|
||||||
// /// <summary>
|
|
||||||
// /// Create a buffer for a song file. It will create multiples files to ensure, that radio don't fill up disk space.
|
|
||||||
// /// It also help for large music by deleting files that are already seen.
|
|
||||||
// /// </summary>
|
|
||||||
// class SongBuffer : Stream
|
|
||||||
// {
|
|
||||||
// public SongBuffer(MusicPlayer musicPlayer, string basename, SongInfo songInfo, int skipTo, int maxFileSize)
|
|
||||||
// {
|
|
||||||
// MusicPlayer = musicPlayer;
|
|
||||||
// Basename = basename;
|
|
||||||
// SongInfo = songInfo;
|
|
||||||
// SkipTo = skipTo;
|
|
||||||
// MaxFileSize = maxFileSize;
|
|
||||||
// CurrentFileStream = new FileStream(this.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
|
|
||||||
// _log = LogManager.GetCurrentClassLogger();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// MusicPlayer MusicPlayer { get; }
|
|
||||||
|
|
||||||
// private string Basename { get; }
|
|
||||||
|
|
||||||
// private SongInfo SongInfo { get; }
|
|
||||||
|
|
||||||
// private int SkipTo { get; }
|
|
||||||
|
|
||||||
// private int MaxFileSize { get; } = 2.MiB();
|
|
||||||
|
|
||||||
// private long FileNumber = -1;
|
|
||||||
|
|
||||||
// private long NextFileToRead = 0;
|
|
||||||
|
|
||||||
// public bool BufferingCompleted { get; private set; } = false;
|
|
||||||
|
|
||||||
// private ulong CurrentBufferSize = 0;
|
|
||||||
|
|
||||||
// private FileStream CurrentFileStream;
|
|
||||||
// private Logger _log;
|
|
||||||
|
|
||||||
// public Task BufferSong(CancellationToken cancelToken) =>
|
|
||||||
// Task.Run(async () =>
|
|
||||||
// {
|
|
||||||
// Process p = null;
|
|
||||||
// FileStream outStream = null;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// p = Process.Start(new ProcessStartInfo
|
|
||||||
// {
|
|
||||||
// FileName = "ffmpeg",
|
|
||||||
// Arguments = $"-ss {SkipTo} -i {SongInfo.Uri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel quiet",
|
|
||||||
// UseShellExecute = false,
|
|
||||||
// RedirectStandardOutput = true,
|
|
||||||
// RedirectStandardError = false,
|
|
||||||
// CreateNoWindow = true,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// byte[] buffer = new byte[81920];
|
|
||||||
// int currentFileSize = 0;
|
|
||||||
// ulong prebufferSize = 100ul.MiB();
|
|
||||||
|
|
||||||
// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
|
||||||
// while (!p.HasExited) //Also fix low bandwidth
|
|
||||||
// {
|
|
||||||
// int bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false);
|
|
||||||
// if (currentFileSize >= MaxFileSize)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// outStream.Dispose();
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
|
||||||
// currentFileSize = bytesRead;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// currentFileSize += bytesRead;
|
|
||||||
// }
|
|
||||||
// CurrentBufferSize += Convert.ToUInt64(bytesRead);
|
|
||||||
// await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false);
|
|
||||||
// while (CurrentBufferSize > prebufferSize)
|
|
||||||
// await Task.Delay(100, cancelToken);
|
|
||||||
// }
|
|
||||||
// BufferingCompleted = true;
|
|
||||||
// }
|
|
||||||
// catch (System.ComponentModel.Win32Exception)
|
|
||||||
// {
|
|
||||||
// var oldclr = Console.ForegroundColor;
|
|
||||||
// Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
// Console.WriteLine(@"You have not properly installed or configured FFMPEG.
|
|
||||||
//Please install and configure FFMPEG to play music.
|
|
||||||
//Check the guides for your platform on how to setup ffmpeg correctly:
|
|
||||||
// Windows Guide: https://goo.gl/OjKk8F
|
|
||||||
// Linux Guide: https://goo.gl/ShjCUo");
|
|
||||||
// Console.ForegroundColor = oldclr;
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"Buffering stopped: {ex.Message}");
|
|
||||||
// }
|
|
||||||
// finally
|
|
||||||
// {
|
|
||||||
// if (outStream != null)
|
|
||||||
// outStream.Dispose();
|
|
||||||
// if (p != null)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// p.Kill();
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// p.Dispose();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// Return the next file to read, and delete the old one
|
|
||||||
// /// </summary>
|
|
||||||
// /// <returns>Name of the file to read</returns>
|
|
||||||
// private string GetNextFile()
|
|
||||||
// {
|
|
||||||
// string filename = Basename + "-" + NextFileToRead;
|
|
||||||
|
|
||||||
// if (NextFileToRead != 0)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// CurrentBufferSize -= Convert.ToUInt64(new FileInfo(Basename + "-" + (NextFileToRead - 1)).Length);
|
|
||||||
// File.Delete(Basename + "-" + (NextFileToRead - 1));
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// }
|
|
||||||
// NextFileToRead++;
|
|
||||||
// return filename;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private bool IsNextFileReady()
|
|
||||||
// {
|
|
||||||
// return NextFileToRead <= FileNumber;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void CleanFiles()
|
|
||||||
// {
|
|
||||||
// for (long i = NextFileToRead - 1; i <= FileNumber; i++)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// File.Delete(Basename + "-" + i);
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Stream part
|
|
||||||
|
|
||||||
// public override bool CanRead => true;
|
|
||||||
|
|
||||||
// public override bool CanSeek => false;
|
|
||||||
|
|
||||||
// public override bool CanWrite => false;
|
|
||||||
|
|
||||||
// public override long Length => (long)CurrentBufferSize;
|
|
||||||
|
|
||||||
// public override long Position { get; set; } = 0;
|
|
||||||
|
|
||||||
// public override void Flush() { }
|
|
||||||
|
|
||||||
// public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
// {
|
|
||||||
// int read = CurrentFileStream.Read(buffer, offset, count);
|
|
||||||
// if (read < count)
|
|
||||||
// {
|
|
||||||
// if (!BufferingCompleted || IsNextFileReady())
|
|
||||||
// {
|
|
||||||
// CurrentFileStream.Dispose();
|
|
||||||
// CurrentFileStream = new FileStream(GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
|
|
||||||
// read += CurrentFileStream.Read(buffer, read + offset, count - read);
|
|
||||||
// }
|
|
||||||
// if (read < count)
|
|
||||||
// Array.Clear(buffer, read, count - read);
|
|
||||||
// }
|
|
||||||
// return read;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void SetLength(long value)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public new void Dispose()
|
|
||||||
// {
|
|
||||||
// CurrentFileStream.Dispose();
|
|
||||||
// MusicPlayer.SongCancelSource.Cancel();
|
|
||||||
// CleanFiles();
|
|
||||||
// base.Dispose();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -16,9 +16,13 @@ using NadekoBot.Modules.NSFW.Exceptions;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.NSFW
|
namespace NadekoBot.Modules.NSFW
|
||||||
{
|
{
|
||||||
|
// thanks to halitalf for adding autoboob and autobutt features :D
|
||||||
public class NSFW : NadekoTopLevelModule<SearchesService>
|
public class NSFW : NadekoTopLevelModule<SearchesService>
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<ulong, Timer> _autoHentaiTimers = new ConcurrentDictionary<ulong, Timer>();
|
private static readonly ConcurrentDictionary<ulong, Timer> _autoHentaiTimers = new ConcurrentDictionary<ulong, Timer>();
|
||||||
|
private static readonly ConcurrentDictionary<ulong, Timer> _autoBoobTimers = new ConcurrentDictionary<ulong, Timer>();
|
||||||
|
private static readonly ConcurrentDictionary<ulong, Timer> _autoButtTimers = new ConcurrentDictionary<ulong, Timer>();
|
||||||
|
|
||||||
private static readonly ConcurrentHashSet<ulong> _hentaiBombBlacklist = new ConcurrentHashSet<ulong>();
|
private static readonly ConcurrentHashSet<ulong> _hentaiBombBlacklist = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
|
private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
|
||||||
@ -49,10 +53,34 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
.WithDescription($"[{GetText("tag")}: {tag}]({img})"))
|
.WithDescription($"[{GetText("tag")}: {tag}]({img})"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
private async Task InternalBoobs(IMessageChannel Channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JToken obj;
|
||||||
|
obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.oboobs.ru/boobs/{new NadekoRandom().Next(0, 10330)}").ConfigureAwait(false))[0];
|
||||||
|
await Channel.SendMessageAsync($"http://media.oboobs.ru/{obj["preview"]}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InternalButts(IMessageChannel Channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JToken obj;
|
||||||
|
obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.obutts.ru/butts/{new NadekoRandom().Next(0, 4335)}").ConfigureAwait(false))[0];
|
||||||
|
await Channel.SendMessageAsync($"http://media.obutts.ru/{obj["preview"]}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
public Task Hentai([Remainder] string tag = null) =>
|
|
||||||
InternalHentai(Context.Channel, tag, false);
|
|
||||||
#if !GLOBAL_NADEKO
|
#if !GLOBAL_NADEKO
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
@ -65,7 +93,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
if (!_autoHentaiTimers.TryRemove(Context.Channel.Id, out t)) return;
|
if (!_autoHentaiTimers.TryRemove(Context.Channel.Id, out t)) return;
|
||||||
|
|
||||||
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
||||||
await ReplyConfirmLocalized("autohentai_stopped").ConfigureAwait(false);
|
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +127,90 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
interval,
|
interval,
|
||||||
string.Join(", ", tagsArr)).ConfigureAwait(false);
|
string.Join(", ", tagsArr)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
|
public async Task AutoBoobs(int interval = 0)
|
||||||
|
{
|
||||||
|
Timer t;
|
||||||
|
|
||||||
|
if (interval == 0)
|
||||||
|
{
|
||||||
|
if (!_autoBoobTimers.TryRemove(Context.Channel.Id, out t)) return;
|
||||||
|
|
||||||
|
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
||||||
|
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interval < 20)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t = new Timer(async (state) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await InternalBoobs(Context.Channel).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}, null, interval * 1000, interval * 1000);
|
||||||
|
|
||||||
|
_autoBoobTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) =>
|
||||||
|
{
|
||||||
|
old.Change(Timeout.Infinite, Timeout.Infinite);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized("started", interval).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
|
public async Task AutoButts(int interval = 0)
|
||||||
|
{
|
||||||
|
Timer t;
|
||||||
|
|
||||||
|
if (interval == 0)
|
||||||
|
{
|
||||||
|
if (!_autoButtTimers.TryRemove(Context.Channel.Id, out t)) return;
|
||||||
|
|
||||||
|
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
||||||
|
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interval < 20)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t = new Timer(async (state) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await InternalButts(Context.Channel).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}, null, interval * 1000, interval * 1000);
|
||||||
|
|
||||||
|
_autoButtTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) =>
|
||||||
|
{
|
||||||
|
old.Change(Timeout.Infinite, Timeout.Infinite);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized("started", interval).ConfigureAwait(false);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public Task Hentai([Remainder] string tag = null) =>
|
||||||
|
InternalHentai(Context.Channel, tag, false);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task HentaiBomb([Remainder] string tag = null)
|
public async Task HentaiBomb([Remainder] string tag = null)
|
||||||
{
|
{
|
||||||
@ -199,7 +309,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
tag = tag.Trim().ToLowerInvariant();
|
tag = tag.Trim().ToLowerInvariant();
|
||||||
var added = _service.ToggleBlacklistedTag(Context.Guild.Id, tag);
|
var added = _service.ToggleBlacklistedTag(Context.Guild.Id, tag);
|
||||||
|
|
||||||
if(added)
|
if (added)
|
||||||
await ReplyConfirmLocalized("blacklisted_tag_add", tag).ConfigureAwait(false);
|
await ReplyConfirmLocalized("blacklisted_tag_add", tag).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await ReplyConfirmLocalized("blacklisted_tag_remove", tag).ConfigureAwait(false);
|
await ReplyConfirmLocalized("blacklisted_tag_remove", tag).ConfigureAwait(false);
|
||||||
|
@ -26,6 +26,27 @@ namespace NadekoBot.Modules.Xp
|
|||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task ClubAdmin([Remainder]IUser toAdmin)
|
||||||
|
{
|
||||||
|
bool admin;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
admin = _service.ToggleAdmin(Context.User, toAdmin);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("club_admin_error").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(admin)
|
||||||
|
await ReplyConfirmLocalized("club_admin_add", Format.Bold(toAdmin.ToString())).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await ReplyConfirmLocalized("club_admin_remove", Format.Bold(toAdmin.ToString())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task ClubCreate([Remainder]string clubName)
|
public async Task ClubCreate([Remainder]string clubName)
|
||||||
{
|
{
|
||||||
@ -97,7 +118,14 @@ namespace NadekoBot.Modules.Xp
|
|||||||
.AddField("Level Req.", club.MinimumLevelReq.ToString(), true)
|
.AddField("Level Req.", club.MinimumLevelReq.ToString(), true)
|
||||||
.AddField("Members", string.Join("\n", club.Users
|
.AddField("Members", string.Join("\n", club.Users
|
||||||
.Skip(page * 10)
|
.Skip(page * 10)
|
||||||
.Take(10)), false);
|
.Take(10)
|
||||||
|
.OrderByDescending(x => x.IsClubAdmin)
|
||||||
|
.Select(x =>
|
||||||
|
{
|
||||||
|
if (x.IsClubAdmin)
|
||||||
|
return x.ToString() + "⭐";
|
||||||
|
return x.ToString();
|
||||||
|
})), false);
|
||||||
|
|
||||||
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
||||||
return embed.WithThumbnailUrl(club.ImageUrl);
|
return embed.WithThumbnailUrl(club.ImageUrl);
|
||||||
@ -112,7 +140,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
var club = _service.GetBansAndApplications(Context.User.Id);
|
var club = _service.GetClubWithBansAndApplications(Context.User.Id);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return ReplyErrorLocalized("club_not_exists");
|
return ReplyErrorLocalized("club_not_exists");
|
||||||
|
|
||||||
@ -143,11 +171,11 @@ namespace NadekoBot.Modules.Xp
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
var club = _service.GetBansAndApplications(Context.User.Id);
|
var club = _service.GetClubWithBansAndApplications(Context.User.Id);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return ReplyErrorLocalized("club_not_exists");
|
return ReplyErrorLocalized("club_not_exists");
|
||||||
|
|
||||||
var bans = club
|
var apps = club
|
||||||
.Applicants
|
.Applicants
|
||||||
.Select(x => x.User)
|
.Select(x => x.User)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -155,7 +183,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
return Context.Channel.SendPaginatedConfirmAsync(_client, page,
|
return Context.Channel.SendPaginatedConfirmAsync(_client, page,
|
||||||
curPage =>
|
curPage =>
|
||||||
{
|
{
|
||||||
var toShow = string.Join("\n", bans
|
var toShow = string.Join("\n", apps
|
||||||
.Skip(page * 10)
|
.Skip(page * 10)
|
||||||
.Take(10)
|
.Take(10)
|
||||||
.Select(x => x.ToString()));
|
.Select(x => x.ToString()));
|
||||||
@ -164,7 +192,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
.WithTitle(GetText("club_apps_for", club.ToString()))
|
.WithTitle(GetText("club_apps_for", club.ToString()))
|
||||||
.WithDescription(toShow);
|
.WithDescription(toShow);
|
||||||
|
|
||||||
}, bans.Length / 10);
|
}, apps.Length / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -27,10 +27,11 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
var du = uow.DiscordUsers.GetOrCreate(user);
|
var du = uow.DiscordUsers.GetOrCreate(user);
|
||||||
uow._context.SaveChanges();
|
uow._context.SaveChanges();
|
||||||
var xp = new LevelStats(uow.Xp.GetTotalUserXp(user.Id));
|
var xp = new LevelStats(du.TotalXp);
|
||||||
|
|
||||||
if (xp.Level >= 5 && du.Club == null)
|
if (xp.Level >= 5 && du.Club == null)
|
||||||
{
|
{
|
||||||
|
du.IsClubAdmin = true;
|
||||||
du.Club = new ClubInfo()
|
du.Club = new ClubInfo()
|
||||||
{
|
{
|
||||||
Name = clubName,
|
Name = clubName,
|
||||||
@ -52,6 +53,27 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ToggleAdmin(IUser owner, IUser toAdmin)
|
||||||
|
{
|
||||||
|
bool newState;
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var club = uow.Clubs.GetByOwner(owner.Id);
|
||||||
|
var adminUser = uow.DiscordUsers.GetOrCreate(toAdmin);
|
||||||
|
|
||||||
|
if (club.OwnerId == adminUser.Id)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (club == null || club.Owner.UserId != owner.Id ||
|
||||||
|
!club.Users.Contains(adminUser))
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
public ClubInfo GetClubByMember(IUser user)
|
public ClubInfo GetClubByMember(IUser user)
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
@ -107,7 +129,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
uow._context.SaveChanges();
|
uow._context.SaveChanges();
|
||||||
|
|
||||||
if (du.Club != null
|
if (du.Club != null
|
||||||
|| new LevelStats(uow.Xp.GetTotalUserXp(user.Id)).Level < club.MinimumLevelReq
|
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|
||||||
|| club.Bans.Any(x => x.UserId == du.Id)
|
|| club.Bans.Any(x => x.UserId == du.Id)
|
||||||
|| club.Applicants.Any(x => x.UserId == du.Id))
|
|| club.Applicants.Any(x => x.UserId == du.Id))
|
||||||
{
|
{
|
||||||
@ -134,11 +156,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
discordUser = null;
|
discordUser = null;
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var club = uow.Clubs.GetByOwner(clubOwnerUserId,
|
var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId);
|
||||||
set => set.Include(x => x.Applicants)
|
|
||||||
.ThenInclude(x => x.Club)
|
|
||||||
.Include(x => x.Applicants)
|
|
||||||
.ThenInclude(x => x.User));
|
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -147,6 +165,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
applicant.User.Club = club;
|
applicant.User.Club = club;
|
||||||
|
applicant.User.IsClubAdmin = false;
|
||||||
club.Applicants.Remove(applicant);
|
club.Applicants.Remove(applicant);
|
||||||
|
|
||||||
//remove that user's all other applications
|
//remove that user's all other applications
|
||||||
@ -159,15 +178,11 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClubInfo GetBansAndApplications(ulong ownerUserId)
|
public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
return uow.Clubs.GetByOwner(ownerUserId,
|
return uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
x => x.Include(y => y.Bans)
|
|
||||||
.ThenInclude(y => y.User)
|
|
||||||
.Include(y => y.Applicants)
|
|
||||||
.ThenInclude(y => y.User));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,6 +195,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
du.Club = null;
|
du.Club = null;
|
||||||
|
du.IsClubAdmin = false;
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -221,9 +237,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwner(ownerUserId,
|
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
set => set.Include(x => x.Applicants)
|
|
||||||
.ThenInclude(x => x.User));
|
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -256,9 +270,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwner(ownerUserId,
|
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
set => set.Include(x => x.Bans)
|
|
||||||
.ThenInclude(x => x.User));
|
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -277,7 +289,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwner(ownerUserId);
|
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
|
|
||||||
du.LastXpGain = DateTime.UtcNow;
|
du.LastXpGain = DateTime.UtcNow;
|
||||||
|
|
||||||
var globalXp = uow.Xp.GetTotalUserXp(item.Key.User.Id);
|
var globalXp = du.TotalXp;
|
||||||
var oldGlobalLevelData = new LevelStats(globalXp);
|
var oldGlobalLevelData = new LevelStats(globalXp);
|
||||||
var newGlobalLevelData = new LevelStats(globalXp + xp);
|
var newGlobalLevelData = new LevelStats(globalXp + xp);
|
||||||
|
|
||||||
@ -403,17 +403,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return _rewardedUsers.Add(userId);
|
return _rewardedUsers.Add(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LevelStats GetGlobalUserStats(ulong userId)
|
|
||||||
{
|
|
||||||
int totalXp;
|
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
|
||||||
totalXp = uow.Xp.GetTotalUserXp(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LevelStats(totalXp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FullUserStats GetUserStats(IGuildUser user)
|
public FullUserStats GetUserStats(IGuildUser user)
|
||||||
{
|
{
|
||||||
DiscordUser du;
|
DiscordUser du;
|
||||||
|
@ -3780,4 +3780,31 @@
|
|||||||
<data name="nsfwclearcache_desc" xml:space="preserve">
|
<data name="nsfwclearcache_desc" xml:space="preserve">
|
||||||
<value>Clears nsfw cache.</value>
|
<value>Clears nsfw cache.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="clubadmin_cmd" xml:space="preserve">
|
||||||
|
<value>clubadmin</value>
|
||||||
|
</data>
|
||||||
|
<data name="clubadmin_usage" xml:space="preserve">
|
||||||
|
<value>`{0}clubadmin`</value>
|
||||||
|
</data>
|
||||||
|
<data name="clubadmin_desc" xml:space="preserve">
|
||||||
|
<value>Assigns (or unassigns) staff role to the member of the club. Admins can ban, kick and accept applications.</value>
|
||||||
|
</data>
|
||||||
|
<data name="autoboobs_cmd" xml:space="preserve">
|
||||||
|
<value>autoboobs</value>
|
||||||
|
</data>
|
||||||
|
<data name="autoboobs_desc" xml:space="preserve">
|
||||||
|
<value>Posts a boobs every X seconds. 20 seconds minimum. Provide no arguments to disable.</value>
|
||||||
|
</data>
|
||||||
|
<data name="autoboobs_usage" xml:space="preserve">
|
||||||
|
<value>`{0}autoboobs 30` or `{0}autoboobs`</value>
|
||||||
|
</data>
|
||||||
|
<data name="autobutts_cmd" xml:space="preserve">
|
||||||
|
<value>autobutts</value>
|
||||||
|
</data>
|
||||||
|
<data name="autobutts_desc" xml:space="preserve">
|
||||||
|
<value>Posts a butts every X seconds. 20 seconds minimum. Provide no arguments to disable.</value>
|
||||||
|
</data>
|
||||||
|
<data name="autobutts_usage" xml:space="preserve">
|
||||||
|
<value>`{0}autobutts 30` or `{0}autobutts`</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
@ -10,6 +10,7 @@ namespace NadekoBot.Services.Database.Models
|
|||||||
public string AvatarId { get; set; }
|
public string AvatarId { get; set; }
|
||||||
|
|
||||||
public ClubInfo Club { get; set; }
|
public ClubInfo Club { get; set; }
|
||||||
|
public bool IsClubAdmin { get; set; }
|
||||||
|
|
||||||
public int TotalXp { get; set; }
|
public int TotalXp { get; set; }
|
||||||
public DateTime LastLevelUp { get; set; } = DateTime.UtcNow;
|
public DateTime LastLevelUp { get; set; } = DateTime.UtcNow;
|
||||||
|
@ -329,7 +329,7 @@ namespace NadekoBot.Services.Database
|
|||||||
#region ClubManytoMany
|
#region ClubManytoMany
|
||||||
|
|
||||||
modelBuilder.Entity<ClubApplicants>()
|
modelBuilder.Entity<ClubApplicants>()
|
||||||
.HasKey(t => new { t.ClubId, t.UserId });
|
.HasKey(t => new { t.ClubId, t.UserId });
|
||||||
|
|
||||||
modelBuilder.Entity<ClubApplicants>()
|
modelBuilder.Entity<ClubApplicants>()
|
||||||
.HasOne(pt => pt.User)
|
.HasOne(pt => pt.User)
|
||||||
@ -340,7 +340,7 @@ namespace NadekoBot.Services.Database
|
|||||||
.WithMany(x => x.Applicants);
|
.WithMany(x => x.Applicants);
|
||||||
|
|
||||||
modelBuilder.Entity<ClubBans>()
|
modelBuilder.Entity<ClubBans>()
|
||||||
.HasKey(t => new { t.ClubId, t.UserId });
|
.HasKey(t => new { t.ClubId, t.UserId });
|
||||||
|
|
||||||
modelBuilder.Entity<ClubBans>()
|
modelBuilder.Entity<ClubBans>()
|
||||||
.HasOne(pt => pt.User)
|
.HasOne(pt => pt.User)
|
||||||
|
@ -10,6 +10,7 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
int GetNextDiscrim(string clubName);
|
int GetNextDiscrim(string clubName);
|
||||||
ClubInfo GetByName(string v, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByName(string v, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
ClubInfo GetByOwner(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByOwner(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
|
ClubInfo GetByOwnerOrAdmin(ulong userId);
|
||||||
ClubInfo GetByMember(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByMember(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
ClubInfo[] GetClubLeaderboardPage(int page);
|
ClubInfo[] GetClubLeaderboardPage(int page);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
public interface IXpRepository : IRepository<UserXpStats>
|
public interface IXpRepository : IRepository<UserXpStats>
|
||||||
{
|
{
|
||||||
UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
|
UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
|
||||||
int GetTotalUserXp(ulong userId);
|
|
||||||
int GetUserGuildRanking(ulong userId, ulong guildId);
|
int GetUserGuildRanking(ulong userId, ulong guildId);
|
||||||
UserXpStats[] GetUsersFor(ulong guildId, int page);
|
UserXpStats[] GetUsersFor(ulong guildId, int page);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,30 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return func(_set).FirstOrDefault(x => x.Owner.UserId == userId);
|
return func(_set).FirstOrDefault(x => x.Owner.UserId == userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClubInfo GetByOwnerOrAdmin(ulong userId)
|
||||||
|
{
|
||||||
|
return _set
|
||||||
|
.Include(x => x.Bans)
|
||||||
|
.ThenInclude(x => x.User)
|
||||||
|
.Include(x => x.Applicants)
|
||||||
|
.ThenInclude(x => x.User)
|
||||||
|
.Include(x => x.Owner)
|
||||||
|
.FirstOrDefault(x => x.Owner.UserId == userId) ??
|
||||||
|
_context.Set<DiscordUser>()
|
||||||
|
.Include(x => x.Club)
|
||||||
|
.ThenInclude(x => x.Users)
|
||||||
|
.Include(x => x.Club)
|
||||||
|
.ThenInclude(x => x.Bans)
|
||||||
|
.ThenInclude(x => x.User)
|
||||||
|
.Include(x => x.Club)
|
||||||
|
.ThenInclude(x => x.Applicants)
|
||||||
|
.ThenInclude(x => x.User)
|
||||||
|
.Include(x => x.Club)
|
||||||
|
.ThenInclude(x => x.Owner)
|
||||||
|
.FirstOrDefault(x => x.UserId == userId && x.IsClubAdmin)
|
||||||
|
?.Club;
|
||||||
|
}
|
||||||
|
|
||||||
public ClubInfo GetByName(string name, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null)
|
public ClubInfo GetByName(string name, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null)
|
||||||
{
|
{
|
||||||
if (func == null)
|
if (func == null)
|
||||||
|
@ -29,11 +29,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return usr;
|
return usr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTotalUserXp(ulong userId)
|
|
||||||
{
|
|
||||||
return _set.Where(x => x.UserId == userId).Sum(x => x.Xp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserXpStats[] GetUsersFor(ulong guildId, int page)
|
public UserXpStats[] GetUsersFor(ulong guildId, int page)
|
||||||
{
|
{
|
||||||
return _set.Where(x => x.GuildId == guildId)
|
return _set.Where(x => x.GuildId == guildId)
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"customreactions_stats_not_found": "No stats for that trigger found, no action taken.",
|
"customreactions_stats_not_found": "No stats for that trigger found, no action taken.",
|
||||||
"customreactions_trigger": "Trigger",
|
"customreactions_trigger": "Trigger",
|
||||||
"customreactions_redacted_too_long": "Redecated because it's too long.",
|
"customreactions_redacted_too_long": "Redecated because it's too long.",
|
||||||
"nsfw_autohentai_stopped": "Autohentai stopped.",
|
|
||||||
"nsfw_not_found": "No results found.",
|
"nsfw_not_found": "No results found.",
|
||||||
"nsfw_blacklisted_tag_list": "List of blacklisted tags:",
|
"nsfw_blacklisted_tag_list": "List of blacklisted tags:",
|
||||||
"nsfw_blacklisted_tag": "One or more tags you've used are blacklisted",
|
"nsfw_blacklisted_tag": "One or more tags you've used are blacklisted",
|
||||||
@ -868,5 +867,10 @@
|
|||||||
"xp_club_icon_set": "New club icon set.",
|
"xp_club_icon_set": "New club icon set.",
|
||||||
"xp_club_bans_for": "Bans for {0} club",
|
"xp_club_bans_for": "Bans for {0} club",
|
||||||
"xp_club_apps_for": "Applicants for {0} club",
|
"xp_club_apps_for": "Applicants for {0} club",
|
||||||
"xp_club_leaderboard": "Club leaderboard - page {0}"
|
"xp_club_leaderboard": "Club leaderboard - page {0}",
|
||||||
|
"xp_club_admin_add": "{0} is now a club admin.",
|
||||||
|
"xp_club_admin_remove": "{0} is no longer club admin.",
|
||||||
|
"xp_club_admin_error": "Error. You are either not the owner of the club, or that user is not in your club.",
|
||||||
|
"nsfw_started": "Started. Reposting every {0}s.",
|
||||||
|
"nsfw_stopped": "Stopped reposting."
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user