Compare commits

...

2 Commits

Author SHA1 Message Date
423fe5cb96 more units for conversion 2023-12-05 21:23:08 -05:00
23e18f2028 complex channel types, some channels UI 2023-12-03 14:33:58 -05:00
11 changed files with 532 additions and 16 deletions

View File

@ -0,0 +1,37 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using vassago.Models;
namespace vassago.Controllers;
public class ChannelsController : Controller
{
private readonly ILogger<ChannelsController> _logger;
private readonly ChattingContext _db;
public ChannelsController(ILogger<ChannelsController> logger, ChattingContext db)
{
_logger = logger;
_db = db;
}
public async Task<IActionResult> Index(string searchString)
{
return _db.Channels != null ?
View(_db.Channels.Include(u => u.ParentChannel).ToList().OrderBy(c => c.LineageSummary)) :
Problem("Entity set '_db.Channels' is null.");
}
public async Task<IActionResult> Details(Guid id)
{
return _db.Channels != null ?
View(await _db.Channels.Include(u => u.ParentChannel).FirstAsync(u => u.Id == id)) :
Problem("Entity set '_db.Channels' is null.");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}

View File

@ -0,0 +1,349 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using vassago.Models;
#nullable disable
namespace vassago.Migrations
{
[DbContext(typeof(ChattingContext))]
[Migration("20231203193139_channeltype")]
partial class channeltype
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("vassago.Models.Account", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<string>("ExternalId")
.HasColumnType("text");
b.Property<Guid?>("FeaturePermissionId")
.HasColumnType("uuid");
b.Property<bool>("IsBot")
.HasColumnType("boolean");
b.Property<Guid?>("IsUserId")
.HasColumnType("uuid");
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<Guid?>("SeenInChannelId")
.HasColumnType("uuid");
b.Property<string>("Username")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("FeaturePermissionId");
b.HasIndex("IsUserId");
b.HasIndex("SeenInChannelId");
b.ToTable("Accounts");
});
modelBuilder.Entity("vassago.Models.Attachment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<byte[]>("Content")
.HasColumnType("bytea");
b.Property<string>("ContentType")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<decimal?>("ExternalId")
.HasColumnType("numeric(20,0)");
b.Property<string>("Filename")
.HasColumnType("text");
b.Property<Guid?>("MessageId")
.HasColumnType("uuid");
b.Property<int>("Size")
.HasColumnType("integer");
b.Property<string>("Source")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("MessageId");
b.ToTable("Attachments");
});
modelBuilder.Entity("vassago.Models.Channel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<int>("ChannelType")
.HasColumnType("integer");
b.Property<string>("DisplayName")
.HasColumnType("text");
b.Property<string>("ExternalId")
.HasColumnType("text");
b.Property<Guid?>("FeaturePermissionId")
.HasColumnType("uuid");
b.Property<Guid?>("ParentChannelId")
.HasColumnType("uuid");
b.Property<int?>("PermissionsId")
.HasColumnType("integer");
b.Property<string>("Protocol")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("FeaturePermissionId");
b.HasIndex("ParentChannelId");
b.HasIndex("PermissionsId");
b.ToTable("Channels");
});
modelBuilder.Entity("vassago.Models.ChannelPermissions", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("LewdnessFilterLevel")
.HasColumnType("integer");
b.Property<bool?>("LinksAllowed")
.HasColumnType("boolean");
b.Property<decimal?>("MaxAttachmentBytes")
.HasColumnType("numeric(20,0)");
b.Property<long?>("MaxTextChars")
.HasColumnType("bigint");
b.Property<int?>("MeannessFilterLevel")
.HasColumnType("integer");
b.Property<bool?>("ReactionsPossible")
.HasColumnType("boolean");
b.HasKey("Id");
b.ToTable("ChannelPermissions");
});
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Inheritable")
.HasColumnType("boolean");
b.Property<string>("InternalName")
.HasColumnType("text");
b.Property<int?>("InternalTag")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("FeaturePermissions");
});
modelBuilder.Entity("vassago.Models.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("ActedOn")
.HasColumnType("boolean");
b.Property<Guid?>("AuthorId")
.HasColumnType("uuid");
b.Property<Guid?>("ChannelId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("ExternalId")
.HasColumnType("text");
b.Property<bool>("MentionsMe")
.HasColumnType("boolean");
b.Property<string>("Protocol")
.HasColumnType("text");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("ChannelId");
b.ToTable("Messages");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("FeaturePermissionId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("FeaturePermissionId");
b.ToTable("Users");
});
modelBuilder.Entity("vassago.Models.Account", b =>
{
b.HasOne("vassago.Models.FeaturePermission", null)
.WithMany("RestrictedToAccounts")
.HasForeignKey("FeaturePermissionId");
b.HasOne("vassago.Models.User", "IsUser")
.WithMany("Accounts")
.HasForeignKey("IsUserId");
b.HasOne("vassago.Models.Channel", "SeenInChannel")
.WithMany("Users")
.HasForeignKey("SeenInChannelId");
b.Navigation("IsUser");
b.Navigation("SeenInChannel");
});
modelBuilder.Entity("vassago.Models.Attachment", b =>
{
b.HasOne("vassago.Models.Message", "Message")
.WithMany("Attachments")
.HasForeignKey("MessageId");
b.Navigation("Message");
});
modelBuilder.Entity("vassago.Models.Channel", b =>
{
b.HasOne("vassago.Models.FeaturePermission", null)
.WithMany("RestrictedToChannels")
.HasForeignKey("FeaturePermissionId");
b.HasOne("vassago.Models.Channel", "ParentChannel")
.WithMany("SubChannels")
.HasForeignKey("ParentChannelId");
b.HasOne("vassago.Models.ChannelPermissions", "Permissions")
.WithMany()
.HasForeignKey("PermissionsId");
b.Navigation("ParentChannel");
b.Navigation("Permissions");
});
modelBuilder.Entity("vassago.Models.Message", b =>
{
b.HasOne("vassago.Models.Account", "Author")
.WithMany()
.HasForeignKey("AuthorId");
b.HasOne("vassago.Models.Channel", "Channel")
.WithMany("Messages")
.HasForeignKey("ChannelId");
b.Navigation("Author");
b.Navigation("Channel");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.HasOne("vassago.Models.FeaturePermission", null)
.WithMany("RestrictedToUsers")
.HasForeignKey("FeaturePermissionId");
});
modelBuilder.Entity("vassago.Models.Channel", b =>
{
b.Navigation("Messages");
b.Navigation("SubChannels");
b.Navigation("Users");
});
modelBuilder.Entity("vassago.Models.FeaturePermission", b =>
{
b.Navigation("RestrictedToAccounts");
b.Navigation("RestrictedToChannels");
b.Navigation("RestrictedToUsers");
});
modelBuilder.Entity("vassago.Models.Message", b =>
{
b.Navigation("Attachments");
});
modelBuilder.Entity("vassago.Models.User", b =>
{
b.Navigation("Accounts");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace vassago.Migrations
{
/// <inheritdoc />
public partial class channeltype : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsDM",
table: "Channels");
migrationBuilder.AddColumn<int>(
name: "ChannelType",
table: "Channels",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ChannelType",
table: "Channels");
migrationBuilder.AddColumn<bool>(
name: "IsDM",
table: "Channels",
type: "boolean",
nullable: false,
defaultValue: false);
}
}
}

