Merge branch '1.9' of https://github.com/Kwoth/NadekoBot into 1.9
This commit is contained in:
commit
900622322f
@ -1,14 +1,54 @@
|
|||||||
using NadekoBot.Core.Services;
|
using Discord;
|
||||||
|
using NadekoBot.Core.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling.Services
|
namespace NadekoBot.Modules.Gambling.Services
|
||||||
{
|
{
|
||||||
public class WaifuService : INService
|
public class WaifuService : INService
|
||||||
{
|
{
|
||||||
|
private readonly DbService _db;
|
||||||
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, DateTime> DivorceCooldowns { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
public ConcurrentDictionary<ulong, DateTime> DivorceCooldowns { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
||||||
public ConcurrentDictionary<ulong, DateTime> AffinityCooldowns { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
public ConcurrentDictionary<ulong, DateTime> AffinityCooldowns { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
||||||
|
|
||||||
|
public WaifuService(DbService db, CurrencyService cs)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_cs = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> WaifuTransfer(IUser owner, ulong waifuId, IUser newOwner)
|
||||||
|
{
|
||||||
|
if (owner.Id == newOwner.Id || waifuId == newOwner.Id)
|
||||||
|
return false;
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var waifu = uow.Waifus.ByWaifuUserId(waifuId);
|
||||||
|
var ownerUser = uow.DiscordUsers.GetOrCreate(owner);
|
||||||
|
|
||||||
|
// owner has to be the owner of the waifu
|
||||||
|
if (waifu == null || waifu.ClaimerId != ownerUser.Id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!await _cs.RemoveAsync(owner.Id,
|
||||||
|
"Waifu Transfer",
|
||||||
|
waifu.Price / 10,
|
||||||
|
uow).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//new claimerId is the id of the new owner
|
||||||
|
var newOwnerUser = uow.DiscordUsers.GetOrCreate(newOwner);
|
||||||
|
waifu.ClaimerId = newOwnerUser.Id;
|
||||||
|
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
InsufficientAmount
|
InsufficientAmount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30);
|
||||||
|
private readonly IBotConfigProvider _bc;
|
||||||
|
private readonly CurrencyService _cs;
|
||||||
|
private readonly DbService _db;
|
||||||
|
|
||||||
public WaifuClaimCommands(IBotConfigProvider bc, CurrencyService cs, DbService db)
|
public WaifuClaimCommands(IBotConfigProvider bc, CurrencyService cs, DbService db)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -183,6 +188,23 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await Context.Channel.SendConfirmAsync(Context.User.Mention + msg).ConfigureAwait(false);
|
await Context.Channel.SendConfirmAsync(Context.User.Mention + msg).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task WaifuTransfer(IUser waifu, IUser newOwner)
|
||||||
|
{
|
||||||
|
if(!await _service.WaifuTransfer(Context.User, waifu.Id, newOwner)
|
||||||
|
.ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("waifu_transfer_fail").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized("waifu_transfer_success",
|
||||||
|
Format.Bold(waifu.ToString()),
|
||||||
|
Format.Bold(Context.User.ToString()),
|
||||||
|
Format.Bold(newOwner.ToString())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
public enum DivorceResult
|
public enum DivorceResult
|
||||||
{
|
{
|
||||||
Success,
|
Success,
|
||||||
@ -274,11 +296,6 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30);
|
|
||||||
private readonly IBotConfigProvider _bc;
|
|
||||||
private readonly CurrencyService _cs;
|
|
||||||
private readonly DbService _db;
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task WaifuClaimerAffinity([Remainder]IGuildUser u = null)
|
public async Task WaifuClaimerAffinity([Remainder]IGuildUser u = null)
|
||||||
@ -299,6 +316,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
if (w?.Affinity?.UserId == u?.Id)
|
if (w?.Affinity?.UserId == u?.Id)
|
||||||
{
|
{
|
||||||
|
//todo don't let people change affinity on different shards
|
||||||
}
|
}
|
||||||
else if (_service.AffinityCooldowns.AddOrUpdate(Context.User.Id,
|
else if (_service.AffinityCooldowns.AddOrUpdate(Context.User.Id,
|
||||||
now,
|
now,
|
||||||
|
@ -16,6 +16,32 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class AnimeSearchCommands : NadekoSubmodule<AnimeSearchService>
|
public class AnimeSearchCommands : NadekoSubmodule<AnimeSearchService>
|
||||||
{
|
{
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task Novel([Remainder] string query)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var novelData = await _service.GetNovelData(query).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (novelData == null)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalized("failed_finding_novel").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
|
||||||
|
.WithDescription(novelData.Description.Replace("<br>", Environment.NewLine))
|
||||||
|
.WithTitle(novelData.Title)
|
||||||
|
.WithUrl(novelData.Link)
|
||||||
|
.WithImageUrl(novelData.ImageUrl)
|
||||||
|
.AddField(efb => efb.WithName(GetText("authors")).WithValue(String.Join("\n", novelData.Authors)).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName(GetText("status")).WithValue(novelData.Status).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName(GetText("genres")).WithValue(string.Join(" ", novelData.Genres.Any() ? novelData.Genres : new[] { "none" })).WithIsInline(true))
|
||||||
|
.WithFooter(efb => efb.WithText(GetText("score") + " " + novelData.Score));
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[Priority(0)]
|
[Priority(0)]
|
||||||
public async Task Mal([Remainder] string name)
|
public async Task Mal([Remainder] string name)
|
||||||
|
20
NadekoBot.Core/Modules/Searches/Common/NovelData.cs
Normal file
20
NadekoBot.Core/Modules/Searches/Common/NovelData.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Common
|
||||||
|
{
|
||||||
|
public class NovelResult
|
||||||
|
{
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Link { get; set; }
|
||||||
|
public string ImageUrl { get; set; }
|
||||||
|
public string[] Authors { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
|
public string[] Genres { get; set; }
|
||||||
|
public string Score { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,9 @@ using System;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Modules.Searches.Common;
|
using NadekoBot.Modules.Searches.Common;
|
||||||
|
using AngleSharp;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches.Services
|
namespace NadekoBot.Modules.Searches.Services
|
||||||
{
|
{
|
||||||
@ -46,6 +49,81 @@ namespace NadekoBot.Modules.Searches.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<NovelResult> GetNovelData(string query)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
throw new ArgumentNullException(nameof(query));
|
||||||
|
|
||||||
|
query = query.Replace(" ", "-");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
var link = "http://www.novelupdates.com/series/" + Uri.EscapeDataString(query.Replace("/", " "));
|
||||||
|
link = link.ToLowerInvariant();
|
||||||
|
var (ok, data) = await _cache.TryGetNovelDataAsync(link).ConfigureAwait(false);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
var document = await BrowsingContext.New(config).OpenAsync(link);
|
||||||
|
|
||||||
|
var imageElem = document.QuerySelector("div.seriesimg > img");
|
||||||
|
var imageUrl = ((IHtmlImageElement)imageElem).Source;
|
||||||
|
|
||||||
|
var descElem = document.QuerySelector("div#editdescription > p");
|
||||||
|
var desc = descElem.InnerHtml;
|
||||||
|
|
||||||
|
var genres = document.QuerySelector("div#seriesgenre").Children
|
||||||
|
.Select(x => x as IHtmlAnchorElement)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var authors = document
|
||||||
|
.QuerySelector("div#showauthors")
|
||||||
|
.Children
|
||||||
|
.Select(x => x as IHtmlAnchorElement)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var score = ((IHtmlSpanElement)document
|
||||||
|
.QuerySelector("h5.seriesother > span.uvotes"))
|
||||||
|
.InnerHtml;
|
||||||
|
|
||||||
|
var status = document
|
||||||
|
.QuerySelector("div#editstatus")
|
||||||
|
.InnerHtml;
|
||||||
|
var title = document
|
||||||
|
.QuerySelector("div.w-blog-content > div.seriestitlenu")
|
||||||
|
.InnerHtml;
|
||||||
|
|
||||||
|
var obj = new NovelResult()
|
||||||
|
{
|
||||||
|
Description = desc,
|
||||||
|
Authors = authors,
|
||||||
|
Genres = genres,
|
||||||
|
ImageUrl = imageUrl,
|
||||||
|
Link = link,
|
||||||
|
Score = score,
|
||||||
|
Status = status,
|
||||||
|
Title = title,
|
||||||
|
};
|
||||||
|
|
||||||
|
await _cache.SetNovelDataAsync(link,
|
||||||
|
JsonConvert.SerializeObject(obj)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject<NovelResult>(data);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Error(ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<MangaResult> GetMangaData(string query)
|
public async Task<MangaResult> GetMangaData(string query)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(query))
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
@ -9,8 +9,10 @@ namespace NadekoBot.Core.Services
|
|||||||
ConnectionMultiplexer Redis { get; }
|
ConnectionMultiplexer Redis { get; }
|
||||||
Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key);
|
Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key);
|
||||||
Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key);
|
Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key);
|
||||||
|
Task<(bool Success, string Data)> TryGetNovelDataAsync(string key);
|
||||||
Task SetImageDataAsync(string key, byte[] data);
|
Task SetImageDataAsync(string key, byte[] data);
|
||||||
Task SetAnimeDataAsync(string link, string data);
|
Task SetAnimeDataAsync(string link, string data);
|
||||||
|
Task SetNovelDataAsync(string link, string data);
|
||||||
TimeSpan? AddTimelyClaim(ulong id, int period);
|
TimeSpan? AddTimelyClaim(ulong id, int period);
|
||||||
void RemoveAllTimelyClaims();
|
void RemoveAllTimelyClaims();
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,17 @@ namespace NadekoBot.Core.Services.Impl
|
|||||||
return _db.StringSetAsync("anime_" + key, data);
|
return _db.StringSetAsync("anime_" + key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(bool Success, string Data)> TryGetNovelDataAsync(string key)
|
||||||
|
{
|
||||||
|
string x = await _db.StringGetAsync("novel_" + key);
|
||||||
|
return (x != null, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SetNovelDataAsync(string key, string data)
|
||||||
|
{
|
||||||
|
return _db.StringSetAsync("novel_" + key, data);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly object timelyLock = new object();
|
private readonly object timelyLock = new object();
|
||||||
public TimeSpan? AddTimelyClaim(ulong id, int period)
|
public TimeSpan? AddTimelyClaim(ulong id, int period)
|
||||||
{
|
{
|
||||||
|
@ -311,6 +311,8 @@
|
|||||||
"gambling_waifu_not_yours": "That waifu is not yours.",
|
"gambling_waifu_not_yours": "That waifu is not yours.",
|
||||||
"gambling_waifu_not_yourself": "You can't claim yourself.",
|
"gambling_waifu_not_yourself": "You can't claim yourself.",
|
||||||
"gambling_waifu_recent_divorce": "You divorced recently. You must wait {0} hours and {1} minutes to divorce again.",
|
"gambling_waifu_recent_divorce": "You divorced recently. You must wait {0} hours and {1} minutes to divorce again.",
|
||||||
|
"gambling_waifu_transfer_fail": "You're either not the owner of that waifu, or you can't afford it. Alternatively your input is invalid.",
|
||||||
|
"gambling_waifu_transfer_success": "Claim on {0} has been transfered from {1} to {2}",
|
||||||
"gambling_nobody": "Nobody",
|
"gambling_nobody": "Nobody",
|
||||||
"gambling_waifu_divorced_notlike": "You have divorced a waifu who doesn't like you. You received {0} back.",
|
"gambling_waifu_divorced_notlike": "You have divorced a waifu who doesn't like you. You received {0} back.",
|
||||||
"games_8ball": "8ball",
|
"games_8ball": "8ball",
|
||||||
@ -498,6 +500,7 @@
|
|||||||
"searches_failed_finding_anime": "Failed finding that animu.",
|
"searches_failed_finding_anime": "Failed finding that animu.",
|
||||||
"searches_failed_finding_manga": "Failed finding that mango.",
|
"searches_failed_finding_manga": "Failed finding that mango.",
|
||||||
"searches_genres": "Genres",
|
"searches_genres": "Genres",
|
||||||
|
"searches_authors": "Authors",
|
||||||
"searches_hashtag_error": "Failed finding a definition for that tag.",
|
"searches_hashtag_error": "Failed finding a definition for that tag.",
|
||||||
"searches_height_weight": "Height/Weight",
|
"searches_height_weight": "Height/Weight",
|
||||||
"searches_height_weight_val": "{0}m/{1}kg",
|
"searches_height_weight_val": "{0}m/{1}kg",
|
||||||
|
@ -2314,6 +2314,13 @@
|
|||||||
"{0}claim 50 @Himesama"
|
"{0}claim 50 @Himesama"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"waifutransfer": {
|
||||||
|
"cmd": "waifutransfer",
|
||||||
|
"desc": "Transfer the ownership of one of your waifus to another user. You must pay 10% of your waifu's value.",
|
||||||
|
"usage": [
|
||||||
|
"{0}waifutransfer @ExWaifu @NewOwner"
|
||||||
|
]
|
||||||
|
},
|
||||||
"waifugift": {
|
"waifugift": {
|
||||||
"Cmd": "waifugift gift gifts",
|
"Cmd": "waifugift gift gifts",
|
||||||
"Desc": "Gift an item to someone. This will increase their waifu value by 50% of the gifted item's value if they don't have affinity set towards you, or 100% if they do. Provide no arguments to see a list of items that you can gift.",
|
"Desc": "Gift an item to someone. This will increase their waifu value by 50% of the gifted item's value if they don't have affinity set towards you, or 100% if they do. Provide no arguments to see a list of items that you can gift.",
|
||||||
@ -3076,5 +3083,12 @@
|
|||||||
"usage": [
|
"usage": [
|
||||||
"{0}timelyreset"
|
"{0}timelyreset"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"novel": {
|
||||||
|
"cmd": "novel",
|
||||||
|
"desc": "Searches for a novel on `http://novelupdates.com/`. You have to provide an exact name.",
|
||||||
|
"usage": [
|
||||||
|
"{0}novel the nine cauldrons"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user