Merge pull request 'Messaging System' (#2) from messaging into master

Reviewed-on: https://gitea.milenia.local.alanmoon.net/Moonbase/jumpstart-games-reduxed/pulls/2
This commit is contained in:
Alan Moon 2025-03-07 18:19:53 -08:00
commit 2e70d89ddb
18 changed files with 4011 additions and 12 deletions

View File

@ -1,39 +1,86 @@
using Microsoft.AspNetCore.Mvc;
using sodoff.Attributes;
using sodoff.Model;
using sodoff.Schema;
using sodoff.Services;
using sodoff.Util;
namespace sodoff.Controllers.Common;
public class MessagingController : Controller {
private readonly MessagingService messagingService;
private readonly DBContext ctx;
public MessagingController(MessagingService messagingService, DBContext ctx)
{
this.messagingService = messagingService;
this.ctx = ctx;
}
[HttpPost]
[Produces("application/xml")]
[Route("MessagingWebService.asmx/GetUserMessageQueue")]
public ArrayOfMessageInfo? GetUserMessageQueue() {
// TODO: this is a placeholder
return null;
[VikingSession]
public ArrayOfMessageInfo? GetUserMessageQueue(Viking viking, [FromForm] bool showOldMessages, [FromForm] bool showDeletedMessages) {
return messagingService.ConstructUserMessageInfoArray(viking, showOldMessages, showDeletedMessages);
}
[HttpPost]
[Produces("application/xml")]
[Route("MessagingWebService.asmx/SendMessage")]
public IActionResult SendMessage() {
// TODO: this is a placeholder
return Ok(false);
[VikingSession]
public IActionResult SendMessage(Viking viking, [FromForm] Guid toUser, [FromForm] int messageID, [FromForm] string data) {
// find viking to send to
Viking? toViking = ctx.Vikings.FirstOrDefault(e => e.Uid == toUser);
if (toViking == null) return Ok(false);
// clients (at least older ones) don't send what typeID the message is, its encoded in data
ArrayOfKeyValuePairOfStringString arrayOfKeyValuePairOfStringString = XmlUtil.DeserializeXml<ArrayOfKeyValuePairOfStringString>(data);
MessageTypeID typeID = MessageTypeID.Unknown;
string typeText = "";
switch(arrayOfKeyValuePairOfStringString.KeyValuePairOfStringString[0]?.Value)
{
case "Drawing":
typeID = MessageTypeID.GreetingCard;
typeText = "Card";
break;
case "Photo":
typeID = MessageTypeID.Photo;
typeText = "PhotoBomb";
break;
}
var msg = messagingService.AddMessageToViking(viking, toViking, MessageType.Data, typeID, MessageLevel.WhiteList, data, "[[Line1]]=[[{{BuddyUserName}}]] has sent you a " + typeText + "!", "[[Line1]]=[[{{BuddyUserName}}]] has sent you a " + typeText + "!");
if (msg != null) return Ok(true);
else return Ok(false);
}
[HttpPost]
[Produces("application/xml")]
[Route("MessagingWebService.asmx/SaveMessage")]
public IActionResult SaveMessage() {
// TODO: this is a placeholder
return Ok(false);
public IActionResult SaveMessage([FromForm] int userMessageQueueId, [FromForm] bool isNew, [FromForm] bool IsDeleted) {
var updatedMessage = messagingService.UpdateMessageByQueueID(userMessageQueueId, isNew, IsDeleted);
if (updatedMessage != null) return Ok(true);
else return Ok(false);
}
[HttpPost]
[Produces("application/xml")]
[Route("MessageWebService.asmx/GetCombinedListMessage")]
public IActionResult GetCombinedListMessage()
public ArrayOfCombinedListMessage? GetCombinedListMessage([FromForm] Guid userId)
{
// TODO - placeholder
return Ok(new ArrayOfMessageInfo());
// find viking
Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Uid == userId);
if (viking != null) return messagingService.ConstructCombinedMessageArray(viking);
else return new ArrayOfCombinedListMessage();
}
[HttpPost]
[Produces("application/xml")]
[Route("MessageWebService.asmx/RemoveMessageFromBoard")]
public IActionResult RemoveMessageFromBoard([FromForm] int messageID)
{
messagingService.RemoveMessage(messageID);
return Ok(true);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,971 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace sodoff.Migrations
{
/// <inheritdoc />
public partial class IntialCreatePostDesign : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
GroupID = table.Column<Guid>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
Color = table.Column<string>(type: "TEXT", nullable: false),
Logo = table.Column<string>(type: "TEXT", nullable: false),
ApiKey = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "RatingRanks",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CategoryID = table.Column<int>(type: "INTEGER", nullable: false),
RatedEntityID = table.Column<int>(type: "INTEGER", nullable: true),
RatedUserID = table.Column<string>(type: "TEXT", nullable: true),
Rank = table.Column<int>(type: "INTEGER", nullable: false),
RatingAverage = table.Column<float>(type: "REAL", nullable: false),
UpdateDate = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RatingRanks", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<Guid>(type: "TEXT", nullable: false),
Email = table.Column<string>(type: "TEXT", nullable: false),
Username = table.Column<string>(type: "TEXT", nullable: false),
Password = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AchievementPoints",
columns: table => new
{
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
Value = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AchievementPoints", x => new { x.VikingId, x.Type });
});
migrationBuilder.CreateTable(
name: "AchievementTaskState",
columns: table => new
{
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
TaskId = table.Column<int>(type: "INTEGER", nullable: false),
Points = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AchievementTaskState", x => new { x.TaskId, x.VikingId });
});
migrationBuilder.CreateTable(
name: "Bans",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
UserBanType = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
ExpiresOn = table.Column<DateTime>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Bans", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Dragons",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
EntityId = table.Column<Guid>(type: "TEXT", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
RaisedPetData = table.Column<string>(type: "TEXT", nullable: true),
PetXP = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Dragons", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Vikings",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Uid = table.Column<Guid>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
UserId = table.Column<Guid>(type: "TEXT", nullable: false),
AvatarSerialized = table.Column<string>(type: "TEXT", nullable: true),
SelectedDragonId = table.Column<int>(type: "INTEGER", nullable: true),
CreationDate = table.Column<DateTime>(type: "TEXT", nullable: true),
BirthDate = table.Column<DateTime>(type: "TEXT", nullable: true),
Gender = table.Column<int>(type: "INTEGER", nullable: true),
GameVersion = table.Column<uint>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Vikings", x => x.Id);
table.ForeignKey(
name: "FK_Vikings_Dragons_SelectedDragonId",
column: x => x.SelectedDragonId,
principalTable: "Dragons",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Vikings_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GameData",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
GameId = table.Column<int>(type: "INTEGER", nullable: false),
Difficulty = table.Column<int>(type: "INTEGER", nullable: false),
GameLevel = table.Column<int>(type: "INTEGER", nullable: false),
DatePlayed = table.Column<DateTime>(type: "TEXT", nullable: false),
IsMultiplayer = table.Column<bool>(type: "INTEGER", nullable: false),
Win = table.Column<bool>(type: "INTEGER", nullable: false),
Loss = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GameData", x => x.Id);
table.ForeignKey(
name: "FK_GameData_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupViking",
columns: table => new
{
GroupsId = table.Column<int>(type: "INTEGER", nullable: false),
VikingsId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupViking", x => new { x.GroupsId, x.VikingsId });
table.ForeignKey(
name: "FK_GroupViking_Groups_GroupsId",
column: x => x.GroupsId,
principalTable: "Groups",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupViking_Vikings_VikingsId",
column: x => x.VikingsId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Images",
columns: table => new
{
ImageType = table.Column<string>(type: "TEXT", nullable: false),
ImageSlot = table.Column<int>(type: "INTEGER", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
ImageData = table.Column<string>(type: "TEXT", nullable: true),
TemplateName = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Images", x => new { x.ImageType, x.ImageSlot, x.VikingId });
table.ForeignKey(
name: "FK_Images_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "InventoryItems",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ItemId = table.Column<int>(type: "INTEGER", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
StatsSerialized = table.Column<string>(type: "TEXT", nullable: true),
AttributesSerialized = table.Column<string>(type: "TEXT", nullable: true),
Quantity = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_InventoryItems", x => x.Id);
table.ForeignKey(
name: "FK_InventoryItems_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Messages",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
ToVikingId = table.Column<int>(type: "INTEGER", nullable: false),
QueueID = table.Column<int>(type: "INTEGER", nullable: false),
ConversationID = table.Column<int>(type: "INTEGER", nullable: true),
ParentMessageId = table.Column<int>(type: "INTEGER", nullable: true),
MessageType = table.Column<int>(type: "INTEGER", nullable: true),
MessageTypeID = table.Column<int>(type: "INTEGER", nullable: true),
MessageLevel = table.Column<int>(type: "INTEGER", nullable: false),
Data = table.Column<string>(type: "TEXT", nullable: true),
MemberMessage = table.Column<string>(type: "TEXT", nullable: true),
NonMemberMessage = table.Column<string>(type: "TEXT", nullable: true),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
LastUpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: true),
IsDeleted = table.Column<bool>(type: "INTEGER", nullable: false),
IsNew = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Messages", x => x.Id);
table.ForeignKey(
name: "FK_Messages_Messages_ParentMessageId",
column: x => x.ParentMessageId,
principalTable: "Messages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Messages_Vikings_ToVikingId",
column: x => x.ToVikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Messages_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "MissionStates",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
MissionId = table.Column<int>(type: "INTEGER", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
MissionStatus = table.Column<int>(type: "INTEGER", nullable: false),
UserAccepted = table.Column<bool>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_MissionStates", x => x.Id);
table.ForeignKey(
name: "FK_MissionStates_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "MMORoles",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
Role = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MMORoles", x => x.Id);
table.ForeignKey(
name: "FK_MMORoles_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Neighborhoods",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
Slot0 = table.Column<Guid>(type: "TEXT", nullable: false),
Slot1 = table.Column<Guid>(type: "TEXT", nullable: false),
Slot2 = table.Column<Guid>(type: "TEXT", nullable: false),
Slot3 = table.Column<Guid>(type: "TEXT", nullable: false),
Slot4 = table.Column<Guid>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Neighborhoods", x => x.Id);
table.ForeignKey(
name: "FK_Neighborhoods_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PairData",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
PairId = table.Column<int>(type: "INTEGER", nullable: false),
UserId = table.Column<Guid>(type: "TEXT", nullable: true),
VikingId = table.Column<int>(type: "INTEGER", nullable: true),
DragonId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PairData", x => x.Id);
table.ForeignKey(
name: "FK_PairData_Dragons_DragonId",
column: x => x.DragonId,
principalTable: "Dragons",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PairData_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PairData_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Parties",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Location = table.Column<string>(type: "TEXT", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
ExpirationDate = table.Column<DateTime>(type: "TEXT", nullable: false),
PrivateParty = table.Column<bool>(type: "INTEGER", nullable: true),
LocationIconAsset = table.Column<string>(type: "TEXT", nullable: false),
AssetBundle = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Parties", x => x.Id);
table.ForeignKey(
name: "FK_Parties_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ProfileAnswers",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
QuestionID = table.Column<int>(type: "INTEGER", nullable: false),
AnswerID = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProfileAnswers", x => x.Id);
table.ForeignKey(
name: "FK_ProfileAnswers_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Ratings",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
RankId = table.Column<int>(type: "INTEGER", nullable: false),
Value = table.Column<int>(type: "INTEGER", nullable: false),
Date = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Ratings", x => x.Id);
table.ForeignKey(
name: "FK_Ratings_RatingRanks_RankId",
column: x => x.RankId,
principalTable: "RatingRanks",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Ratings_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Rooms",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoomId = table.Column<string>(type: "TEXT", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Rooms", x => x.Id);
table.ForeignKey(
name: "FK_Rooms_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "SavedData",
columns: table => new
{
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
SaveId = table.Column<uint>(type: "INTEGER", nullable: false),
SerializedData = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_SavedData", x => new { x.VikingId, x.SaveId });
table.ForeignKey(
name: "FK_SavedData_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "SceneData",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
SceneName = table.Column<string>(type: "TEXT", nullable: false),
XmlData = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SceneData", x => x.Id);
table.ForeignKey(
name: "FK_SceneData_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sessions",
columns: table => new
{
ApiToken = table.Column<Guid>(type: "TEXT", nullable: false),
UserId = table.Column<Guid>(type: "TEXT", nullable: true),
VikingId = table.Column<int>(type: "INTEGER", nullable: true),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Sessions", x => x.ApiToken);
table.ForeignKey(
name: "FK_Sessions_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Sessions_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "TaskStatuses",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false),
MissionId = table.Column<int>(type: "INTEGER", nullable: false),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
Payload = table.Column<string>(type: "TEXT", nullable: true),
Completed = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TaskStatuses", x => new { x.Id, x.VikingId, x.MissionId });
table.ForeignKey(
name: "FK_TaskStatuses_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "UserBadgesCompleted",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
BadgeId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserBadgesCompleted", x => x.Id);
table.ForeignKey(
name: "FK_UserBadgesCompleted_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "UserMissionData",
columns: table => new
{
VikingId = table.Column<int>(type: "INTEGER", nullable: false),
WorldId = table.Column<int>(type: "INTEGER", nullable: false),
MissionId = table.Column<int>(type: "INTEGER", nullable: false),
StepId = table.Column<int>(type: "INTEGER", nullable: false),
TaskId = table.Column<int>(type: "INTEGER", nullable: false),
IsCompleted = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserMissionData", x => new { x.VikingId, x.WorldId, x.MissionId });
table.ForeignKey(
name: "FK_UserMissionData_Vikings_VikingId",
column: x => x.VikingId,
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GameDataPairs",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
GameDataId = table.Column<int>(type: "INTEGER", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Value = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GameDataPairs", x => x.Id);
table.ForeignKey(
name: "FK_GameDataPairs_GameData_GameDataId",
column: x => x.GameDataId,
principalTable: "GameData",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Pairs",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Key = table.Column<string>(type: "TEXT", nullable: false),
Value = table.Column<string>(type: "TEXT", nullable: false),
MasterId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Pairs", x => x.Id);
table.ForeignKey(
name: "FK_Pairs_PairData_MasterId",
column: x => x.MasterId,
principalTable: "PairData",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RoomItems",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoomId = table.Column<int>(type: "INTEGER", nullable: false),
RoomItemData = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RoomItems", x => x.Id);
table.ForeignKey(
name: "FK_RoomItems_Rooms_RoomId",
column: x => x.RoomId,
principalTable: "Rooms",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AchievementTaskState_VikingId",
table: "AchievementTaskState",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Bans_VikingId",
table: "Bans",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Dragons_VikingId",
table: "Dragons",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_GameData_VikingId",
table: "GameData",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_GameDataPairs_GameDataId",
table: "GameDataPairs",
column: "GameDataId");
migrationBuilder.CreateIndex(
name: "IX_GroupViking_VikingsId",
table: "GroupViking",
column: "VikingsId");
migrationBuilder.CreateIndex(
name: "IX_Images_VikingId",
table: "Images",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_InventoryItems_VikingId",
table: "InventoryItems",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Messages_ParentMessageId",
table: "Messages",
column: "ParentMessageId");
migrationBuilder.CreateIndex(
name: "IX_Messages_ToVikingId",
table: "Messages",
column: "ToVikingId");
migrationBuilder.CreateIndex(
name: "IX_Messages_VikingId",
table: "Messages",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_MissionStates_VikingId",
table: "MissionStates",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_MMORoles_VikingId",
table: "MMORoles",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Neighborhoods_VikingId",
table: "Neighborhoods",
column: "VikingId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PairData_DragonId",
table: "PairData",
column: "DragonId");
migrationBuilder.CreateIndex(
name: "IX_PairData_UserId",
table: "PairData",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_PairData_VikingId",
table: "PairData",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Pairs_MasterId",
table: "Pairs",
column: "MasterId");
migrationBuilder.CreateIndex(
name: "IX_Parties_VikingId",
table: "Parties",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_ProfileAnswers_VikingId",
table: "ProfileAnswers",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Ratings_RankId",
table: "Ratings",
column: "RankId");
migrationBuilder.CreateIndex(
name: "IX_Ratings_VikingId",
table: "Ratings",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_RoomItems_RoomId",
table: "RoomItems",
column: "RoomId");
migrationBuilder.CreateIndex(
name: "IX_Rooms_VikingId",
table: "Rooms",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_SceneData_VikingId",
table: "SceneData",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Sessions_UserId",
table: "Sessions",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Sessions_VikingId",
table: "Sessions",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_TaskStatuses_VikingId",
table: "TaskStatuses",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_UserBadgesCompleted_VikingId",
table: "UserBadgesCompleted",
column: "VikingId");
migrationBuilder.CreateIndex(
name: "IX_Vikings_SelectedDragonId",
table: "Vikings",
column: "SelectedDragonId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Vikings_Uid",
table: "Vikings",
column: "Uid");
migrationBuilder.CreateIndex(
name: "IX_Vikings_UserId",
table: "Vikings",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_AchievementPoints_Vikings_VikingId",
table: "AchievementPoints",
column: "VikingId",
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_AchievementTaskState_Vikings_VikingId",
table: "AchievementTaskState",
column: "VikingId",
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Bans_Vikings_VikingId",
table: "Bans",
column: "VikingId",
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Dragons_Vikings_VikingId",
table: "Dragons",
column: "VikingId",
principalTable: "Vikings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Dragons_Vikings_VikingId",
table: "Dragons");
migrationBuilder.DropTable(
name: "AchievementPoints");
migrationBuilder.DropTable(
name: "AchievementTaskState");
migrationBuilder.DropTable(
name: "Bans");
migrationBuilder.DropTable(
name: "GameDataPairs");
migrationBuilder.DropTable(
name: "GroupViking");
migrationBuilder.DropTable(
name: "Images");
migrationBuilder.DropTable(
name: "InventoryItems");
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable(
name: "MissionStates");
migrationBuilder.DropTable(
name: "MMORoles");
migrationBuilder.DropTable(
name: "Neighborhoods");
migrationBuilder.DropTable(
name: "Pairs");
migrationBuilder.DropTable(
name: "Parties");
migrationBuilder.DropTable(
name: "ProfileAnswers");
migrationBuilder.DropTable(
name: "Ratings");
migrationBuilder.DropTable(
name: "RoomItems");
migrationBuilder.DropTable(
name: "SavedData");
migrationBuilder.DropTable(
name: "SceneData");
migrationBuilder.DropTable(
name: "Sessions");
migrationBuilder.DropTable(
name: "TaskStatuses");
migrationBuilder.DropTable(
name: "UserBadgesCompleted");
migrationBuilder.DropTable(
name: "UserMissionData");
migrationBuilder.DropTable(
name: "GameData");
migrationBuilder.DropTable(
name: "Groups");
migrationBuilder.DropTable(
name: "PairData");
migrationBuilder.DropTable(
name: "RatingRanks");
migrationBuilder.DropTable(
name: "Rooms");
migrationBuilder.DropTable(
name: "Vikings");
migrationBuilder.DropTable(
name: "Dragons");
migrationBuilder.DropTable(
name: "Users");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@ public class DBContext : DbContext {
public DbSet<UserMissionData> UserMissionData { get; set; } = null!;
public DbSet<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
public DbSet<UserBan> Bans { get; set; } = null!;
public DbSet<Message> Messages { get; set; } = null!;
private readonly IOptions<ApiServerConfig> config;
@ -160,6 +161,12 @@ public class DBContext : DbContext {
builder.Entity<Viking>().HasMany(v => v.UserBans)
.WithOne(r => r.Viking);
builder.Entity<Viking>().HasMany(v => v.MessageBoard)
.WithOne(r => r.ToViking);
builder.Entity<Viking>().HasMany(v => v.MessagesMade)
.WithOne(r => r.Viking);
// Dragons
builder.Entity<Dragon>().HasOne(d => d.Viking)
.WithMany(e => e.Dragons)
@ -310,5 +317,19 @@ public class DBContext : DbContext {
builder.Entity<UserBan>().HasOne(r => r.Viking)
.WithMany(e => e.UserBans)
.HasForeignKey(e => e.VikingId);
// Messages
builder.Entity<Message>().HasOne(r => r.Viking)
.WithMany(e => e.MessagesMade)
.HasForeignKey(e => e.VikingId);
builder.Entity<Message>().HasOne(r => r.ToViking)
.WithMany(e => e.MessageBoard)
.HasForeignKey(e => e.ToVikingId);
builder.Entity<Message>().HasMany(e => e.Replies)
.WithOne(e => e.ParentMessage)
.HasForeignKey(e => e.ParentMessageId)
.OnDelete(DeleteBehavior.Cascade);
}
}

38
src/Model/Message.cs Normal file
View File

@ -0,0 +1,38 @@
using System;
using System.ComponentModel.DataAnnotations;
using sodoff.Schema;
namespace sodoff.Model;
public class Message
{
[Key]
public int Id { get; set; }
public int VikingId { get; set; }
public int ToVikingId { get; set; }
public int QueueID { get; set; }
public int? ConversationID { get; set; }
public int? ParentMessageId { get; set; }
public MessageType? MessageType { get; set; }
public MessageTypeID? MessageTypeID { get; set; }
public MessageLevel MessageLevel { get; set; }
public string? Data { get; set; }
public string? MemberMessage { get; set; }
public string? NonMemberMessage { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? LastUpdatedAt { get; set; }
public bool IsDeleted { get; set; }
public bool IsNew { get; set; }
public virtual Viking? Viking { get; set; }
public virtual Viking? ToViking { get; set; }
public virtual Message? ParentMessage { get; set; }
public virtual ICollection<Message> Replies { get; set; } = null!;
}

View File

@ -45,6 +45,8 @@ public class Viking {
public virtual ICollection<UserMissionData> UserMissions { get; set; } = null!;
public virtual ICollection<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
public virtual ICollection<UserBan> UserBans { get; set; } = null!;
public virtual ICollection<Message> MessageBoard { get; set; } = null!;
public virtual ICollection<Message> MessagesMade { get; set; } = null!;
public DateTime? CreationDate { get; set; }
public DateTime? BirthDate { get; set; }

View File

@ -41,6 +41,7 @@ builder.Services.AddScoped<GameDataService>();
builder.Services.AddScoped<ProfileService>();
builder.Services.AddScoped<NeighborhoodService>();
builder.Services.AddScoped<ModerationService>();
builder.Services.AddScoped<MessagingService>();
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");

View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "ArrayOfCombinedListMessage")]
[Serializable]
public class ArrayOfCombinedListMessage
{
[XmlElement("CombinedListMessage")]
public CombinedListMessage[] CombinedListMessage;
}
}

View File

@ -0,0 +1,11 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "ArrayOfKeyValuePairOfStringString")]
public class ArrayOfKeyValuePairOfStringString
{
[XmlElement(ElementName = "KeyValuePairOfStringString")]
public KeyValuePairOfStringString[]? KeyValuePairOfStringString { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[Serializable]
public class CombinedListMessage
{
[XmlElement(ElementName = "MessageType")]
public int MessageType;
[XmlElement(ElementName = "MessageDate")]
public DateTime MessageDate;
[XmlElement(ElementName = "Body", IsNullable = true)]
public string MessageBody;
}
}

View File

@ -0,0 +1,13 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[Serializable]
public class KeyValuePairOfStringString
{
[XmlElement(ElementName = "Key")]
public string? Key { get; set; }
[XmlElement(ElementName = "Value")]
public string? Value { get; set; }
}
}

39
src/Schema/Message.cs Normal file
View File

@ -0,0 +1,39 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "Message")]
[Serializable]
public class Message
{
[XmlElement(ElementName = "MessageID")]
public int? MessageID;
[XmlElement(ElementName = "Creator")]
public string Creator;
[XmlElement(ElementName = "MessageLevel")]
public MessageLevel MessageLevel;
[XmlElement(ElementName = "MessageType")]
public MessageType MessageType;
[XmlElement(ElementName = "Content", IsNullable = true)]
public string? Content;
[XmlElement(ElementName = "ReplyToMessageID", IsNullable = true)]
public int? ReplyToMessageID;
[XmlElement(ElementName = "CreateTime")]
public DateTime CreateTime;
[XmlElement(ElementName = "UpdateDate", IsNullable = true)]
public DateTime? UpdateDate;
[XmlElement(ElementName = "ConversationID")]
public int ConversationID;
[XmlElement(ElementName = "DisplayAttribute", IsNullable = true)]
public string? DisplayAttribute;
}
}

View File

@ -0,0 +1,8 @@
namespace sodoff.Schema
{
public enum MessageLevel
{
Canned = 1,
WhiteList
}
}

11
src/Schema/MessageType.cs Normal file
View File

@ -0,0 +1,11 @@
namespace sodoff.Schema
{
public enum MessageType
{
Chat = 1,
Post = 2,
Data = 3,
Challenge = 4,
Announcement = 5
}
}

View File

@ -0,0 +1,28 @@
namespace sodoff.Schema
{
public enum MessageTypeID
{
Unknown = 0,
Billboard = 1,
Dialog = 2,
Notification = 3,
Rank = 4,
BuddyList = 5,
Jumpstar = 6,
SpaAdventureGift = 7,
PrizeCode = 8,
Achievement = 9,
Messaging = 10,
SocialRank = 11,
MuttCare = 12,
Mission = 13,
ChallengeWon = 14,
InviteFriend = 15,
Gifts = 19,
FriendReward = 20,
ThreadUpdate = 21,
Photo = 22,
GreetingCard = 23,
ProfileSelection = 24
}
}

View File

@ -0,0 +1,265 @@
using System;
using Microsoft.EntityFrameworkCore;
using sodoff.Model;
using sodoff.Schema;
using sodoff.Util;
using ZstdSharp.Unsafe;
namespace sodoff.Services;
public class MessagingService
{
private readonly DBContext ctx;
public MessagingService(DBContext ctx)
{
this.ctx = ctx;
}
public Model.Message AddMessageToViking(Viking viking, Viking toViking, MessageType messageType, MessageTypeID messageTypeID, MessageLevel messageLevel, string data, string memberMessage = "", string nonMemberMessage = "", bool IsNew = true, bool IsDeleted = false, bool isReply = false, int parentMessageId = 0)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// for generating ConversationId and QueueId
Random rnd = new Random();
// construct message
Model.Message message = new Model.Message
{
Viking = viking,
VikingId = viking.Id,
ToViking = toViking,
ToVikingId = toViking.Id,
QueueID = rnd.Next(1000, 9999),
ConversationID = rnd.Next(1000, 9999),
MessageType = messageType,
MessageTypeID = messageTypeID,
MessageLevel = messageLevel,
Data = data,
MemberMessage = memberMessage,
NonMemberMessage = nonMemberMessage,
CreatedAt = now,
LastUpdatedAt = now,
IsDeleted = IsDeleted,
IsNew = IsNew
};
if (isReply)
{
// get message this is in reply to
Model.Message? messageToReplyTo = ctx.Messages.FirstOrDefault(e => e.Id == parentMessageId);
if (messageToReplyTo != null)
{
message.ParentMessage = messageToReplyTo;
message.ParentMessageId = messageToReplyTo.Id;
message.ConversationID = messageToReplyTo.ConversationID;
} else throw new InvalidOperationException("Tried To Reply To A Message That Doesn't Exist");
}
// add message to database
ctx.Messages.Add(message);
ctx.SaveChanges();
// return constructed message
return message;
}
public void RemoveMessage(int id)
{
// find message
Model.Message? message = ctx.Messages.FirstOrDefault(e => e.Id == id);
if (message != null)
{
// remove it
ctx.Messages.Remove(message);
ctx.SaveChanges();
} else throw new InvalidOperationException("Tried To Delete A Message That Doesn't Exist");
}
public Model.Message? UpdateMessageByQueueID(int queueId, bool isNew, bool IsDeleted)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// find message
Model.Message? message = ctx.Messages.FirstOrDefault(e => e.QueueID == queueId);
if (message != null)
{
// set params (TODO - figure out what else the clients update in messages)
message.IsNew = isNew;
message.IsDeleted = IsDeleted;
message.LastUpdatedAt = now;
return message;
} else return null;
}
public ArrayOfCombinedListMessage ConstructCombinedMessageArray(Viking viking)
{
// get all messages in viking board
List<Model.Message> messages = ctx.Messages.Where(e => e.ToVikingId == viking.Id).ToList();
List<CombinedListMessage> combinedListMessages = new List<CombinedListMessage>();
ArrayOfCombinedListMessage response = new ArrayOfCombinedListMessage();
foreach(var message in messages)
{
if (message.IsDeleted)
{
ctx.Messages.Remove(message);
continue;
}
Viking? msgAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == message.VikingId) ?? new Viking();
// construct a CombinedListMessage based on Model.Message
CombinedListMessage clm = new CombinedListMessage
{
MessageType = (int?)message.MessageType ?? 0,
MessageDate = message.CreatedAt
};
// if type id is messaging, use Schema.Message, otherwise treat it as Schema.MessageInfo
if (message.MessageTypeID == MessageTypeID.Messaging)
{
clm.MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = message.Id,
ConversationID = message.ConversationID ?? 0,
ReplyToMessageID = message.ParentMessageId,
Creator = msgAuthor.Uid.ToString() ?? "Ghost",
CreateTime = message.CreatedAt,
UpdateDate = message.LastUpdatedAt,
MessageType = message.MessageType.Value,
MessageLevel = message.MessageLevel,
Content = message.Data ?? "No Data Found In This Message. This Might Be An Error.",
DisplayAttribute = "C=White" // still having it always white :)
});
} else if (message.Data.StartsWith("<?xml"))
{
// xml data needs to be parsed and put in the right format for response
ArrayOfKeyValuePairOfStringString arrayOfKVP = XmlUtil.DeserializeXml<ArrayOfKeyValuePairOfStringString>(message.Data);
string data = "";
List<KeyValuePairOfStringString> pairList = new List<KeyValuePairOfStringString>();
for(int i = 0; i < arrayOfKVP.KeyValuePairOfStringString.Length; i++)
{
pairList.Add(arrayOfKVP.KeyValuePairOfStringString[i]);
}
foreach(KeyValuePairOfStringString pair in pairList)
{
data = data + $"[[{pair.Key}]]=[[{pair.Value}]]";
}
clm.MessageBody = XmlUtil.SerializeXml(new MessageInfo
{
UserMessageQueueID = message.QueueID,
MessageID = message.Id,
MessageTypeID = (int?)message.MessageTypeID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MemberMessage = message.MemberMessage ?? "NoData",
NonMemberMessage = message.NonMemberMessage ?? "NoData",
Data = data
});
} else
{
clm.MessageBody = XmlUtil.SerializeXml(new MessageInfo
{
UserMessageQueueID = message.QueueID,
MessageID = message.Id,
MessageTypeID = (int?)message.MessageTypeID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MemberMessage = message.MemberMessage ?? "NoData",
NonMemberMessage = message.NonMemberMessage ?? "NoData",
Data = message.Data
});
}
// add clm to list
combinedListMessages.Add(clm);
// ensure all replies are included in response
foreach(var reply in message.Replies)
{
Viking? replyAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == reply.VikingId) ?? new Viking();
CombinedListMessage clmReply = new CombinedListMessage
{
MessageType = (int)reply.MessageType,
MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = reply.Id,
ConversationID = reply.ConversationID ?? 0,
ReplyToMessageID = reply.ParentMessageId,
Creator = replyAuthor.Uid.ToString() ?? "Ghost",
CreateTime = reply.CreatedAt,
UpdateDate = reply.LastUpdatedAt,
MessageType = reply.MessageType.Value,
MessageLevel = reply.MessageLevel,
Content = reply.Data ?? "No Data Found In This Message. This Might Be An Error.",
DisplayAttribute = "C=White" // still having it always white :)
}),
MessageDate = reply.CreatedAt
};
combinedListMessages.Add(clmReply);
}
}
// save any changes made to db
ctx.SaveChanges();
// reverse list
combinedListMessages.Reverse();
// add list as array to response
response.CombinedListMessage = combinedListMessages.ToArray();
// return response
return response;
}
public ArrayOfMessageInfo ConstructUserMessageInfoArray(Viking viking, bool showOldMessages, bool showDeletedMessages)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// get all recent messages
List<Model.Message> messages = ctx.Messages.Where(e => e.ToVikingId == viking.Id)
.OrderBy(e => e.CreatedAt)
.OrderBy(e => e.QueueID)
.ToList();
List<MessageInfo> messageInfos = new List<MessageInfo>();
ArrayOfMessageInfo response = new ArrayOfMessageInfo();
foreach(var message in messages)
{
Viking? msgAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == message.VikingId) ?? new Viking();
if(!showOldMessages && message.IsNew && DateTime.Compare(message.CreatedAt.AddMinutes(30), now) > 0 || message.IsDeleted) continue; // sometimes clients won't set IsNew flag when updating messages, so do not add messages more than 30 minutes old to response
if(!message.IsNew && !showOldMessages) continue;
messageInfos.Add(new MessageInfo
{
MessageID = message.Id,
UserMessageQueueID = message.QueueID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MessageTypeID = (int?)message.MessageTypeID,
Data = message.Data ?? "NoData",
MemberMessage = message.MemberMessage ?? "NoMessage",
NonMemberMessage = message.NonMemberMessage ?? "NoMessage"
});
}
// add list as array to response
response.MessageInfo = messageInfos.ToArray();
// return response
return response;
}
}

View File

@ -12,6 +12,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.20">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.7" />
</ItemGroup>
<Choose>