View File

@ -106,6 +106,9 @@ namespace vassago.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<int>("ChannelType")
.HasColumnType("integer");
b.Property<string>("DisplayName") b.Property<string>("DisplayName")
.HasColumnType("text"); .HasColumnType("text");
@ -115,9 +118,6 @@ namespace vassago.Migrations
b.Property<Guid?>("FeaturePermissionId") b.Property<Guid?>("FeaturePermissionId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<bool>("IsDM")
.HasColumnType("boolean");
b.Property<Guid?>("ParentChannelId") b.Property<Guid?>("ParentChannelId")
.HasColumnType("uuid"); .HasColumnType("uuid");

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord; using static vassago.Models.Enumerations;
public class Channel public class Channel
{ {
@ -13,13 +13,13 @@ public class Channel
public Guid Id { get; set; } public Guid Id { get; set; }
public string ExternalId { get; set; } public string ExternalId { get; set; }
public string DisplayName { get; set; } public string DisplayName { get; set; }
public bool IsDM { get; set; }
public ChannelPermissions Permissions { get; set; } public ChannelPermissions Permissions { get; set; }
public List<Channel> SubChannels { get; set; } public List<Channel> SubChannels { get; set; }
public Channel ParentChannel { get; set; } public Channel ParentChannel { get; set; }
public string Protocol { get; set; } public string Protocol { get; set; }
public List<Message> Messages { get; set; } public List<Message> Messages { get; set; }
public List<Account> Users { get; set; } public List<Account> Users { get; set; }
public ChannelType ChannelType {get; set;}
//public Dictionary<string, string> EmoteOverrides{get;set;} //public Dictionary<string, string> EmoteOverrides{get;set;}
[NonSerialized] [NonSerialized]
@ -62,4 +62,18 @@ public class Channel
return settings; return settings;
} }
} }
public string LineageSummary
{
get
{
if(this.ParentChannel != null)
{
return this.ParentChannel.LineageSummary + '/' + this.DisplayName;
}
else
{
return this.Protocol;
}
}
}
} }

