Discord Bot Intergration
Discord bot added to server some general info commands a example event, also ability to register account with discord bot and link discord user to that account and give them role for registering.
This commit is contained in:
parent
583a2bbd9b
commit
8957f284f5
@ -75,6 +75,35 @@ namespace DiIiS_NA.LoginServer.AccountsSystem
|
||||
Logger.Warn("Created account {0}", email);
|
||||
return GetAccountByEmail(email);
|
||||
}
|
||||
public static bool BindDiscordAccount(string email, ulong discordId, string discordTag)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DBSessions.SessionQueryWhere<DBAccount>(dba => dba.DiscordId == discordId).Count() > 0)
|
||||
return false;
|
||||
|
||||
var account = GetAccountByEmail(email);
|
||||
account.DBAccount.DiscordTag = discordTag;
|
||||
account.DBAccount.DiscordId = discordId;
|
||||
DBSessions.SessionUpdate(account.DBAccount);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.DebugException(e, "BindDiscordAccount() exception: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static Account GetAccountByDiscordId(ulong discordId)
|
||||
{
|
||||
List<DBAccount> dbAcc = DBSessions.SessionQueryWhere<DBAccount>(dba => dba.DiscordId == discordId).ToList();
|
||||
if (dbAcc.Count() == 0)
|
||||
{
|
||||
Logger.Warn("GetAccountByDiscordId {0}: DBAccount is null!", discordId);
|
||||
return null;
|
||||
}
|
||||
return GetAccountByDBAccount(dbAcc.First());
|
||||
}
|
||||
|
||||
public static bool GenerateReferralCode(string email)
|
||||
{
|
||||
|
||||
@ -64,6 +64,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Castle.Core" Version="4.4.1" />
|
||||
<PackageReference Include="Discord.Net" Version="3.8.0" />
|
||||
<PackageReference Include="DotNetty.Buffers" Version="0.6.0" />
|
||||
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
|
||||
<PackageReference Include="DotNetty.Codecs.Http" Version="0.6.0" />
|
||||
@ -85,6 +86,7 @@
|
||||
<PackageReference Include="Skater.exe" Version="7.5.0" />
|
||||
<PackageReference Include="SoapCore" Version="0.9.9.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
|
||||
<PackageReference Include="System.ServiceModel.Web" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -95,7 +97,7 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="config.ini">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="database.Account.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
|
||||
284
src/DiIiS-NA/Core/Discord/Bot.cs
Normal file
284
src/DiIiS-NA/Core/Discord/Bot.cs
Normal file
@ -0,0 +1,284 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using DiIiS_NA.Core.Discord.Services;
|
||||
using DiIiS_NA.LoginServer.AccountsSystem;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
using DiIiS_NA.Core.Storage;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
|
||||
namespace DiIiS_NA.Core.Discord
|
||||
{
|
||||
public class Bot
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.CreateLogger();
|
||||
|
||||
public static void Init()
|
||||
=> new Bot().MainAsync().GetAwaiter().GetResult();
|
||||
|
||||
public DiscordSocketClient Client = null;
|
||||
private DiscordSocketConfig _config = new DiscordSocketConfig{MessageCacheSize = 100};
|
||||
|
||||
public async Task MainAsync()
|
||||
{
|
||||
var services = ConfigureServices();
|
||||
this.Client = services.GetService<DiscordSocketClient>();
|
||||
await services.GetService<CommandHandlingService>().InitializeAsync();
|
||||
|
||||
await this.Client.LoginAsync(TokenType.Bot, Config.Instance.Token);
|
||||
await this.Client.StartAsync();
|
||||
|
||||
this.Client.ReactionAdded += HandleReactionAsync;// ReactionAdded;
|
||||
|
||||
//await Task.Delay(-1);
|
||||
}
|
||||
|
||||
private IServiceProvider ConfigureServices()
|
||||
{
|
||||
return new ServiceCollection()
|
||||
// Base
|
||||
.AddSingleton(new DiscordSocketClient(_config))
|
||||
.AddSingleton<CommandService>()
|
||||
.AddSingleton<CommandHandlingService>()
|
||||
// Add additional services here...
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
private async Task HandleReactionAsync(Cacheable<IUserMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel, SocketReaction reaction)
|
||||
{
|
||||
if (this.Client.GetUser(reaction.UserId).IsBot) return;
|
||||
|
||||
// If the message was not in the cache, downloading it will result in getting a copy of it.
|
||||
var msg = await message.GetOrDownloadAsync();
|
||||
if (channel.Id == (ulong)DiIiS_NA.Core.Discord.Config.Instance.EventsChannelId)
|
||||
{
|
||||
var user = reaction.User.Value;
|
||||
var guild_user = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetUser(user.Id);
|
||||
|
||||
if (!guild_user.Roles.Select(r => r.Id).Contains((ulong)DiIiS_NA.Core.Discord.Config.Instance.BaseRoleId) && !guild_user.IsBot)
|
||||
{
|
||||
await msg.RemoveReactionAsync(reaction.Emote, reaction.User.Value);
|
||||
await user.SendMessageAsync("**Your #💎events entry has been removed because your Blizzless account isn't linked to Discord!**\nYou can do that if you send me:\n\n`!email my_d3r_email@something.com`\n\n**(Replace** `my_d3r_email@something.com` **with your D3 Reflection email)**");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task AddCollectorRole(ulong userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetUser(userId);
|
||||
await user.AddRoleAsync(this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetRole((ulong)DiIiS_NA.Core.Discord.Config.Instance.CollectorRoleId));
|
||||
await user.SendMessageAsync("Congratulations! You are now a **Collector**.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "AddCollectorRole() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task AddPremiumRole(ulong userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetUser(userId);
|
||||
await user.AddRoleAsync(this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetRole((ulong)DiIiS_NA.Core.Discord.Config.Instance.PremiumRoleId));
|
||||
await user.SendMessageAsync("Congratulations! You are now a **Premium** user.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "AddPremiumRole() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateBattleTag(ulong userId, string btag)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetUser(userId);
|
||||
await user.AddRoleAsync(this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetRole((ulong)DiIiS_NA.Core.Discord.Config.Instance.PremiumRoleId));
|
||||
await user.ModifyAsync(x => {x.Nickname = btag;});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "UpdateBattleTag() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ClearPremiumRoles(List<ulong> userIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
var guild = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId);
|
||||
var role = guild.GetRole((ulong)DiIiS_NA.Core.Discord.Config.Instance.PremiumRoleId);
|
||||
foreach (var userId in userIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = guild.GetUser(userId);
|
||||
await user.RemoveRoleAsync(role);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "ClearPremiumRoles() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ShowServerStats()
|
||||
{
|
||||
try
|
||||
{
|
||||
var guild = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId);
|
||||
var channelId = (ulong)DiIiS_NA.Core.Discord.Config.Instance.StatsChannelId;
|
||||
string opened = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "ServerOpened").First().Value > 0 ? "ENABLED" : "DISABLED";
|
||||
// int gs_count = Program.MooNetServer.MooNetBackend.GameServers.Count;
|
||||
// int ccu = DiIiS_NA.Core.MooNet.Online.PlayerManager.OnlinePlayers.Count;
|
||||
// int games = DiIiS_NA.Core.MooNet.Games.GameFactoryManager.GamesOnline;
|
||||
var messages = await guild.GetTextChannel(channelId).GetMessagesAsync(10).FlattenAsync();
|
||||
await guild.GetTextChannel(channelId).DeleteMessagesAsync(messages);
|
||||
// await guild.GetTextChannel(channelId).SendMessageAsync($"Login availability: **{opened}**\nGame servers available: {gs_count}\nPlayers online: {ccu}\nGames online: {games}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "ShowStats() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task StartGiveaway()
|
||||
{
|
||||
try
|
||||
{
|
||||
var guild = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId);
|
||||
var channelId = (ulong)DiIiS_NA.Core.Discord.Config.Instance.EventsChannelId;
|
||||
var param_message = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "DiscordGiveawayPostId");
|
||||
if (param_message.Count < 1)
|
||||
{
|
||||
var messages = await guild.GetTextChannel(channelId).GetMessagesAsync(10).FlattenAsync();
|
||||
await guild.GetTextChannel(channelId).DeleteMessagesAsync(messages);
|
||||
}
|
||||
else
|
||||
{
|
||||
await guild.GetTextChannel(channelId).DeleteMessageAsync(param_message.First().Value);
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder();
|
||||
eb.WithTitle("Reward: 7 days of Premium");
|
||||
eb.WithDescription("Click <:wolfRNG:607868292979490816> to join.\nEnds at 18:00 UTC");
|
||||
eb.WithFooter("You must bind your D3R account email to be able to join!");
|
||||
eb.WithColor(Color.Blue);
|
||||
var mes = await guild.GetTextChannel(channelId).SendMessageAsync("@here \n <:wolfRNG:607868292979490816> **GIVEAWAY ROULETTE!** <:wolfRNG:607868292979490816>", false, eb.Build());
|
||||
|
||||
//var giveaway_message = await guild.GetTextChannel(channelId).GetMessagesAsync(1).FlattenAsync();
|
||||
//foreach (var mes in giveaway_message)
|
||||
//{
|
||||
var param = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "DiscordGiveawayPostId");
|
||||
if (param.Count < 1)
|
||||
{
|
||||
var new_param = new DBGlobalParams{
|
||||
Name = "DiscordGiveawayPostId",
|
||||
Value = mes.Id
|
||||
};
|
||||
DBSessions.SessionSave(new_param);
|
||||
}
|
||||
else
|
||||
{
|
||||
var postId = param.First();
|
||||
postId.Value = mes.Id;
|
||||
DBSessions.SessionUpdate(postId);
|
||||
}
|
||||
await (mes as IUserMessage).AddReactionAsync(Emote.Parse("<:wolfRNG:607868292979490816>"));
|
||||
//}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "StartGiveaway() exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task FinishGiveaway()
|
||||
{
|
||||
try
|
||||
{
|
||||
var guild = this.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId);
|
||||
var channelId = (ulong)DiIiS_NA.Core.Discord.Config.Instance.EventsChannelId;
|
||||
bool haveWinner = true;
|
||||
string winnerName = "";
|
||||
var param = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "DiscordGiveawayPostId");
|
||||
if (param.Count < 1)
|
||||
{
|
||||
haveWinner = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (param.First().Value > 0)
|
||||
{
|
||||
var message = await guild.GetTextChannel(channelId).GetMessageAsync(param.First().Value);
|
||||
var reactedUsers = await (message as IUserMessage).GetReactionUsersAsync(Emote.Parse("<:wolfRNG:607868292979490816>"), 100).FlattenAsync();
|
||||
var contestants = reactedUsers.Where(u => !u.IsBot).ToList();
|
||||
if (contestants.Count() > 0)
|
||||
{
|
||||
var winner = reactedUsers.Where(u => !u.IsBot).ToList()[DiIiS_NA.Core.Helpers.Math.FastRandom.Instance.Next(0, reactedUsers.Count() - 1)];
|
||||
winnerName = guild.GetUser(winner.Id).Nickname;
|
||||
await winner.SendMessageAsync("Congratulations! You have won **7 days of D3 Reflection Premium**!.\nYour account has already had its Premium prolonged. Have a nice game!");
|
||||
var acc = AccountManager.GetAccountByDiscordId(winner.Id);
|
||||
if (acc != null) {
|
||||
//acc.UpdatePremiumTime(7);
|
||||
}
|
||||
}
|
||||
else
|
||||
haveWinner = false;
|
||||
}
|
||||
else
|
||||
haveWinner = false;
|
||||
}
|
||||
|
||||
if (param.Count < 1)
|
||||
{
|
||||
var messages = await guild.GetTextChannel(channelId).GetMessagesAsync(10).FlattenAsync();
|
||||
await guild.GetTextChannel(channelId).DeleteMessagesAsync(messages);
|
||||
}
|
||||
else
|
||||
{
|
||||
await guild.GetTextChannel(channelId).DeleteMessageAsync(param.First().Value);
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder();
|
||||
eb.WithTitle("Giveaway ended");
|
||||
eb.WithDescription(haveWinner ? string.Format("Winner: {0}", winnerName) : "We have no winner this time :(");
|
||||
eb.WithFooter("Free Premium giveaways - starts every Friday and Saturday!");
|
||||
eb.WithColor(Color.Red);
|
||||
var mes = await guild.GetTextChannel(channelId).SendMessageAsync("<:wolfRNG:607868292979490816> **GIVEAWAY ROULETTE!** <:wolfRNG:607868292979490816>", false, eb.Build());
|
||||
|
||||
var db_param = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "DiscordGiveawayPostId");
|
||||
if (db_param.Count < 1)
|
||||
{
|
||||
var new_param = new DBGlobalParams{
|
||||
Name = "DiscordGiveawayPostId",
|
||||
Value = mes.Id
|
||||
};
|
||||
DBSessions.SessionSave(new_param);
|
||||
}
|
||||
else
|
||||
{
|
||||
var postId = db_param.First();
|
||||
postId.Value = mes.Id;
|
||||
DBSessions.SessionUpdate(postId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WarnException(e, "FinishGiveaway() exception: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/DiIiS-NA/Core/Discord/Config.cs
Normal file
31
src/DiIiS-NA/Core/Discord/Config.cs
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2011 - 2012 DiIiS_NA project - http://www.DiIiS_NA.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace DiIiS_NA.Core.Discord
|
||||
{
|
||||
public sealed class Config : Core.Config.Config
|
||||
{
|
||||
public bool Enabled { get { return this.GetBoolean("Enabled", false); } set { this.Set("Enabled", value); } }
|
||||
public bool MonitorEnabled { get { return this.GetBoolean("MonitorEnabled", true); } set { this.Set("MonitorEnabled", value); } }
|
||||
public string Token { get { return this.GetString("Token", ""); } set { this.Set("Token", value); } }
|
||||
public long GuildId { get { return this.GetLong("GuildId", 0); } set { this.Set("GuildId", value); } }
|
||||
public long AnnounceChannelId { get { return this.GetLong("AnnounceChannelId", 0); } set { this.Set("AnnounceChannelId", value); } }
|
||||
public long StatsChannelId { get { return this.GetLong("StatsChannelId", 0); } set { this.Set("StatsChannelId", value); } }
|
||||
public long EventsChannelId { get { return this.GetLong("EventsChannelId", 0); } set { this.Set("EventsChannelId", value); } }
|
||||
public long BaseRoleId { get { return this.GetLong("BaseRoleId", 0); } set { this.Set("BaseRoleId", value); } }
|
||||
public long PremiumRoleId { get { return this.GetLong("PremiumRoleId", 0); } set { this.Set("PremiumRoleId", value); } }
|
||||
public long CollectorRoleId { get { return this.GetLong("CollectorRoleId", 0); } set { this.Set("CollectorRoleId", value); } }
|
||||
|
||||
private static readonly Config _instance = new Config();
|
||||
public static Config Instance { get { return _instance; } }
|
||||
private Config() : base("Discord") { }
|
||||
}
|
||||
}
|
||||
115
src/DiIiS-NA/Core/Discord/Modules/AuthModule.cs
Normal file
115
src/DiIiS-NA/Core/Discord/Modules/AuthModule.cs
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Mail;
|
||||
using DiIiS_NA.LoginServer.AccountsSystem;
|
||||
using DiIiS_NA.Core.Storage;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
namespace DiIiS_NA.Core.Discord.Modules
|
||||
{
|
||||
public class AuthModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("register")]
|
||||
public async Task Register([Remainder] string args)
|
||||
{
|
||||
string dtag = Context.User.Username + "#" + Context.User.Discriminator;
|
||||
string[] registerInfo = args.Split(null);
|
||||
|
||||
var email = registerInfo[0];
|
||||
var password = registerInfo[1];
|
||||
var battleTagName = registerInfo[2];
|
||||
var userLevel = Account.UserLevels.User;
|
||||
|
||||
if (!(Context.Channel is IDMChannel))
|
||||
{
|
||||
await Context.Guild.GetTextChannel(Context.Channel.Id).DeleteMessageAsync(Context.Message);
|
||||
await ReplyAsync($"<@{Context.User.Id}> that command could be used only via direct message!\nDon't show your e-mail to anyone, don't be a fool! <:200iq:538833204421984286>");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (registerInfo.Count() == 3)
|
||||
{
|
||||
if (!email.Contains('@'))
|
||||
{
|
||||
await ReplyAsync($"<@{Context.User.Id}> " + string.Format("'{0}' is not a valid email address.", email));
|
||||
return;
|
||||
}
|
||||
if (!IsValid(email))
|
||||
{
|
||||
await ReplyAsync("Your e-mail address is invalid!");
|
||||
return;
|
||||
}
|
||||
if (battleTagName.Contains('#'))
|
||||
{
|
||||
await ReplyAsync($"<@{Context.User.Id}> BattleTag must not contain '#' or HashCode.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (password.Length < 8 || password.Length > 16)
|
||||
{
|
||||
await ReplyAsync($"<@{Context.User.Id}> Password should be a minimum of 8 and a maximum of 16 characters.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (AccountManager.GetAccountByEmail(email) != null)
|
||||
{
|
||||
await ReplyAsync($"<@{Context.User.Id}> " + string.Format("An account already exists for email address {0}.", email));
|
||||
return;
|
||||
}
|
||||
|
||||
var account = AccountManager.CreateAccount(email, password, battleTagName, userLevel);
|
||||
var gameAccount = GameAccountManager.CreateGameAccount(account);
|
||||
|
||||
var guild_user = Context.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetUser(Context.User.Id);
|
||||
|
||||
if (guild_user == null)
|
||||
{
|
||||
await ReplyAsync("Your Discord account is not participated channel!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (AccountManager.BindDiscordAccount(email, Context.User.Id, dtag))
|
||||
{
|
||||
var accountcheck = AccountManager.GetAccountByEmail(email);
|
||||
string battle_tag = account.DBAccount.BattleTagName + "#" + account.DBAccount.HashCode;
|
||||
await ReplyAsync($"Account registered.\nYour Discord account has been successfully bound to {battle_tag}!");
|
||||
await guild_user.AddRoleAsync(Context.Client.GetGuild((ulong)DiIiS_NA.Core.Discord.Config.Instance.GuildId).GetRole((ulong)DiIiS_NA.Core.Discord.Config.Instance.BaseRoleId));
|
||||
await ReplyAsync("You are now **DemonSlayer**!");
|
||||
try
|
||||
{
|
||||
await guild_user.ModifyAsync(x => { x.Nickname = battle_tag; });
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
else
|
||||
await ReplyAsync("An error occured: make sure your Discord account hasn't already been bound to another account.!");
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyAsync("Incorrect usage: !register <email> <password> <battletag>.!");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid(string emailaddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
MailAddress m = new MailAddress(emailaddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/DiIiS-NA/Core/Discord/Modules/EventsModule.cs
Normal file
39
src/DiIiS-NA/Core/Discord/Modules/EventsModule.cs
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using DiIiS_NA.Core.Storage;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
|
||||
namespace DiIiS_NA.Core.Discord.Modules
|
||||
{
|
||||
public class EventsModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
private ulong EventsChannelId
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ulong)DiIiS_NA.Core.Discord.Config.Instance.EventsChannelId;
|
||||
}
|
||||
set{}
|
||||
}
|
||||
|
||||
|
||||
[Command("announce_event")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task SalesAnnounce()
|
||||
{
|
||||
var eb = new EmbedBuilder();
|
||||
eb.WithTitle("New Event");
|
||||
eb.WithDescription("Event Description.");
|
||||
eb.WithFooter("Ends 4th Dec 2022.\nStay at home!");
|
||||
eb.WithColor(Color.Green);
|
||||
await Context.Guild.GetTextChannel(EventsChannelId).SendMessageAsync("<:party:> **NEW EVENT!** <:party:>", false, eb.Build());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
116
src/DiIiS-NA/Core/Discord/Modules/InfoModule.cs
Normal file
116
src/DiIiS-NA/Core/Discord/Modules/InfoModule.cs
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using DiIiS_NA.Core.Extensions;
|
||||
using DiIiS_NA.Core.Storage;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
using DiIiS_NA.Core.Storage;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
using DiIiS_NA.LoginServer.Battle;
|
||||
using DiIiS_NA.LoginServer.GamesSystem;
|
||||
|
||||
namespace DiIiS_NA.Core.Discord.Modules
|
||||
{
|
||||
public class InfoModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
private ulong AnnounceChannelId
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ulong)DiIiS_NA.Core.Discord.Config.Instance.AnnounceChannelId;
|
||||
}
|
||||
set{}
|
||||
}
|
||||
|
||||
private ulong StatsChannelId
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ulong)DiIiS_NA.Core.Discord.Config.Instance.StatsChannelId;
|
||||
}
|
||||
set{}
|
||||
}
|
||||
|
||||
[Command("about")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task Info()
|
||||
{
|
||||
await ReplyAsync($"Hello, I am a bot called {Context.Client.CurrentUser.Username} written for Blizzless Server\nSpecial Thanks to those who want it.");
|
||||
}
|
||||
|
||||
[Command("ping")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task PingAsync()
|
||||
{
|
||||
await ReplyAsync("pong!");
|
||||
}
|
||||
|
||||
[Command("list_online")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task ListOnline()
|
||||
{
|
||||
int ccu = PlayerManager.OnlinePlayers.Count;
|
||||
string players = "";
|
||||
foreach (var plr in PlayerManager.OnlinePlayers)
|
||||
{
|
||||
players += plr.Account.BattleTag;
|
||||
players += "\n";
|
||||
}
|
||||
|
||||
await ReplyAsync(string.Format("Total players online: {0}\n{1}", ccu, players));
|
||||
}
|
||||
|
||||
[Command("lock")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task Lock()
|
||||
{
|
||||
var param = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "ServerOpened").First();
|
||||
param.Value = 0;
|
||||
DBSessions.SessionUpdate(param);
|
||||
await ReplyAsync("Login availability now **DISABLED**");
|
||||
}
|
||||
|
||||
[Command("unlock")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task Unlock()
|
||||
{
|
||||
var param = DBSessions.SessionQueryWhere<DBGlobalParams>(dbgp => dbgp.Name == "ServerOpened").First();
|
||||
param.Value = 1;
|
||||
DBSessions.SessionUpdate(param);
|
||||
await ReplyAsync("Login availability now **ENABLED**");
|
||||
}
|
||||
|
||||
[Command("maintenance")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task MaintenanceAnnounce([Remainder]int minutes)
|
||||
{
|
||||
//notify players maintenance is enabled
|
||||
var messages = await Context.Guild.GetTextChannel(AnnounceChannelId).GetMessagesAsync(10).FlattenAsync();
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).DeleteMessagesAsync(messages);
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).SendMessageAsync("Servers status: :tools: **PLANNED MAINTENANCE**.");
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).SendMessageAsync($"@here Servers will be restarted in **{minutes}** minutes for a planned maintenance.\n----\nСерверы будут перезагружены через **{minutes}** минут для плановых профилактических работ.");
|
||||
}
|
||||
|
||||
[Command("online")]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task OnlineAnnounce()
|
||||
{
|
||||
var messages = await Context.Guild.GetTextChannel(AnnounceChannelId).GetMessagesAsync(10).FlattenAsync();
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).DeleteMessagesAsync(messages);
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).SendMessageAsync("Servers status: :white_check_mark: **ONLINE**.");
|
||||
await Context.Guild.GetTextChannel(AnnounceChannelId).SendMessageAsync("@here Servers are up and running.\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
84
src/DiIiS-NA/Core/Discord/Services/CommandHandlingService.cs
Normal file
84
src/DiIiS-NA/Core/Discord/Services/CommandHandlingService.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
|
||||
namespace DiIiS_NA.Core.Discord.Services
|
||||
{
|
||||
public class CommandHandlingService
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.CreateLogger();
|
||||
private readonly CommandService _commands;
|
||||
private readonly DiscordSocketClient _discord;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public CommandHandlingService(IServiceProvider services)
|
||||
{
|
||||
_commands = services.GetService<CommandService>();
|
||||
_discord = services.GetService<DiscordSocketClient>();
|
||||
_services = services;
|
||||
|
||||
// Hook CommandExecuted to handle post-command-execution logic.
|
||||
_commands.CommandExecuted += CommandExecutedAsync;
|
||||
// Hook MessageReceived so we can process each message to see
|
||||
// if it qualifies as a command.
|
||||
_discord.MessageReceived += MessageReceivedAsync;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// Register modules that are public and inherit ModuleBase<T>.
|
||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
||||
}
|
||||
|
||||
public async Task MessageReceivedAsync(SocketMessage rawMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Ignore system messages, or messages from other bots
|
||||
if (!(rawMessage is SocketUserMessage message)) return;
|
||||
if (message.Source != MessageSource.User) return;
|
||||
|
||||
//if (!(message.Channel is SocketTextChannel textChannel)) return;
|
||||
//if (textChannel.Name != DiIiS_NA.Core.Discord.Config.Instance.ConsoleChannel) return;
|
||||
// This value holds the offset where the prefix ends
|
||||
var argPos = 0;
|
||||
// Perform prefix check. You may want to replace this with
|
||||
if (!message.HasCharPrefix('!', ref argPos)) return;
|
||||
// for a more traditional command format like !help.
|
||||
//if (!message.HasMentionPrefix(_discord.CurrentUser, ref argPos)) return;
|
||||
|
||||
var context = new SocketCommandContext(_discord, message);
|
||||
// Perform the execution of the command. In this method,
|
||||
// the command service will perform precondition and parsing check
|
||||
// then execute the command if one is matched.
|
||||
Logger.BotCommand("[{0}]: {1}", message.Author.Username, message.Content);
|
||||
await _commands.ExecuteAsync(context, argPos, _services);
|
||||
// Note that normally a result will be returned by this format, but here
|
||||
// we will handle the result in CommandExecutedAsync,
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.DebugException(e, "Discord exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CommandExecutedAsync(Optional<CommandInfo> command, ICommandContext context, IResult result)
|
||||
{
|
||||
// command is unspecified when there was a search failure (command not found); we don't care about these errors
|
||||
if (!command.IsSpecified)
|
||||
return;
|
||||
|
||||
// the command was successful, we don't care about this result, unless we want to log that a command succeeded.
|
||||
if (result.IsSuccess)
|
||||
return;
|
||||
|
||||
// the command failed, let's notify the user that something happened.
|
||||
await context.Channel.SendMessageAsync($"error: {result}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23,5 +23,7 @@ namespace DiIiS_NA.Core.Storage.AccountDataBase.Entities
|
||||
public virtual ulong LastOnline { get; set; }
|
||||
public virtual bool HasRename { get; set; }
|
||||
public virtual ulong RenameCooldown { get; set; }
|
||||
}
|
||||
public virtual ulong DiscordId { get; set; }
|
||||
public virtual string DiscordTag { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@ namespace DiIiS_NA.Core.Storage.AccountDataBase.Mapper
|
||||
Table("accounts");
|
||||
Id(e => e.Id).CustomType<PostgresUserTypeNullable>().GeneratedBy.Sequence("accounts_seq").UnsavedValue(null);
|
||||
Map(e => e.Email);
|
||||
Map(e => e.DiscordTag);
|
||||
Map(e => e.DiscordId).CustomType<PostgresUserType>().Default("0");
|
||||
Map(e => e.Banned).Not.Nullable().Default("false");
|
||||
Map(e => e.Salt)/*.CustomSqlType("VarBinary(32)")*/.Length(32);
|
||||
Map(e => e.PasswordVerifier)/*.CustomSqlType("VarBinary")*/.Length(128);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
//Blizzless Project 2022
|
||||
using DiIiS_NA.Core.Discord;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
//Blizzless Project 2022
|
||||
using DiIiS_NA.GameServer.ClientSystem.Base;
|
||||
@ -24,7 +25,7 @@ namespace DiIiS_NA.GameServer.ClientSystem
|
||||
public static GSBackend GSBackend { get; set; }
|
||||
|
||||
public static int MaintenanceTime = -1;
|
||||
|
||||
public Bot DiscordBot { get; set; }
|
||||
public GameServer()
|
||||
{
|
||||
this.OnConnect += ClientManager.Instance.OnConnect;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
//Blizzless Project 2022
|
||||
//Blizzless Project 2022
|
||||
using DiIiS_NA.Core.Discord.Modules;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
//Blizzless Project 2022
|
||||
using DiIiS_NA.Core.MPQ;
|
||||
@ -164,6 +165,7 @@ namespace DiIiS_NA
|
||||
Logger.Info("REST server started - " + REST.Config.Instance.IP + ":{0}", REST.Config.Instance.PORT);
|
||||
}
|
||||
|
||||
|
||||
//BGS
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
IEventLoopGroup boss = new MultithreadEventLoopGroup(1);
|
||||
@ -268,7 +270,16 @@ namespace DiIiS_NA
|
||||
GameServer = new DiIiS_NA.GameServer.ClientSystem.GameServer();
|
||||
GameServerThread = new Thread(GameServer.Run) { Name = "GameServerThread", IsBackground = true };
|
||||
GameServerThread.Start();
|
||||
|
||||
if (DiIiS_NA.Core.Discord.Config.Instance.Enabled)
|
||||
{
|
||||
Logger.Info("Starting Discord bot handler..");
|
||||
GameServer.DiscordBot = new Core.Discord.Bot();
|
||||
GameServer.DiscordBot.MainAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info("Discord bot Disabled..");
|
||||
}
|
||||
DiIiS_NA.GameServer.GSSystem.GeneratorsSystem.SpawnGenerator.RegenerateDensity();
|
||||
DiIiS_NA.GameServer.ClientSystem.GameServer.GSBackend = new GSBackend(DiIiS_NA.LoginServer.Config.Instance.BindIP, DiIiS_NA.LoginServer.Config.Instance.WebPort);
|
||||
return true;
|
||||
|
||||
148
src/DiIiS-NA/config.ini
Normal file
148
src/DiIiS-NA/config.ini
Normal file
@ -0,0 +1,148 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ;
|
||||
; blizzless Configuration File ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------------------------------------------------------;
|
||||
; ;
|
||||
; This file is an example configuration and may require modification to suit your needs. ;
|
||||
; ;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Settings for Bnet server
|
||||
[Battle-Server]
|
||||
Enabled = true
|
||||
BindIP = 127.0.0.1
|
||||
BindIPv6 = ::1
|
||||
Port = 1119
|
||||
MOTD = Welcome to Diablo 3 Emulator!
|
||||
RoSEnabled = true
|
||||
SeasonEnabled = true
|
||||
|
||||
; Settings for game server
|
||||
[Game-Server]
|
||||
Enabled = true
|
||||
PvP = false
|
||||
BindIP = 127.0.0.1
|
||||
WebIP = 127.0.0.1
|
||||
WebPort = 9001
|
||||
BindIPv6 = ::1
|
||||
Port = 1999
|
||||
DRLGemu = true
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Authentication settings
|
||||
[Authentication]
|
||||
DisablePasswordChecks=true
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Discord bot settings
|
||||
[Discord]
|
||||
Enabled=true
|
||||
MonitorEnabled=false
|
||||
Token=secret token
|
||||
GuildId=0
|
||||
AnnounceChannelId=0
|
||||
StatsChannelId=0
|
||||
EventsChannelId=0
|
||||
BaseRoleId=0
|
||||
PremiumRoleId=0
|
||||
CollectorRoleId=0
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; You can set here the command-prefix. Note: You can't use slash as a prefix.
|
||||
[Commands]
|
||||
CommandPrefix = !
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; You can enable web-services here and use the provided contrib/web/LibMooge.php for communicating mooege over http.
|
||||
[REST]
|
||||
Enabled = true
|
||||
Public = 127.0.0.1
|
||||
PublicIP = 127.0.0.1
|
||||
PORT = 8081
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Networking settings.
|
||||
[Networking]
|
||||
EnableIPv6 = false ; experimental!!
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Network address translation settings.
|
||||
; You only need to change this if you're running behind a dsl router or so.
|
||||
; Important: If you enable NAT, LAN-clients will not able to connect in gs.
|
||||
; (Will be fixed later with a proper implementation similar to one in pvpgn).
|
||||
[NAT]
|
||||
Enabled = false
|
||||
PublicIP = 101.185.137.121 ; You need to change this to your router's public interface IP if you'd like to use NAT.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; General logging settings
|
||||
[Logging]
|
||||
Root=logs
|
||||
|
||||
; Settings for console logger
|
||||
[ConsoleLog]
|
||||
Enabled=true
|
||||
Target=Console
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=Trace
|
||||
MaximumLevel=Fatal
|
||||
|
||||
; Settings for server log file.
|
||||
[ServerLog]
|
||||
Enabled=true
|
||||
Target=File
|
||||
FileName="blizzless.log"
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=Trace
|
||||
MaximumLevel=Fatal
|
||||
ResetOnStartup=true
|
||||
|
||||
; Settings for chat log file.
|
||||
[ChatLog]
|
||||
Enabled=true
|
||||
Target=File
|
||||
FileName="blizzless-chat.log"
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=ChatMessage
|
||||
MaximumLevel=ChatMessage
|
||||
ResetOnStartup=true
|
||||
|
||||
; Settings for discord log file.
|
||||
[DiscordLog]
|
||||
Enabled=false
|
||||
Target=File
|
||||
FileName="discord-bot.log"
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=BotCommand
|
||||
MaximumLevel=BotCommand
|
||||
ResetOnStartup=true
|
||||
|
||||
; Settings for renames log file.
|
||||
[RenameAccountLog]
|
||||
Enabled=true
|
||||
Target=File
|
||||
FileName="blizzless-btag-rename.log"
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=RenameAccountLog
|
||||
MaximumLevel=RenameAccountLog
|
||||
ResetOnStartup=true
|
||||
|
||||
; Settings for packet logger, only recommended for developers!
|
||||
[PacketLog]
|
||||
Enabled=true
|
||||
Target=File
|
||||
FileName="packet-dump.log"
|
||||
IncludeTimeStamps=true
|
||||
MinimumLevel=PacketDump
|
||||
MaximumLevel=PacketDump
|
||||
ResetOnStartup=true
|
||||
Loading…
Reference in New Issue
user.block.title