Compare commits

..

No commits in common. "ee8cc96f71219775ffed655eb2e885eba14648a5" and "059b2e657cc757213562bca43e0c36b98f90cfe3" have entirely different histories.

8 changed files with 75 additions and 1290 deletions

View File

@ -20,7 +20,7 @@ public class Behaver
var subtypes = AppDomain.CurrentDomain.GetAssemblies() var subtypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(domainAssembly => domainAssembly.GetTypes()) .SelectMany(domainAssembly => domainAssembly.GetTypes())
.Where(type => type.IsSubclassOf(typeof(vassago.Behavior.Behavior)) && !type.IsAbstract && .Where(type => type.IsSubclassOf(typeof(vassago.Behavior.Behavior)) && !type.IsAbstract &&
type.GetCustomAttributes(typeof(StaticPlzAttribute), false)?.Any() == true) type.GetCustomAttributes(typeof(StaticPlzAttribute),false)?.Any() == true)
.ToList(); .ToList();
foreach (var subtype in subtypes) foreach (var subtype in subtypes)
@ -72,7 +72,7 @@ public class Behaver
public void MarkSelf(Account selfAccount) public void MarkSelf(Account selfAccount)
{ {
if (SelfUser == null) if(SelfUser == null)
{ {
SelfUser = selfAccount.IsUser; SelfUser = selfAccount.IsUser;
} }
@ -86,25 +86,15 @@ public class Behaver
public bool CollapseUsers(User primary, User secondary) public bool CollapseUsers(User primary, User secondary)
{ {
if (primary.Accounts == null) if(primary.Accounts == null)
primary.Accounts = new List<Account>(); primary.Accounts = new List<Account>();
if (secondary.Accounts != null) if(secondary.Accounts != null)
primary.Accounts.AddRange(secondary.Accounts); primary.Accounts.AddRange(secondary.Accounts);
foreach (var a in secondary.Accounts) foreach(var a in secondary.Accounts)
{ {
a.IsUser = primary; a.IsUser = primary;
} }
secondary.Accounts.Clear(); secondary.Accounts.Clear();
var uacs = Rememberer.SearchUACs(u => u.Users.FirstOrDefault(u => u.Id == secondary.Id) != null);
if (uacs.Count() > 0)
{
foreach (var uac in uacs)
{
uac.Users.RemoveAll(u => u.Id == secondary.Id);
uac.Users.Add(primary);
Rememberer.RememberUAC(uac);
}
}
Rememberer.ForgetUser(secondary); Rememberer.ForgetUser(secondary);
Rememberer.RememberUser(primary); Rememberer.RememberUser(primary);
return true; return true;

View File

@ -14,7 +14,7 @@ public class TwitchDismiss : Behavior
public override bool ShouldAct(Message message) public override bool ShouldAct(Message message)
{ {
var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault(); var ti = ProtocolInterfaces.ProtocolList.twitchs.FirstOrDefault();
// Console.WriteLine($"TwitchDismiss checking. menions me? {message.MentionsMe}"); Console.WriteLine($"TwitchDismiss checking. menions me? {message.MentionsMe}");
if(message.MentionsMe && if(message.MentionsMe &&
(Regex.IsMatch(message.Content.ToLower(), "\\bbegone\\b") || Regex.IsMatch(message.Content.ToLower(), "\\bfuck off\\b"))) (Regex.IsMatch(message.Content.ToLower(), "\\bbegone\\b") || Regex.IsMatch(message.Content.ToLower(), "\\bfuck off\\b")))
{ {

View File

@ -16,36 +16,24 @@ namespace vassago.Conversion
{ {
public static class Converter public static class Converter
{ {
private delegate decimal Convert1Way(decimal input); public static string DebugInfo(){
private static string currencyPath;
private static ExchangePairs currencyConf = null;
private static DateTime lastUpdatedCurrency = DateTime.UnixEpoch;
private static List<Tuple<string, string, Convert1Way, Convert1Way>> knownConversions = new List<Tuple<string, string, Convert1Way, Convert1Way>>();
private static Dictionary<List<string>, string> knownAliases = new Dictionary<List<string>, string>(new List<KeyValuePair<List<string>, string>>());
public static string DebugInfo()
{
var convertibles = knownConversions.Select(kc => kc.Item1).Union(knownConversions.Select(kc => kc.Item2)).Union( var convertibles = knownConversions.Select(kc => kc.Item1).Union(knownConversions.Select(kc => kc.Item2)).Union(
knownAliases.Keys.SelectMany(k => k)).Distinct(); knownAliases.Keys.SelectMany(k => k)).Distinct();
return $"{convertibles.Count()} convertibles; {string.Join(", ", convertibles)}"; return $"{convertibles.Count()} convertibles; {string.Join(", ", convertibles)}";
} }
private delegate decimal Convert1Way(decimal input);
private static string currencyPath;
private static ExchangePairs currencyConf = null;
private static DateTime lastUpdatedCurrency = DateTime.UnixEpoch;
private static List<Tuple<string, string, Convert1Way, Convert1Way>> knownConversions = new List<Tuple<string, string, Convert1Way, Convert1Way>>()
{
new Tuple<string, string, Convert1Way, Convert1Way>("℉", "°C", (f => {return(f- 32.0m) / 1.8m;}), (c => {return 1.8m*c + 32.0m;})),
};
private static Dictionary<List<string>, string> knownAliases = new Dictionary<List<string>, string>(new List<KeyValuePair<List<string>, string>>());
public static void Load(string currencyPath) public static void Load(string currencyPath)
{ {
Converter.currencyPath = currencyPath; Converter.currencyPath = currencyPath;
loadStatic();
Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromHours(8));
loadCurrency();
}
});
}
private static void loadStatic()
{
knownConversions = new List<Tuple<string, string, Convert1Way, Convert1Way>>();
knownAliases = new Dictionary<List<string>, string>(new List<KeyValuePair<List<string>, string>>());
var convConf = JsonConvert.DeserializeObject<ConversionConfig>(File.ReadAllText("assets/conversion.json")); var convConf = JsonConvert.DeserializeObject<ConversionConfig>(File.ReadAllText("assets/conversion.json"));
foreach (var unit in convConf.Units) foreach (var unit in convConf.Units)
{ {
@ -55,12 +43,18 @@ namespace vassago.Conversion
{ {
AddLinearPair(lp.item1, lp.item2, lp.factor); AddLinearPair(lp.item1, lp.item2, lp.factor);
} }
Task.Run(async () => {
while(true)
{
loadCurrency(); loadCurrency();
await Task.Delay(TimeSpan.FromHours(8));
}
});
} }
private static void loadCurrency() private static void loadCurrency()
{ {
Console.WriteLine("loading currency exchange data."); Console.WriteLine("loading currency exchange data.");
if (currencyConf != null) if(currencyConf != null)
{ {
knownConversions.RemoveAll(kc => kc.Item1 == currencyConf.Base); knownConversions.RemoveAll(kc => kc.Item1 == currencyConf.Base);
} }
@ -68,41 +62,38 @@ namespace vassago.Conversion
{ {
currencyConf = JsonConvert.DeserializeObject<ExchangePairs>(File.ReadAllText(currencyPath)); currencyConf = JsonConvert.DeserializeObject<ExchangePairs>(File.ReadAllText(currencyPath));
if (!knownAliases.ContainsValue(currencyConf.Base)) if(!knownAliases.ContainsValue(currencyConf.Base))
{ {
knownAliases.Add(new List<string>() { currencyConf.Base.ToLower() }, currencyConf.Base); knownAliases.Add(new List<string>() { currencyConf.Base.ToLower() }, currencyConf.Base);
} }
foreach (var rate in currencyConf.rates) foreach (var rate in currencyConf.rates)
{ {
if (!knownAliases.ContainsValue(rate.Key)) if(!knownAliases.ContainsValue(rate.Key))
{ {
knownAliases.Add(new List<string>() { rate.Key.ToLower() }, rate.Key); knownAliases.Add(new List<string>() { rate.Key.ToLower() }, rate.Key);
} }
AddLinearPair(currencyConf.Base, rate.Key, rate.Value); AddLinearPair(currencyConf.Base, rate.Key, rate.Value);
Console.WriteLine($"{rate.Key.ToLower()} alias of {rate.Key}");
} }
} }
} }
public static string Convert(decimal numericTerm, string sourceunit, string destinationUnit) public static string Convert(decimal numericTerm, string sourceunit, string destinationUnit)
{ {
var normalizationAttempt = NormalizeUnit(sourceunit); var normalizedSourceUnit = NormalizeUnit(sourceunit);
if (normalizationAttempt.Item2 != null) if (string.IsNullOrWhiteSpace(normalizedSourceUnit))
{ {
return $"problem with {sourceunit}: {normalizationAttempt.Item2}"; return $"parse failure: what's {sourceunit}?";
} }
var normalizedSourceUnit = normalizationAttempt.Item1; var normalizedDestUnit = NormalizeUnit(destinationUnit);
if (string.IsNullOrWhiteSpace(normalizedDestUnit))
normalizationAttempt = NormalizeUnit(destinationUnit);
if (normalizationAttempt.Item2 != null)
{ {
return $"problem with {destinationUnit}: {normalizationAttempt.Item2}"; return $"parse failure: what's {destinationUnit}?";
} }
var normalizedDestUnit = normalizationAttempt.Item1;
if (normalizedSourceUnit == normalizedDestUnit) if (normalizedSourceUnit == normalizedDestUnit)
{ {
return $"source and dest are the same, so... {numericTerm} {normalizedDestUnit}?"; return $"source and dest are the same, so... {numericTerm} {normalizedDestUnit}?";
} }
var foundPath = exhaustiveBreadthFirst(normalizedDestUnit, new List<string>() { normalizedSourceUnit })?.ToList(); var foundPath = exhaustiveBreadthFirst(normalizedDestUnit, new List<string>() { normalizedSourceUnit })?.ToList();
if (foundPath != null) if (foundPath != null)
@ -127,7 +118,7 @@ namespace vassago.Conversion
} }
else else
{ {
if (String.Format("{0:G3}", accumulator).Contains("E-")) if(String.Format("{0:G3}", accumulator).Contains("E-"))
{ {
return $"{accumulator} {normalizedDestUnit}"; return $"{accumulator} {normalizedDestUnit}";
} }
@ -139,34 +130,21 @@ namespace vassago.Conversion
} }
return "dimensional analysis failure - I know those units but can't find a path between them."; return "dimensional analysis failure - I know those units but can't find a path between them.";
} }
private static Tuple<string, string> NormalizeUnit(string unit) private static string NormalizeUnit(string unit)
{ {
if (string.IsNullOrWhiteSpace(unit)) if(string.IsNullOrWhiteSpace(unit))
return new(null, "no unit provided"); return null;
var normalizedUnit = unit.ToLower(); var normalizedUnit = unit.ToLower();
if (knownConversions.FirstOrDefault(c => c.Item1 == normalizedUnit || c.Item2 == normalizedUnit) != null) if (knownConversions.FirstOrDefault(c => c.Item1 == normalizedUnit || c.Item2 == normalizedUnit) != null)
{ {
return new(normalizedUnit, null); return normalizedUnit;
} }
//if "unit" isn't a canonical name...
if (!knownAliases.ContainsValue(normalizedUnit)) if (!knownAliases.ContainsValue(normalizedUnit))
{ {
//then we look through aliases... var key = knownAliases.Keys.FirstOrDefault(listkey => listkey.Contains(normalizedUnit));
var keys = knownAliases.Keys.Where(listkey => listkey.Contains(normalizedUnit)); if (key != null)
if (keys?.Count() > 1)
{ {
var sb = new StringBuilder(); return knownAliases[key];
sb.Append($"{normalizedUnit} could refer to any of");
foreach (var key in keys)
{
sb.Append($" {knownAliases[key]}");
}
return new(null, sb.ToString());
}
else if (keys.Count() == 1)
{
//for the canonical name.
return new(knownAliases[keys.First()], null);
} }
} }
if (normalizedUnit.EndsWith("es")) if (normalizedUnit.EndsWith("es"))
@ -177,7 +155,7 @@ namespace vassago.Conversion
{ {
return NormalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 1)); return NormalizeUnit(normalizedUnit.Substring(0, normalizedUnit.Length - 1));
} }
return new(null, "couldn't find unit"); return null;
} }
private static IEnumerable<string> exhaustiveBreadthFirst(string dest, IEnumerable<string> currentPath) private static IEnumerable<string> exhaustiveBreadthFirst(string dest, IEnumerable<string> currentPath)
{ {

3
Jenkinsfile vendored
View File

@ -59,7 +59,7 @@ pipeline {
{ {
sh """#!/bin/bash sh """#!/bin/bash
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf temp_deploy & mkdir -p temp_deploy' ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf temp_deploy & mkdir -p temp_deploy'
scp -i \"${PK}\" -r dist/ ${linuxServiceAccount_USR}@${env.targetHost}:temp_deploy scp -i \"${PK}\" -r dist ${linuxServiceAccount_USR}@${env.targetHost}:temp_deploy
""" """
} }
} }
@ -105,7 +105,6 @@ pipeline {
withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')]) withCredentials([sshUserPrivateKey(credentialsId: env.linuxServiceAccountID, keyFileVariable: 'PK')])
{ {
sh """#!/bin/bash sh """#!/bin/bash
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'cp dist oldgood-\$(mktemp -u XXXX)'
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv dist/appsettings.json appsettings.json' ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv dist/appsettings.json appsettings.json'
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf dist/ && shopt -s dotglob & mv temp_deploy/* dist/' ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'rm -rf dist/ && shopt -s dotglob & mv temp_deploy/* dist/'
ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv appsettings.json dist/appsettings.json' ssh -i \"${PK}\" -tt ${linuxServiceAccount_USR}@${targetHost} 'mv appsettings.json dist/appsettings.json'

View File

@ -15,7 +15,7 @@ namespace vassago.TwitchInterface;
internal class unifiedTwitchMessage internal class unifiedTwitchMessage
{ {
public unifiedTwitchMessage(ChatMessage chatMessage) { } public unifiedTwitchMessage(ChatMessage chatMessage){}
} }
public class TwitchInterface public class TwitchInterface
@ -142,15 +142,14 @@ public class TwitchInterface
private Account UpsertAccount(string username, Channel inChannel) private Account UpsertAccount(string username, Channel inChannel)
{ {
//Console.WriteLine($"upserting twitch account. username: {username}. inChannel: {inChannel?.Id}"); Console.WriteLine($"upserting twitch account. username: {username}. inChannel: {inChannel?.Id}");
var acc = Rememberer.SearchAccount(ui => ui.ExternalId == username && ui.SeenInChannel.ExternalId == inChannel.ExternalId); var acc = Rememberer.SearchAccount(ui => ui.ExternalId == username && ui.SeenInChannel.ExternalId == inChannel.ExternalId);
// Console.WriteLine($"upserting twitch account, retrieved {acc?.Id}."); Console.WriteLine($"upserting twitch account, retrieved {acc?.Id}.");
if (acc != null) if (acc != null)
{ {
Console.WriteLine($"acc's usser: {acc.IsUser?.Id}"); Console.WriteLine($"acc's usser: {acc.IsUser?.Id}");
} }
acc ??= new Account() acc ??= new Account() {
{
IsUser = Rememberer.SearchUser( IsUser = Rememberer.SearchUser(
u => u.Accounts.Any(a => a.ExternalId == username && a.Protocol == PROTOCOL)) u => u.Accounts.Any(a => a.ExternalId == username && a.Protocol == PROTOCOL))
?? new vassago.Models.User() ?? new vassago.Models.User()
@ -162,16 +161,16 @@ public class TwitchInterface
acc.Protocol = PROTOCOL; acc.Protocol = PROTOCOL;
acc.SeenInChannel = inChannel; acc.SeenInChannel = inChannel;
// Console.WriteLine($"we asked rememberer to search for acc's user. {acc.IsUser?.Id}"); Console.WriteLine($"we asked rememberer to search for acc's user. {acc.IsUser?.Id}");
// if (acc.IsUser != null) if (acc.IsUser != null)
// { {
// Console.WriteLine($"user has record of {acc.IsUser.Accounts?.Count ?? 0} accounts"); Console.WriteLine($"user has record of {acc.IsUser.Accounts?.Count ?? 0} accounts");
// } }
acc.IsUser ??= new vassago.Models.User() { Accounts = [acc] }; acc.IsUser ??= new vassago.Models.User() { Accounts = [acc] };
// if (inChannel.Users?.Count > 0) if (inChannel.Users?.Count > 0)
// { {
// Console.WriteLine($"channel has {inChannel.Users.Count} accounts"); Console.WriteLine($"channel has {inChannel.Users.Count} accounts");
// } }
Rememberer.RememberAccount(acc); Rememberer.RememberAccount(acc);
inChannel.Users ??= []; inChannel.Users ??= [];
if (!inChannel.Users.Contains(acc)) if (!inChannel.Users.Contains(acc))
@ -188,7 +187,7 @@ public class TwitchInterface
&& ci.Protocol == PROTOCOL); && ci.Protocol == PROTOCOL);
if (c == null) if (c == null)
{ {
// Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channelName}"); Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channelName}");
c = new Channel() c = new Channel()
{ {
Users = [] Users = []
@ -207,7 +206,7 @@ public class TwitchInterface
c = Rememberer.RememberChannel(c); c = Rememberer.RememberChannel(c);
var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId); var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId);
if (selfAccountInChannel == null) if(selfAccountInChannel == null)
{ {
selfAccountInChannel = UpsertAccount(selfAccountInProtocol.Username, c); selfAccountInChannel = UpsertAccount(selfAccountInProtocol.Username, c);
} }
@ -216,11 +215,11 @@ public class TwitchInterface
} }
private Channel UpsertDMChannel(string whisperWith) private Channel UpsertDMChannel(string whisperWith)
{ {
Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == $"w_{whisperWith}" Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == $"w_{whisperWith}"
&& ci.Protocol == PROTOCOL); && ci.Protocol == PROTOCOL);
if (c == null) if (c == null)
{ {
// Console.WriteLine($"couldn't find channel under protocol {PROTOCOL}, whisper with {whisperWith}"); Console.WriteLine($"couldn't find channel under protocol {PROTOCOL}, whisper with {whisperWith}");
c = new Channel() c = new Channel()
{ {
Users = [] Users = []
@ -234,16 +233,13 @@ public class TwitchInterface
c.Protocol = PROTOCOL; c.Protocol = PROTOCOL;
c.ParentChannel = protocolAsChannel; c.ParentChannel = protocolAsChannel;
c.SubChannels = c.SubChannels ?? new List<Channel>(); c.SubChannels = c.SubChannels ?? new List<Channel>();
c.SendMessage = (t) => c.SendMessage = (t) => { return Task.Run(() => {
{
return Task.Run(() =>
{
try try
{ {
client.SendWhisper(whisperWith, t); client.SendWhisper(whisperWith, t);
} }
catch (Exception e) catch(Exception e)
{ {
Console.Error.WriteLine(e); Console.Error.WriteLine(e);
} }
@ -253,7 +249,7 @@ public class TwitchInterface
c = Rememberer.RememberChannel(c); c = Rememberer.RememberChannel(c);
var selfAccountInChannel = c.Users.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId); var selfAccountInChannel = c.Users.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId);
if (selfAccountInChannel == null) if(selfAccountInChannel == null)
{ {
selfAccountInChannel = UpsertAccount(selfAccountInChannel.Username, c); selfAccountInChannel = UpsertAccount(selfAccountInChannel.Username, c);
} }

View File

@ -179,15 +179,6 @@ public static class Rememberer
dbAccessSemaphore.Release(); dbAccessSemaphore.Release();
return toReturn; return toReturn;
} }
public static List<UAC> SearchUACs(Expression<Func<UAC, bool>> predicate)
{
List<UAC> toReturn;
dbAccessSemaphore.Wait();
toReturn = db.UACs.Include(uac => uac.Users).Include(uac => uac.Channels).Include(uac => uac.AccountInChannels)
.Where(predicate).ToList();
dbAccessSemaphore.Release();
return toReturn;
}
public static void RememberUAC(UAC toRemember) public static void RememberUAC(UAC toRemember)
{ {
dbAccessSemaphore.Wait(); dbAccessSemaphore.Wait();

File diff suppressed because it is too large Load Diff

View File

@ -47,8 +47,8 @@
<None Update="appsettings.json"> <None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Include="wwwroot/**/*"> <Content Include="wwwroot/**/*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </Content>
</ItemGroup> </ItemGroup>
</Project> </Project>