View File

@ -27,6 +27,18 @@ public static class Enumerations
Unrestricted Unrestricted
} }
public enum ChannelType
{
[Description("Normal")]
Normal,
[Description("DM")]
DM,
[Description("protocol psuedo-channel")]
Protocol,
[Description("organizational psuedo-channel")]
OU
}
public static string GetDescription<T>(this T enumerationValue) public static string GetDescription<T>(this T enumerationValue)
where T : struct where T : struct
{ {

View File

@ -253,7 +253,7 @@ public class DiscordInterface
c.DisplayName = channel.Name; c.DisplayName = channel.Name;
c.ExternalId = channel.Id.ToString(); c.ExternalId = channel.Id.ToString();
c.IsDM = channel is IPrivateChannel; c.ChannelType = (channel is IPrivateChannel) ? vassago.Models.Enumerations.ChannelType.DM : vassago.Models.Enumerations.ChannelType.Normal;
c.Messages = c.Messages ?? new List<Message>(); c.Messages = c.Messages ?? new List<Message>();
c.Protocol = PROTOCOL; c.Protocol = PROTOCOL;
if (channel is IGuildChannel) if (channel is IGuildChannel)
@ -273,6 +273,13 @@ public class DiscordInterface
c.SubChannels = c.SubChannels ?? new List<Channel>(); c.SubChannels = c.SubChannels ?? new List<Channel>();
c.SendMessage = (t) => { return channel.SendMessageAsync(t); }; c.SendMessage = (t) => { return channel.SendMessageAsync(t); };
c.SendFile = (f, t) => { return channel.SendFileAsync(f, t); }; c.SendFile = (f, t) => { return channel.SendFileAsync(f, t); };
switch(c.ChannelType)
{
case vassago.Models.Enumerations.ChannelType.DM:
c.DisplayName = "DM: " + (channel as IPrivateChannel).Recipients?.FirstOrDefault(u => u.Id != client.CurrentUser.Id).Username;
break;
}
return c; return c;
} }
internal Channel UpsertChannel(IGuild channel) internal Channel UpsertChannel(IGuild channel)
@ -286,7 +293,7 @@ public class DiscordInterface
c.DisplayName = channel.Name; c.DisplayName = channel.Name;
c.ExternalId = channel.Id.ToString(); c.ExternalId = channel.Id.ToString();
c.IsDM = false; c.ChannelType = vassago.Models.Enumerations.ChannelType.Normal;
c.Messages = c.Messages ?? new List<Message>(); c.Messages = c.Messages ?? new List<Message>();
c.Protocol = protocolAsChannel.Protocol; c.Protocol = protocolAsChannel.Protocol;
c.ParentChannel = protocolAsChannel; c.ParentChannel = protocolAsChannel;

View File

@ -113,7 +113,7 @@ public class TwitchInterface
return; return;
} }
var m = UpsertMessage(e.WhisperMessage); var m = UpsertMessage(e.WhisperMessage);
m.Channel.IsDM = true; m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM;
m.MentionsMe = Regex.IsMatch(e.WhisperMessage.Message?.ToLower(), $"\\b@{e.WhisperMessage.BotUsername.ToLower()}\\b"); m.MentionsMe = Regex.IsMatch(e.WhisperMessage.Message?.ToLower(), $"\\b@{e.WhisperMessage.BotUsername.ToLower()}\\b");
_db.SaveChanges(); _db.SaveChanges();
@ -192,7 +192,7 @@ public class TwitchInterface
} }
c.DisplayName = channelName; c.DisplayName = channelName;
c.ExternalId = channelName; c.ExternalId = channelName;
c.IsDM = false; c.ChannelType = vassago.Models.Enumerations.ChannelType.Normal;
c.Messages = c.Messages ?? new List<Message>(); c.Messages = c.Messages ?? new List<Message>();
c.Protocol = PROTOCOL; c.Protocol = PROTOCOL;
c.ParentChannel = protocolAsChannel; c.ParentChannel = protocolAsChannel;
@ -211,7 +211,7 @@ public class TwitchInterface
} }
c.DisplayName = $"Whisper: {whisperWith}"; c.DisplayName = $"Whisper: {whisperWith}";
c.ExternalId = $"w_{whisperWith}"; c.ExternalId = $"w_{whisperWith}";
c.IsDM = true; c.ChannelType = vassago.Models.Enumerations.ChannelType.DM;
c.Messages = c.Messages ?? new List<Message>(); c.Messages = c.Messages ?? new List<Message>();
c.Protocol = PROTOCOL; c.Protocol = PROTOCOL;
c.ParentChannel = protocolAsChannel; c.ParentChannel = protocolAsChannel;
@ -267,7 +267,7 @@ public class TwitchInterface
m.Content = whisperMessage.Message; m.Content = whisperMessage.Message;
m.ExternalId = whisperMessage.MessageId; m.ExternalId = whisperMessage.MessageId;
m.Channel = UpsertDMChannel(whisperMessage.Username); m.Channel = UpsertDMChannel(whisperMessage.Username);
m.Channel.IsDM = true; m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM;
m.Author = UpsertAccount(whisperMessage.Username, m.Channel.Id); m.Author = UpsertAccount(whisperMessage.Username, m.Channel.Id);
m.Author.SeenInChannel = m.Channel; m.Author.SeenInChannel = m.Channel;

