Split Geekbot.net into src/Bot, src/Core, and src/Web
This commit is contained in:
parent
7b6dd2d2f9
commit
fc0af492ad
197 changed files with 542 additions and 498 deletions
16
src/Core/Localization/ITranslationHandler.cs
Normal file
16
src/Core/Localization/ITranslationHandler.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
|
||||
namespace Geekbot.Core.Localization
|
||||
{
|
||||
public interface ITranslationHandler
|
||||
{
|
||||
Task<string> GetString(ulong guildId, string command, string stringName);
|
||||
string GetString(string language, string command, string stringName);
|
||||
Task<Dictionary<string, string>> GetDict(ICommandContext context, string command);
|
||||
Task<TranslationGuildContext> GetGuildContext(ICommandContext context);
|
||||
Task<bool> SetLanguage(ulong guildId, string language);
|
||||
List<string> SupportedLanguages { get; }
|
||||
}
|
||||
}
|
90
src/Core/Localization/TranslationGuildContext.cs
Normal file
90
src/Core/Localization/TranslationGuildContext.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Geekbot.Core.Localization
|
||||
{
|
||||
public class TranslationGuildContext
|
||||
{
|
||||
public ITranslationHandler TranslationHandler { get; }
|
||||
public string Language { get; }
|
||||
public Dictionary<string, string> Dict { get; }
|
||||
|
||||
public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary<string, string> dict)
|
||||
{
|
||||
TranslationHandler = translationHandler;
|
||||
Language = language;
|
||||
Dict = dict;
|
||||
}
|
||||
|
||||
public string GetString(string stringToFormat, params object[] args)
|
||||
{
|
||||
return string.Format(Dict[stringToFormat] ?? "", args);
|
||||
}
|
||||
|
||||
public string FormatDateTimeAsRemaining(DateTimeOffset dateTime)
|
||||
{
|
||||
var remaining = dateTime - DateTimeOffset.Now;
|
||||
const string formattable = "{0} {1}";
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (remaining.Days > 0)
|
||||
{
|
||||
var s = GetTimeString(TimeTypes.Days);
|
||||
sb.AppendFormat(formattable, remaining.Days, GetSingOrPlur(remaining.Days, s));
|
||||
}
|
||||
|
||||
if (remaining.Hours > 0)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append(", ");
|
||||
var s = GetTimeString(TimeTypes.Hours);
|
||||
sb.AppendFormat(formattable, remaining.Hours, GetSingOrPlur(remaining.Hours, s));
|
||||
}
|
||||
|
||||
if (remaining.Minutes > 0)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append(", ");
|
||||
var s = GetTimeString(TimeTypes.Minutes);
|
||||
sb.AppendFormat(formattable, remaining.Minutes, GetSingOrPlur(remaining.Minutes, s));
|
||||
}
|
||||
|
||||
if (remaining.Seconds > 0)
|
||||
{
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
var and = TranslationHandler.GetString(Language, "dateTime", "And");
|
||||
sb.AppendFormat(" {0} ", and);
|
||||
}
|
||||
var s = GetTimeString(TimeTypes.Seconds);
|
||||
sb.AppendFormat(formattable, remaining.Seconds, GetSingOrPlur(remaining.Seconds, s));
|
||||
}
|
||||
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
public Task<bool> SetLanguage(ulong guildId, string language)
|
||||
{
|
||||
return TranslationHandler.SetLanguage(guildId, language);
|
||||
}
|
||||
|
||||
private string GetTimeString(TimeTypes type)
|
||||
{
|
||||
return TranslationHandler.GetString(Language, "dateTime", type.ToString());
|
||||
}
|
||||
|
||||
private string GetSingOrPlur(int number, string rawString)
|
||||
{
|
||||
var versions = rawString.Split('|');
|
||||
return number == 1 ? versions[0] : versions[1];
|
||||
}
|
||||
|
||||
private enum TimeTypes
|
||||
{
|
||||
Days,
|
||||
Hours,
|
||||
Minutes,
|
||||
Seconds
|
||||
}
|
||||
}
|
||||
}
|
194
src/Core/Localization/TranslationHandler.cs
Normal file
194
src/Core/Localization/TranslationHandler.cs
Normal file
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core.GuildSettingsManager;
|
||||
using Geekbot.Core.Logger;
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Geekbot.Core.Localization
|
||||
{
|
||||
public class TranslationHandler : ITranslationHandler
|
||||
{
|
||||
private readonly IGeekbotLogger _logger;
|
||||
private readonly IGuildSettingsManager _guildSettingsManager;
|
||||
private readonly Dictionary<ulong, string> _serverLanguages;
|
||||
private Dictionary<string, Dictionary<string, Dictionary<string, string>>> _translations;
|
||||
|
||||
public TranslationHandler(IGeekbotLogger logger, IGuildSettingsManager guildSettingsManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_guildSettingsManager = guildSettingsManager;
|
||||
_logger.Information(LogSource.Geekbot, "Loading Translations");
|
||||
LoadTranslations();
|
||||
_serverLanguages = new Dictionary<ulong, string>();
|
||||
}
|
||||
|
||||
private void LoadTranslations()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Read the file
|
||||
var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.yml"));
|
||||
|
||||
// Deserialize
|
||||
var input = new StringReader(translationFile);
|
||||
var mergingParser = new MergingParser(new Parser(input));
|
||||
var deserializer = new DeserializerBuilder().Build();
|
||||
var rawTranslations = deserializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, string>>>>(mergingParser);
|
||||
|
||||
// Sort
|
||||
var sortedPerLanguage = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
|
||||
foreach (var command in rawTranslations)
|
||||
{
|
||||
foreach (var str in command.Value)
|
||||
{
|
||||
foreach (var lang in str.Value)
|
||||
{
|
||||
if (!sortedPerLanguage.ContainsKey(lang.Key))
|
||||
{
|
||||
var commandDict = new Dictionary<string, Dictionary<string, string>>();
|
||||
var strDict = new Dictionary<string, string>
|
||||
{
|
||||
{str.Key, lang.Value}
|
||||
};
|
||||
commandDict.Add(command.Key, strDict);
|
||||
sortedPerLanguage.Add(lang.Key, commandDict);
|
||||
}
|
||||
if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key))
|
||||
{
|
||||
var strDict = new Dictionary<string, string>
|
||||
{
|
||||
{str.Key, lang.Value}
|
||||
};
|
||||
sortedPerLanguage[lang.Key].Add(command.Key, strDict);
|
||||
}
|
||||
if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key))
|
||||
{
|
||||
sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_translations = sortedPerLanguage;
|
||||
|
||||
// Find Languages
|
||||
SupportedLanguages = new List<string>();
|
||||
foreach (var lang in sortedPerLanguage)
|
||||
{
|
||||
SupportedLanguages.Add(lang.Key);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(LogSource.Geekbot, "Failed to load Translations", e);
|
||||
Environment.Exit(GeekbotExitCode.TranslationsFailed.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
private Task<string> GetServerLanguage(ulong guildId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string lang;
|
||||
try
|
||||
{
|
||||
lang = _serverLanguages[guildId];
|
||||
if (!string.IsNullOrEmpty(lang))
|
||||
{
|
||||
return Task.FromResult(lang);
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
catch
|
||||
{
|
||||
lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN";
|
||||
_serverLanguages[guildId] = lang;
|
||||
return Task.FromResult(lang);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(LogSource.Geekbot, "Could not get guild language", e);
|
||||
return Task.FromResult("EN");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetString(ulong guildId, string command, string stringName)
|
||||
{
|
||||
var serverLang = await GetServerLanguage(guildId);
|
||||
return GetString(serverLang, command, stringName);
|
||||
}
|
||||
|
||||
public string GetString(string language, string command, string stringName)
|
||||
{
|
||||
var translation = _translations[language][command][stringName];
|
||||
if (!string.IsNullOrWhiteSpace(translation)) return translation;
|
||||
translation = _translations[command][stringName]["EN"];
|
||||
if (string.IsNullOrWhiteSpace(translation))
|
||||
{
|
||||
_logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}");
|
||||
}
|
||||
return translation;
|
||||
}
|
||||
|
||||
private async Task<Dictionary<string, string>> GetDict(ICommandContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower();
|
||||
var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return _translations[serverLanguage][command];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(LogSource.Geekbot, "No translations for command found", e);
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TranslationGuildContext> GetGuildContext(ICommandContext context)
|
||||
{
|
||||
var dict = await GetDict(context);
|
||||
var language = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return new TranslationGuildContext(this, language, dict);
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, string>> GetDict(ICommandContext context, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return _translations[serverLanguage][command];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(LogSource.Geekbot, "No translations for command found", e);
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> SetLanguage(ulong guildId, string language)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SupportedLanguages.Contains(language)) return false;
|
||||
var guild = _guildSettingsManager.GetSettings(guildId);
|
||||
guild.Language = language;
|
||||
await _guildSettingsManager.UpdateSettings(guild);
|
||||
_serverLanguages[guildId] = language;
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(LogSource.Geekbot, "Error while changing language", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> SupportedLanguages { get; private set; }
|
||||
}
|
||||
}
|
207
src/Core/Localization/Translations.yml
Normal file
207
src/Core/Localization/Translations.yml
Normal file
|
@ -0,0 +1,207 @@
|
|||
---
|
||||
dateTime:
|
||||
Days:
|
||||
EN: "day|days"
|
||||
CHDE: "tag|täg"
|
||||
Hours:
|
||||
EN: "hour|hours"
|
||||
CHDE: "stund|stunde"
|
||||
Minutes:
|
||||
EN: "minute|minutes"
|
||||
CHDE: "minute|minute"
|
||||
Seconds:
|
||||
EN: "second|seconds"
|
||||
CHDE: "sekunde|sekunde"
|
||||
And:
|
||||
EN: "and"
|
||||
CHDE: "und"
|
||||
admin:
|
||||
NewLanguageSet:
|
||||
EN: "I will reply in english from now on"
|
||||
CHDE: "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä"
|
||||
GetLanguage:
|
||||
EN: "I'm talking english"
|
||||
CHDE: "I red schwiizerdüütsch"
|
||||
errorHandler:
|
||||
SomethingWentWrong:
|
||||
EN: "Something went wrong :confused:"
|
||||
CHDE: "Öppis isch schief gange :confused:"
|
||||
httpErrors:
|
||||
403:
|
||||
EN: "Seems like i don't have enough permission to that :confused:"
|
||||
CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:"
|
||||
choose:
|
||||
Choice:
|
||||
EN: "I Choose **{0}**"
|
||||
CHDE: "I nimme **{0}**"
|
||||
good:
|
||||
CannotChangeOwn:
|
||||
EN: "Sorry {0}, but you can't give yourself karma"
|
||||
CHDE: "Sorry {0}, aber du chasch dr selber kei karma geh"
|
||||
WaitUntill:
|
||||
EN: "Sorry {0}, but you have to wait {1} before you can give karma again..."
|
||||
CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..."
|
||||
Increased:
|
||||
EN: "Karma gained"
|
||||
CHDE: "Karma becho"
|
||||
By:
|
||||
EN: "By"
|
||||
CHDE: "Vo"
|
||||
Amount:
|
||||
EN: "Amount"
|
||||
CHDE: "Mengi"
|
||||
Current:
|
||||
EN: "Current"
|
||||
CHDE: "Jetzt"
|
||||
bad:
|
||||
CannotChangeOwn:
|
||||
EN: "Sorry {0}, but you can't lower your own karma"
|
||||
CHDE: "Sorry {0}, aber du chasch dr din eigete karma nid weg neh"
|
||||
WaitUntill:
|
||||
EN: "Sorry {0}, but you have to wait {1} before you can lower karma again..."
|
||||
CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..."
|
||||
Decreased:
|
||||
EN: "Karma lowered"
|
||||
CHDE: "Karma gsenkt"
|
||||
By:
|
||||
EN: "By"
|
||||
CHDE: "Vo"
|
||||
Amount:
|
||||
EN: "Amount"
|
||||
CHDE: "Mengi"
|
||||
Current:
|
||||
EN: "Current"
|
||||
CHDE: "Jetzt"
|
||||
roll:
|
||||
Rolled:
|
||||
EN: "{0}, you rolled {1}, your guess was {2}"
|
||||
CHDE: "{0}, du hesch {1} grollt und hesch {2} grate"
|
||||
Gratz:
|
||||
EN: "Congratulations {0}, your guess was correct!"
|
||||
CHDE: "Gratuliere {0}, du hesch richtig grate!"
|
||||
RolledNoGuess:
|
||||
EN: "{0}, you rolled {1}"
|
||||
CHDE: "{0}, du hesch {1} grollt"
|
||||
NoPrevGuess:
|
||||
EN: ":red_circle: {0}, you can't guess the same number again, guess another number or wait {1}"
|
||||
CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate, rate öppis anders oder warte {1}"
|
||||
cookies: &cookiesAlias
|
||||
GetCookies:
|
||||
EN: "You got {0} cookies, there are now {1} cookies in you cookie jar"
|
||||
CHDE: "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"
|
||||
WaitForMoreCookies:
|
||||
EN: "You already got cookies today, you can have more cookies in {0}"
|
||||
CHDE: "Du hesch scho guetzli becho hüt, du chasch meh ha in {0}"
|
||||
InYourJar:
|
||||
EN: "There are {0} cookies in you cookie jar"
|
||||
CHDE: "Es hät {0} guetzli ih dineri büchs"
|
||||
Given:
|
||||
EN: "You gave {0} cookies to {1}"
|
||||
CHDE: "Du hesch {1} {0} guetzli geh"
|
||||
NotEnoughToGive:
|
||||
EN: "You don't have enough cookies"
|
||||
CHDE: "Du hesch nid gnueg guetzli"
|
||||
NotEnoughCookiesToEat:
|
||||
EN: "Your cookie jar looks almost empty, you should probably not eat a cookie"
|
||||
CHDE: "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse"
|
||||
AteCookies:
|
||||
EN: "You ate {0} cookies, you've only got {1} cookies left"
|
||||
CHDE: "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"
|
||||
cookie:
|
||||
# because command aliases are to hard to deal with...
|
||||
<<: *cookiesAlias
|
||||
role:
|
||||
NoRolesConfigured:
|
||||
EN: "There are no roles configured for this server"
|
||||
CHDE: "Es sind kei rolle für dä server konfiguriert"
|
||||
ListHeader:
|
||||
EN: "**Self Service Roles on {0}**"
|
||||
CHDE: "**Self Service Rollene uf {0}**"
|
||||
ListInstruction:
|
||||
EN: "To get a role, use `!role [name]`"
|
||||
CHDE: "Zum ä rolle becho, schriib `!role [name]`"
|
||||
RoleNotFound:
|
||||
EN: "That role doesn't exist or is not on the whitelist"
|
||||
CHDE: "Die rolle gids nid or isch nid uf dr whitelist"
|
||||
RemovedUserFromRole:
|
||||
EN: "Removed you from {0}"
|
||||
CHDE: "Han di entfernt vo {0}"
|
||||
AddedUserFromRole:
|
||||
EN: "Added you to {0}"
|
||||
CHDE: "Han di hinzue gfüegt zu {0}"
|
||||
CannotAddManagedRole:
|
||||
EN: "You can't add a role that is managed by discord"
|
||||
CHDE: "Du chasch kei rolle hinzuefüge wo verwalted wird vo discord"
|
||||
CannotAddDangerousRole:
|
||||
EN: "You cannot add that role to self service because it contains one or more dangerous permissions"
|
||||
CHDE: "Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het"
|
||||
AddedRoleToWhitelist:
|
||||
EN: "Added {0} to the whitelist"
|
||||
CHDE: "{0} isch zur whitelist hinzuegfüegt"
|
||||
RemovedRoleFromWhitelist:
|
||||
EN: "Removed {0} from the whitelist"
|
||||
CHDE: "{0} isch vo dr whitelist glöscht"
|
||||
quote:
|
||||
NoQuotesFound:
|
||||
EN: "This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save <messageId>`"
|
||||
CHDE: "Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save <messageId>`"
|
||||
CannotSaveOwnQuotes:
|
||||
EN: "You can't save your own quotes..."
|
||||
CHDE: "Du chasch kei quotes vo dir selber speichere..."
|
||||
CannotQuoteBots:
|
||||
EN: "You can't save quotes by a bot..."
|
||||
CHDE: "Du chasch kei quotes vomne bot speichere..."
|
||||
QuoteAdded:
|
||||
EN: "**Quote Added**"
|
||||
CHDE: "**Quote hinzugfüegt**"
|
||||
Removed:
|
||||
EN: "**Removed #{0}**"
|
||||
CHDE: "**#{0} glöscht**"
|
||||
NotFoundWithId:
|
||||
EN: "I couldn't find a quote with that ID :disappointed:"
|
||||
CHDE: "Ich chan kei quote finde mit därri ID :disappointed:"
|
||||
QuoteStats:
|
||||
EN: "Quote Stats"
|
||||
CHDE: "Quote statistike"
|
||||
TotalQuotes:
|
||||
EN: "Total"
|
||||
CHDE: "Total"
|
||||
MostQuotesPerson:
|
||||
EN: "Most quoted person"
|
||||
CHDE: "Meist quoteti person"
|
||||
rank:
|
||||
InvalidType:
|
||||
EN: "Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'"
|
||||
CHDE: "Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies`'"
|
||||
LimitingTo20Warning:
|
||||
EN: ":warning: Limiting to 20\n"
|
||||
CHDE: ":warning: Limitiert uf 20\n"
|
||||
NoTypeFoundForServer:
|
||||
EN: "No {0} found on this server"
|
||||
CHDE: "Kei {0} gfunde für dä server"
|
||||
FailedToResolveAllUsernames:
|
||||
EN: ":warning: I couldn't find all usernames. Maybe they left the server?\n"
|
||||
CHDE: ":warning: Ich han nid alli benutzername gfunde. villiicht hend sie de server verlah?\n"
|
||||
HighscoresFor:
|
||||
EN: ":bar_chart: **{0} Highscore for {1}**"
|
||||
CHDE: ":bar_chart: **{0} Highscore für {1}**"
|
||||
ship:
|
||||
Matchmaking:
|
||||
EN: "Matchmaking"
|
||||
CHDE: "Verkupple"
|
||||
NotGonnaToHappen:
|
||||
EN: "Not gonna happen"
|
||||
CHDE: "Wird nöd klappe"
|
||||
NotSuchAGoodIdea:
|
||||
EN: "Not such a good idea"
|
||||
CHDE: "Nöd so ä gueti idee"
|
||||
ThereMightBeAChance:
|
||||
EN: "There might be a chance"
|
||||
CHDE: "Es gid eventuel ä chance"
|
||||
CouldWork:
|
||||
EN: "Almost a match"
|
||||
CHDE: "Fasch en match"
|
||||
ItsAMatch:
|
||||
EN: "It's a match"
|
||||
CHDE: "Es isch es traumpaar"
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue