Commit 1d1f34aa authored by L. Ellenbeck's avatar L. Ellenbeck
Browse files

WIP: corrections, restructures and language support coscine/issues#1296

parent 2d1b6c06
using Coscine.Api.Notices.ReturnObjects;
using Coscine.Api.Notices.Services;
using Coscine.Api.Notices.Utils;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.ServiceModel.Syndication;
using System.Xml;
using System;
using Coscine.Api.Notices.Utils;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Coscine.Api.Notices.Controllers
{
......@@ -16,6 +15,9 @@ namespace Coscine.Api.Notices.Controllers
public class NoticeController : Controller
{
private readonly INoticeService _noticeService;
private readonly MaintenanceHelper _maintenanceHelper;
// url to rss feed from consul variable
private readonly string _rssUrl;
/// <summary>
/// NoticeController constructor
......@@ -24,6 +26,8 @@ namespace Coscine.Api.Notices.Controllers
public NoticeController(INoticeService noticeService)
{
_noticeService = noticeService;
_maintenanceHelper = new MaintenanceHelper();
_rssUrl = Program.Configuration.GetStringAndWait($"coscine/global/rss/url");
}
/// <summary>
......@@ -37,12 +41,16 @@ namespace Coscine.Api.Notices.Controllers
public async Task<IActionResult> GetNotice(string documentSlug, [FromQuery] string language = "en")
{
var url = await Program.Configuration.GetStringAsync($"coscine/local/documents/{documentSlug}/{language}", null);
if (url == null)
{
return BadRequest();
}
return Json(new {
data = new {
return Json(new
{
data = new
{
body = await _noticeService.GetNotice(url)
}
});
......@@ -53,29 +61,43 @@ namespace Coscine.Api.Notices.Controllers
/// </summary>
/// <returns>Maintenance</returns>
[HttpGet("[controller]/getMaintenance")]
public JObject GetMaintenance()
public IActionResult GetMaintenance()
{
var array = new JArray();
var maintenance = _maintenanceHelper.GetMaintenance(_rssUrl);
// url to rss feed from consul variable
var url = Program.Configuration.GetStringAndWait($"coscine/global/rss/url");
if(maintenance == null)
{
return NotFound("No maintenance was found.");
}
Maintenance maintenance = Maintenance.GetMaintenance(url);
var maintenanceReturnObjectDe = new MaintenanceReturnObject
{
Body = maintenance.Body,
DisplayName = maintenance.DisplayName,
EndsDate = maintenance.EndsDate.ToString("dddd dd.MM.yyyy HH:mm"),
StartsDate = (maintenance.EndsDate == DateTime.MaxValue) ? "unbekannt" : maintenance.EndsDate.ToString("dddd dd.MM.yyyy HH:mm"),
Type = maintenance.GetTranslatedType(Language.de),
Url = maintenance.Url,
};
if (maintenance != null)
var maintenanceReturnObjectEn = new MaintenanceReturnObject
{
array.Add(new JObject
{
["displayName"] = maintenance.Title,
["url"] = maintenance.Url,
["startDate"] = maintenance.StartsDate.ToString("dddd dd.MM.yyyy HH:mm"),
["endDate"] = (maintenance.EndsDate == DateTime.MaxValue) ? "unbekannt" : maintenance.EndsDate.ToString("dddd dd.MM.yyyy HH:mm"),
["type"] = maintenance.Type,
["body"] = maintenance.Description
});
}
Body = maintenance.Body,
DisplayName = maintenance.DisplayName,
EndsDate = maintenance.EndsDate.ToString("dddd dd.MM.yyyy HH:mm"),
StartsDate = (maintenance.EndsDate == DateTime.MaxValue) ? "unknown" : maintenance.EndsDate.ToString("dddd dd.MM.yyyy HH:mm"),
Type = maintenance.GetTranslatedType(Language.de),
Url = maintenance.Url,
};
return new JObject { ["data"] = array };
return Json(new
{
data = new
{
de = new List<MaintenanceReturnObject> { maintenanceReturnObjectDe },
en = new List<MaintenanceReturnObject> { maintenanceReturnObjectEn },
}
});
}
}
......
......@@ -607,10 +607,13 @@
<Compile Include="Controllers\NoticeController.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReturnObjects\MaintenanceReturnObject.cs" />
<Compile Include="Services\INoticeService.cs" />
<Compile Include="Services\NoticeService.cs" />
<Compile Include="Startup.cs" />
<Compile Include="Utils\Language.cs" />
<Compile Include="Utils\Maintenance.cs" />
<Compile Include="Utils\MaintenanceHelper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
......
using System;
namespace Coscine.Api.Notices.ReturnObjects
{
/// <summary>
/// This class represents a maintenance with its significant properties, which is returned from the api.
/// </summary>
public class MaintenanceReturnObject
{
/// <summary>
/// Maintenance title.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Maintenance url.
/// </summary>
public Uri Url { get; set; }
/// <summary>
/// Maintenance type.
/// </summary>
public string Type { get; set; }
/// <summary>
/// Maintenance description.
/// </summary>
public string Body { get; set; }
/// <summary>
/// Maintenance start.
/// </summary>
public string StartsDate { get; set; }
/// <summary>
/// Maintenance end.
/// </summary>
public string EndsDate { get; set; }
}
}
namespace Coscine.Api.Notices.Utils
{
/// <summary>
/// Language selector
/// </summary>
public enum Language
{
/// <summary>
/// German
/// </summary>
de,
/// <summary>
/// English
/// </summary>
en
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
namespace Coscine.Api.Notices.Utils
{
// for the most part taken from https://git.rwth-aachen.de/rwthapp/rwthappproxy/-/blob/master/Source/ProxyService/ServiceObjects/Maintenance.cs
/// <summary>
/// This class represents a maintenance with its significant properties.
/// </summary>
public class Maintenance
{
public string Title { get; set; }
/// <summary>
/// Maintenance title.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Maintenance url.
/// </summary>
public Uri Url { get; set; }
/// <summary>
/// Maintenance type.
/// </summary>
public string Type { get; set; }
public string Description { get; set; }
public DateTime StartsDate { get; set; }
public DateTime EndsDate { get; set; }
private static readonly string undefinedString = "-NotDefined-";
/// <summary>
/// Default Constructor
/// Maintenance description.
/// </summary>
public Maintenance()
{
}
public string Body { get; set; }
/// <summary>
/// Creates a new Maintenance
/// Maintenance start.
/// </summary>
/// <param name="titleIn">Title of Maintenance</param>
/// <param name="uriIn">Url of Maintenance</param>
/// <param name="typeIn">Type of Maintenance</param>
/// <param name="startsIn">Start Date of Maintenance</param>
/// <param name="endsIn">End Date of Maintenance</param>
/// <param name="descriptionIn">Description of Maintenance</param>
public Maintenance(string titleIn, Uri uriIn, string typeIn, string descriptionIn, DateTime startsIn, DateTime endsIn)
{
Title = titleIn;
Url = uriIn;
Type = typeIn;
StartsDate = startsIn;
EndsDate = endsIn;
Description = descriptionIn;
}
public DateTime StartsDate { get; set; }
/// <summary>
/// Get the most relevant maintenance from the rss feed
/// Maintenance end.
/// </summary>
/// <param name="feedURLIn">Url of the rss feed</param>
/// <param name="orderIn">Order of Importance</param>
/// <returns></returns>
internal static Maintenance GetMaintenance(string feedURLIn, List<string> orderIn = null)
public DateTime EndsDate { get; set; }
/// <summary>
/// Gets the type in the specified language.
/// <param name="language">Language (e.g. "Language.en" or "Language.de")</param>
/// <returns>Translated type</returns>
/// </summary>
public string GetTranslatedType(Language language)
{
Maintenance result = null;
List<string> order;
string feedUrl = feedURLIn;
if (orderIn != null)
if (language == Language.de)
{
order = orderIn;
return Type;
}
else
{
//Reihenfolge der Relevanz der Störung; Alle nicht aufgelisteten Störungen werden als "-NotDefined-" einsortiert;
//Es wird nur die relevanteste Störung zurückgegeben
order = new List<string> { "Störung", "Teilstörung", "Unterbrechung", "eingeschränkt betriebsfähig", "Wartung", "Teilwartung",
"Änderung", "Warnung", "-NotDefined-", "Hinweis" };
}
if (order.FindIndex(x => x.ToLower() == undefinedString.ToLower()) == -1)
{
order.Add(undefinedString);
}
int resultOrderPos = order.Count() + 1; ;
try
{
SyndicationFeed rssfeed = SyndicationFeed.Load(XmlReader.Create(feedUrl));
List<SyndicationItem> sol = rssfeed.Items.OrderByDescending(x => x.PublishDate).ToList();
foreach (SyndicationItem i in sol)
{
try
{
if (i != null && i.Summary != null && !String.IsNullOrWhiteSpace(i.Summary.Text))
{
Maintenance current = new Maintenance();
current.Title = i.Title.Text;
current.Url = i.Links[0].Uri;
string summary = i.Summary.Text;
int splitter = summary.IndexOf('-');
if (splitter != -1)
{
current.Description = summary.Substring(splitter + 1, summary.Length - splitter - 1).Trim();
string firstPart = summary.Substring(0, splitter).Trim();
splitter = firstPart.IndexOf("von");
if (splitter != -1)
{
current.Type = firstPart.Substring(0, splitter).Trim();
string timespan = firstPart.Substring(splitter + 3, firstPart.Length - splitter - 3).Trim();
splitter = timespan.IndexOf("bis");
if (splitter != -1)
{
String startsString = timespan.Substring(0, splitter).Trim();
String endsString = timespan.Substring(splitter + 3, timespan.Length - splitter - 3).Trim();
List<string> dayList = new List<string> { "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
foreach (string dayString in dayList)
{
startsString = startsString.Replace(dayString, "").Trim();
startsString = startsString.Replace(dayString.ToLower(), "").Trim();
}
foreach (string dayString in dayList)
{
endsString = endsString.Replace(dayString, "").Trim();
endsString = endsString.Replace(dayString.ToLower(), "").Trim();
}
if (startsString.ToLower() == "unbekannt")
{
current.StartsDate = DateTime.MinValue;
}
else
{
current.StartsDate = DateTime.ParseExact(startsString, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture);
}
if (endsString.ToLower() == "unbekannt")
{
current.EndsDate = DateTime.MaxValue;
}
else
{
current.EndsDate = DateTime.ParseExact(endsString, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture);
}
//still active message
if (current.EndsDate > DateTime.Now && current.StartsDate < DateTime.Now)
{
//first listet valid message
if (result == null)
{
result = current;
resultOrderPos = getOrderPos(order, result.Type);
}
else
{
//check if the current message is higher ranged as the previosly result
int currentOrderPos = getOrderPos(order, current.Type);
//higher rang of type
if (currentOrderPos < resultOrderPos)
{
result = current;
resultOrderPos = currentOrderPos;
// same type but longer active
}
else if (currentOrderPos < resultOrderPos && current.EndsDate > result.EndsDate)
{
result = current;
resultOrderPos = currentOrderPos;
}
}
}
}
}
}
}
}
catch (Exception e)
{
//ignore not correct parsed messages
}
}
}
catch (Exception e)
{
//throw new ApiRequestException("RSS Feed could not be parsed", 5324);
throw e;
}
return result;
return _translations.ContainsKey(Type) ? _translations[Type] : Type;
}
private static int getOrderPos(List<string> order, string type)
{
int res = order.FindIndex(x => x.ToLower() == type.ToLower());
if (res == -1)
{
res = order.FindIndex(x => x.ToLower() == undefinedString.ToLower());
}
if (res == -1)
{
res = order.Count() + 1;
}
return res;
}
private static readonly Dictionary<string, string> _translations = new Dictionary<string, string> {
{ "Störung", "StörungEn" },
{ "Teilstörung", "TeilstörungEn" },
{ "Unterbrechung", "UnterbrechungEn" },
{ "eingeschränkt betriebsfähig", "eingeschränkt betriebsfähigEn" },
{ "Wartung", "WartungEn" },
{ "Teilwartung", "TeilwartungEn" },
{ "Änderung", "ÄnderungEn" },
{ "Warnung", "WarnungEn" },
{ "-NotDefined-", "-NotDefined-En" },
{ "Hinweis", "HinweisEn" },
};
}
}
using Coscine.Api.Notices.ReturnObjects;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
namespace Coscine.Api.Notices.Utils
{
/// <summary>
/// This class
/// </summary>
public class MaintenanceHelper
{
private string UndefinedString { get; set; } = "-NotDefined-";
//Reihenfolge der Relevanz der Störung; Alle nicht aufgelisteten Störungen werden als "-NotDefined-" einsortiert;
//Es wird nur die relevanteste Störung zurückgegeben
private List<string> RelevanceList { get; set; } = new List<string> { "Störung", "Teilstörung", "Unterbrechung", "eingeschränkt betriebsfähig", "Wartung", "Teilwartung", "Änderung", "Warnung", "-NotDefined-", "Hinweis" };
/// <summary>
/// Get the most relevant maintenance from the rss feed
/// </summary>
/// <param name="feedUrl">Url of the rss feed</param>
/// <returns></returns>
internal Maintenance GetMaintenance(string feedUrl)
{
return GetMaintenance(feedUrl, RelevanceList);
}
/// <summary>
/// Get the most relevant maintenance from the rss feed
/// </summary>
/// <param name="feedUrl">Url of the rss feed</param>
/// <param name="order">Order of Importance</param>
/// <returns></returns>
internal Maintenance GetMaintenance(string feedUrl, List<string> order)
{
Maintenance result = null;
if (order.FindIndex(x => x.ToLower() == UndefinedString.ToLower()) == -1)
{
order.Add(UndefinedString);
}
int resultOrderPos = order.Count() + 1; ;
try
{
SyndicationFeed rssfeed = SyndicationFeed.Load(XmlReader.Create(feedUrl));
List<SyndicationItem> sol = rssfeed.Items.OrderByDescending(x => x.PublishDate).ToList();
foreach (SyndicationItem i in sol)
{
try
{
if (i != null && i.Summary != null && !String.IsNullOrWhiteSpace(i.Summary.Text))
{
var current = new Maintenance
{
DisplayName = i.Title.Text,
Url = i.Links[0].Uri
};
string summary = i.Summary.Text;
int splitter = summary.IndexOf('-');
if (splitter != -1)
{
current.Body = summary.Substring(splitter + 1, summary.Length - splitter - 1).Trim();
string firstPart = summary.Substring(0, splitter).Trim();
splitter = firstPart.IndexOf("von");
if (splitter != -1)
{
current.Type = firstPart.Substring(0, splitter).Trim();
string timespan = firstPart.Substring(splitter + 3, firstPart.Length - splitter - 3).Trim();
splitter = timespan.IndexOf("bis");
if (splitter != -1)
{
string startsString = timespan.Substring(0, splitter).Trim();
string endsString = timespan.Substring(splitter + 3, timespan.Length - splitter - 3).Trim();
List<string> dayList = new List<string> { "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
foreach (var dayString in dayList)
{
startsString = startsString.Replace(dayString, "").Trim();
startsString = startsString.Replace(dayString.ToLower(), "").Trim();
}
foreach (var dayString in dayList)
{
endsString = endsString.Replace(dayString, "").Trim();
endsString = endsString.Replace(dayString.ToLower(), "").Trim();
}
if (startsString.ToLower() == "unbekannt")
{
current.StartsDate = DateTime.MinValue;
}
else
{
current.StartsDate = DateTime.ParseExact(startsString, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture);
}
if (endsString.ToLower() == "unbekannt")
{
current.EndsDate = DateTime.MaxValue;
}
else
{
current.EndsDate = DateTime.ParseExact(endsString, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture);
}
//still active message
if (current.EndsDate > DateTime.Now && current.StartsDate < DateTime.Now)
{
//first listet valid message
if (result == null)
{
result = current;
resultOrderPos = GetOrderPos(order, result.Type);
}
else
{
//check if the current message is higher ranged as the previosly result
int currentOrderPos = GetOrderPos(order, current.Type);
//higher rang of type
if (currentOrderPos < resultOrderPos)
{
result = current;
resultOrderPos = currentOrderPos;
// same type but longer active
}
else if (currentOrderPos < resultOrderPos && current.EndsDate > result.EndsDate)
{
result = current;
resultOrderPos = currentOrderPos;
}
}
}
}
}
}
}
}
catch (Exception)
{
//ignore not correct parsed messages
}
}
}
catch (Exception e)
{
//throw new ApiRequestException("RSS Feed could not be parsed", 5324);
throw e;
}
return result;
}
private int GetOrderPos(List<string> order, string type)
{
int res = order.FindIndex(x => x.ToLower() == type.ToLower());
if (res == -1)
{
res = order.FindIndex(x => x.ToLower() == UndefinedString.ToLower());
}