View File

@ -0,0 +1,42 @@
@model IEnumerable<Channel>
@{
ViewData["Title"] = "Channels";
}
<table class="table">
<thead>
<tr>
<th>
protocol
</th>
<th>type</th>
<th>
display name
</th>
<th>
Lineage
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td class="@item.Protocol">
<div class="protocol-icon">&nbsp;</div>
</td>
<td class="@item.ChannelType">
<div class="channel-type-icon">&nbsp;</div>
</td>
<td>
@Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
@item.LineageSummary
</td>
<td>
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
</td>
</tr>
}
</tbody>
</table>

View File

@ -204,6 +204,20 @@
"aliases": [ "aliases": [
"parsec" "parsec"
] ]
},
{
"canonical":"mi",
"aliases": [
"mile",
"miles"
]
},
{
"canonical":"blue whale length",
"aliases": [
"bwl",
"whales"
]
} }
], ],
"linearPairs":[ "linearPairs":[
@ -226,6 +240,7 @@
{"item1":"AU", "item2":"ly", "factor": 0.0000158125}, {"item1":"AU", "item2":"ly", "factor": 0.0000158125},
{"item1":"ly", "item2":"km", "factor": 946070000000}, {"item1":"ly", "item2":"km", "factor": 946070000000},
{"item1":"pc", "item2":"AU", "factor":206266.3}, {"item1":"pc", "item2":"AU", "factor":206266.3},
{"item1":"blue whale length", "item2": "m", "factor": 29.9},
{"item1":"floz", "item2":"mL", "factor":29.57344}, {"item1":"floz", "item2":"mL", "factor":29.57344},
{"item1":"L", "item2":"mL", "factor":1000}, {"item1":"L", "item2":"mL", "factor":1000},
@ -242,14 +257,14 @@
{"item1":"gal", "item2":"floz", "factor":128}, {"item1":"gal", "item2":"floz", "factor":128},
{"item1":"gal", "item2":"qt", "factor":4}, {"item1":"gal", "item2":"qt", "factor":4},
{"item1":"acre", "item2":"yd^2", "factor":4840}, {"item1":"acre", "item2":"yd^2", "factor":4840},
{"item1":"yd^2", "item2":"m^2", "factor":0.836127}, {"item1":"yd^2", "item2":"m^2", "factor":0.836127},
{"item1":"mph", "item2":"knot", "factor":0.868976}, {"item1":"mph", "item2":"knot", "factor":0.868976},
{"item1":"mph", "item2":"kph", "factor":1.609343550606653}, {"item1":"mph", "item2":"kph", "factor":1.609343550606653},
{"item1":"kPa", "item2":"Pa", "factor":1000}, {"item1":"kPa", "item2":"Pa", "factor":1000},
{"item1":"Nm^2", "item2":"Pa", "factor":1}, {"item1":"Nm^2", "item2":"Pa", "factor":1},
{"item1":"Pa", "item2":"bar", "factor":100}, {"item1":"Pa", "item2":"bar", "factor":100},

View File

@ -20,15 +20,15 @@ html {
body { body {
margin-bottom: 60px; margin-bottom: 60px;
} }
.account .protocol-icon{ .protocol-icon{
display:inline-block; display:inline-block;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-size: 32px; background-size: 32px;
} }
.account.discord .protocol-icon{ .discord .protocol-icon{
background-image: url("../imgs/discord_logo1600.png"); background-image: url("../imgs/discord_logo1600.png");
} }
.account.twitch .protocol-icon{ .twitch .protocol-icon{
background-image: url("../imgs/twitch.png"); background-image: url("../imgs/twitch.png");
} }