/// <summary> /// 移除相关的订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> public void RemoveSubscriber(Type subjectType) { var client = GetConnection(); var channelName = TopicHelper.GetTopicName(subjectType); RemoveSubscriber(channelName); }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber(Type subjectType, Delegate subscriber) { var client = GetConnection(); var name = TopicHelper.GetTopicName(subjectType); #if NETSTANDARD channels.GetOrAdd(name, () => new List <CSRedisClient.SubscribeObject>()) .Add(client.Subscribe((name, msg => { var subject = Deserialize(subjectType, msg.Body); if (subject != null) { subscriber.DynamicInvoke(subject); } } ))); #else client.GetSubscriber().Subscribe(name, (channel, value) => { var subject = Deserialize(subjectType, Encoding.UTF8.GetString(value)); if (subject != null) { subscriber.DynamicInvoke(subject); } }); #endif }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber(Type subjectType, Delegate subscriber) { var client = GetConnection(); var name = TopicHelper.GetTopicName(subjectType); _channels.GetOrAdd(name, () => new List <CSRedisClient.SubscribeObject>()) .Add(client.Subscribe((name, msg => { StoredSubject subject = null; try { try { subject = Deserialize <StoredSubject>(msg.Body); subscriber.DynamicInvoke(Deserialize(subjectType, subject.Body)); } catch (SerializationException) { subscriber.DynamicInvoke(Deserialize(subjectType, msg.Body)); } } catch (Exception exp) { Tracer.Error($"Throw exception when consume message of '{name}':\n{exp.Output()}"); RetryPublishData(subject, exp); } } ))); }
/// <summary> /// 向 Rabbit 服务器发送消息主题。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subject">主题内容。</param> public void Publish <TSubject>(TSubject subject) where TSubject : class { var name = TopicHelper.GetTopicName(typeof(TSubject)); var data = Serialize(subject); Publish(name, data); }
public void Login(string username, string password) { if (!IsLogin) { if (!Logining) { Logining = true; ClientUserName = username; //消息发送处理频道 RunExchangeConsumeChannel(MyServiceMessageChannelName, TopicHelper.UserTopic(MyServiceName, ClientUserName), ExchangeType.topic, MyServiceMessageExchangeName, TopicHelper.UserTopic(MyServiceName, ClientUserName), MessageChannelCallBack); rabbitMqProvider.Send(MyServiceLoginChannelName, new RemoteMessage() { JsonContent = username + " " + password, Sender = ClientUserName, EnablePersistent = true, MessageType = MessageType.Unknown, }, queueName: MyServiceLoginQueueName); } else { Console.WriteLine("正在登录中"); } } else { Console.WriteLine("已经登录"); } }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subscriber">读取主题的方法。</param> public void AddAsyncSubscriber <TSubject>(Func <TSubject, Task> subscriber) where TSubject : class { var client = GetConnection(); var name = TopicHelper.GetTopicName(typeof(TSubject)); AddAsyncSubscriber <TSubject>(name, subscriber); }
private bool MessageChannelCallBack(RemoteMessage remoteMessage, BasicDeliverEventArgs args) { switch (remoteMessage.MessageType) { case MessageType.LoginCallBack: if (remoteMessage.JsonContent == "true") { Console.WriteLine("登录成功"); IsLogin = true; Logining = false; } else { Console.WriteLine("登录失败"); Logining = false; rabbitMqProvider.DeleteQueue(MyServiceMessageChannelName, TopicHelper.UserTopic(MyServiceName, ClientUserName)); } break; case MessageType.SystemMessage: break; case MessageType.GroupMessage: break; case MessageType.UserMessage: Console.WriteLine(remoteMessage.JsonContent); break; } return(true); }
/// <summary> /// 在 Rabbit 服务器中添加一个异步的订阅方法。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subscriber">读取主题的方法。</param> public void AddAsyncSubscriber <TSubject>(Func <TSubject, Task> subscriber) where TSubject : class { Guard.ArgumentNull(subscriber, nameof(subscriber)); var name = TopicHelper.GetTopicName(typeof(TSubject)); AddAsyncSubscriber <TSubject>(name, subscriber); }
/// <summary> /// 移除相关的订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> public void RemoveSubscriber(Type subjectType) { Guard.ArgumentNull(subjectType, nameof(subjectType)); var channelName = TopicHelper.GetTopicName(subjectType); RemoveSubscriber(channelName); }
/// <summary> /// 向 Redis 服务器发送消息主题。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subject">主题内容。</param> public void Publish <TSubject>(TSubject subject) where TSubject : class { var client = GetConnection(null); var name = TopicHelper.GetTopicName(typeof(TSubject)); var body = SerializeToBytes(subject); Publish(client, name, body); }
/// <summary> /// 在 Rabbit 服务器中添加一个订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber(Type subjectType, Delegate subscriber) { Guard.ArgumentNull(subjectType, nameof(subjectType)); Guard.ArgumentNull(subscriber, nameof(subscriber)); var name = TopicHelper.GetTopicName(subjectType); var list = _subscribers.GetOrAdd(name, () => new RabbitChannelCollection()); list.Add(new RabbitChannel(new SyncSubscribeDelegate(subjectType, subscriber), CreateAliveModel(name))); }
/// <summary> /// 在 Rabbit 服务器中添加一个订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber(Type subjectType, Delegate subscriber) { Guard.ArgumentNull(subjectType, nameof(subjectType)); Guard.ArgumentNull(subscriber, nameof(subscriber)); var name = TopicHelper.GetTopicName(subjectType); var list = subscribers.GetOrAdd(name, () => new RabbitChannelCollection()); list.Add(new RabbitChannel(subscriber, StartQueue(name))); }
/// <summary> /// 异步的,向 Redis 服务器发送消息主题。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subject">主题内容。</param> /// <param name="cancellationToken">取消操作的通知。</param> public async Task PublishAsync <TSubject>(TSubject subject, CancellationToken cancellationToken = default) where TSubject : class { cancellationToken.ThrowIfCancellationRequested(); var client = GetConnection(null); var name = TopicHelper.GetTopicName(typeof(TSubject)); var body = SerializeToBytes(subject); await PublishAsync(client, name, body); }
/// <summary> /// 异步的,向 Redis 服务器发送消息主题。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subject">主题内容。</param> /// <param name="cancellationToken">取消操作的通知。</param> public async Task PublishAsync <TSubject>(TSubject subject, CancellationToken cancellationToken = default) where TSubject : class { #if NETSTANDARD var client = GetConnection(); var name = TopicHelper.GetTopicName(typeof(TSubject)); await client.PublishAsync(name, Serialize(subject)); #else var data = Encoding.UTF8.GetBytes(Serialize(subject)); var name = TopicHelper.GetTopicName(typeof(TSubject)); Publish(name, data); #endif }
/// <summary> /// 向 Redis 服务器发送消息主题。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subject">主题内容。</param> public void Publish <TSubject>(TSubject subject) where TSubject : class { #if NETSTANDARD var client = GetConnection(); var name = TopicHelper.GetTopicName(typeof(TSubject)); client.Publish(name, Serialize(subject)); #else var data = Encoding.UTF8.GetBytes(Serialize(subject)); var name = TopicHelper.GetTopicName(typeof(TSubject)); Publish(name, data); #endif }
public MyService(TimeSpan requestHeartBeat, TimeSpan networkRecoveryInterval) { rabbitMqProvider = new RabbitMqProvider(); if (rabbitMqProvider.ConstructMqConsumerConn(requestHeartBeat, networkRecoveryInterval)) { //登录请求处理频道 RunSimpleConsumeChannel(MyServiceLoginChannelName, MyServiceLoginQueueName, LoginChannelCallBack); //消息接收处理频道 RunSimpleConsumeChannel(MyServiceReceiveChannelName, MyServiceReceiveQueueName, ReceiveChannelCallBack); //消息发送处理频道 RunExchangeChannel(MyServiceMessageChannelName, MyServiceMessageQueueName, ExchangeType.topic, MyServiceMessageExchangeName, TopicHelper.UserTopic(MyServiceName, MyServiceName), MessageChannelCallBack); } }
private static string GetRealLink(IEnumerable <TableOfContentsItem> topics, string name) { foreach (var topic in topics) { if (TopicHelper.LinkMatchesTopic(name, topic)) { return(topic.Link); } var childLink = GetRealLink(topic.Topics, name); if (!string.IsNullOrEmpty(childLink)) { return(childLink); } } return(string.Empty); }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber <TSubject>(Action <TSubject> subscriber) where TSubject : class { var client = GetConnection(); var name = TopicHelper.GetTopicName(typeof(TSubject)); #if NETSTANDARD channels.GetOrAdd(name, () => new List <CSRedisClient.SubscribeObject>()) .Add(client.Subscribe((name, msg => { var subject = Deserialize <TSubject>(msg.Body); subscriber(subject); } ))); #else client.GetSubscriber().Subscribe(name, (channel, value) => { var subject = Deserialize <TSubject>(Encoding.UTF8.GetString(value)); subscriber(subject); }); #endif }
private bool ReceiveChannelCallBack(RemoteMessage remoteMessage, BasicDeliverEventArgs args) { switch (remoteMessage.MessageType) { case MessageType.UserMessage: rabbitMqProvider.Send(MyServiceMessageChannelName, new RemoteMessage() { JsonContent = remoteMessage.JsonContent, Sender = remoteMessage.Sender, TopicRoute = TopicHelper.UserTopic(MyServiceName, remoteMessage.TopicRoute), MessageType = remoteMessage.MessageType, EnablePersistent = true }); break; case MessageType.GroupMessage: break; } return(true); }
private string AutoGenerateTitle(string intermediateHtml) { var value = SettingsHelper.GetSetting <TrueFalseAuto>(SettingsEnum.RenderTitleInTopic, TocSettings, CurrentTopicSettings, CurrentRequestRootSettings); // If it is false, we never do it, no matter what if (value == TrueFalseAuto.False) { return(intermediateHtml); } // If the setting is auto, we only render the title if the topic doesn't start with an h1 if (value == TrueFalseAuto.Auto && intermediateHtml.Trim().StartsWith("<h1")) { return(intermediateHtml); } // We need to auto-generate a title var link = TopicHelper.GetNormalizedName(SelectedTopic.Title); intermediateHtml = "<h1 id=\"" + link + "\">" + SelectedTopic.Title + "</h1>" + intermediateHtml; return(intermediateHtml); }
public void Check() { StatusReportList = new List <Report>(); var clusters = _setting.General.Kafka.Clusters; var connectionTimeoutSec = _setting.General.Kafka.ConnectionTimeoutSec; var topicNameFromSettings = _setting.General.Kafka.TopicName; var certificateLocation = _setting.General.Kafka.SslCertificateLocation; var certificateSubject = _setting.General.Kafka.SslCertificateSubject; var date = DateTime.Now.ToString("dd.MM.yyyy.HH.m"); if (File.Exists(certificateLocation)) { // delete an old certificate File.Delete(certificateLocation); } var counter = 0; foreach (var cluster in clusters) { counter++; string topicName; var kafkaStatus = ReportStatus.Undefined; var mongoDbStatus = ReportStatus.Undefined; var statusReport = new Report(); statusReport.Number = counter; statusReport.EnvName = cluster.Name; _logger.Info($" [{counter}] from [{clusters.Count}]. " + $"Work with the '{cluster.Name}' cluster"); // Check Mongo _logger.Info($"Checking Mongo DB:"); var mongoDbHelper = new MongoDbHelper(); var mongoDbConnectionStr = cluster.MongoDb; mongoDbStatus = mongoDbHelper.Ping(mongoDbConnectionStr, connectionTimeoutSec); // Check Kafka _logger.Info("Checking Kafka:"); var bootStrapServers = string.Join(",", cluster.BootstrapServers); _logger.Info($" bootstrap servers: {bootStrapServers}"); var clientConfig = new ClientConfig { BootstrapServers = bootStrapServers, SocketTimeoutMs = connectionTimeoutSec * 1000, }; topicName = $"{topicNameFromSettings}.{date}"; if (cluster.SslEnabled) { _logger.Info("SSL connection is enabled for this cluster"); if (!File.Exists(certificateLocation)) { try { var certificate = CertificateHelper.GetCertificate(certificateSubject); CertificateHelper.ExportToPEMFile(certificate, certificateLocation); } catch (CertificateException ce) { _logger.Error(ce.Message); kafkaStatus = ReportStatus.CertificateError; _logger.Warn($" Kafka status - [{kafkaStatus}]"); WriteClusterStatus(cluster, statusReport, mongoDbStatus, kafkaStatus); StatusReportList.Add(statusReport); continue; } } clientConfig.SslCaLocation = certificateLocation; clientConfig.SecurityProtocol = SecurityProtocol.Ssl; clientConfig.Debug = "security"; topicName = $"{topicNameFromSettings}.ssl.{date}"; } var bootstrapServersCount = cluster.BootstrapServers.Count; var topicHelper = new TopicHelper(); var producerConsumer = new ProducerConsumer(); var connectionIsOk = topicHelper .CheckConnectivity(clientConfig, bootstrapServersCount); if (connectionIsOk) { var topicWasCreated = topicHelper .CreateTopic(clientConfig, bootstrapServersCount, topicName); if (topicWasCreated) { _logger.Info(string.Empty); var producedMessageCount = producerConsumer.Produce(clientConfig, topicName); var consumedMessageCount = producerConsumer.Consume(clientConfig, topicName); if (producedMessageCount == consumedMessageCount) { _logger.Info($" * Produced messages == consumed messages: '{consumedMessageCount}' - [ok]"); kafkaStatus = ReportStatus.Ok; } else { _logger.Error($" * Produced messages != consumed messages: '{consumedMessageCount}' - [error]"); kafkaStatus = ReportStatus.Error; } } } else { kafkaStatus = ReportStatus.Error; } _logger.Info($" Kafka status - [{kafkaStatus}]"); WriteClusterStatus(cluster, statusReport, mongoDbStatus, kafkaStatus); StatusReportList.Add(statusReport); _logger.Info(string.Empty); } new HtmlReportHelper().PopulateTemplate(StatusReportList); }
public void Publish <TSubject>(TSubject subject) where TSubject : class { var name = TopicHelper.GetTopicName(typeof(TSubject)); Publish(name, subject); }
public async Task PublishAsync <TSubject>(TSubject subject, CancellationToken cancellationToken = default) where TSubject : class { var name = TopicHelper.GetTopicName(typeof(TSubject)); await PublishAsync(name, subject, cancellationToken); }
private bool LoginChannelCallBack(RemoteMessage remoteMessage, BasicDeliverEventArgs args) { var param = remoteMessage.JsonContent.Split(" "); bool ret = false; string returnMessage = "true"; if (param.Length != 2) { LogHelper.LogError($"用户{remoteMessage.Sender}请求登录参数异常"); } else { var username = param[0]; var password = param[1]; LogHelper.Log($"{username} 请求登录。UID:{remoteMessage.Sender};请求时间:{remoteMessage.Timestamp};"); try { //using (var db = new ChegevalaContext()) //{ //var user = db.Set<User>().Where(n => n.UserName == username).FirstOrDefault(); //if (user == null) //{ // //用户未注册,为其注册账号 // db.Add(new User() // { // UserName = username, // PassWord = password // }); // db.SaveChanges(); // ret = true; // returnMessage = "登录成功,已经成功创建账号"; //} //else //{ // //用户已注册,判断密码是否正确 // if (user.PassWord == password) // { // ret = true; // returnMessage = "登录成功"; // } // else // { // ret = false; // returnMessage = "登录失败,密码错误"; // } //} rabbitMqProvider.Send(MyServiceMessageChannelName, new RemoteMessage() { JsonContent = returnMessage, TopicRoute = TopicHelper.UserTopic(MyServiceName, remoteMessage.Sender), Sender = MyServiceName, MessageType = MessageType.LoginCallBack, Timestamp = DateTime.Now, EnablePersistent = false }); if (ret) { LogHelper.Log($"用户{username}登录成功"); } else { LogHelper.Log($"用户{username}登录失败"); } //} } catch (Exception e) { LogHelper.LogError(e.Message); } } return(true); }
private async Task GetHtmlContent() { var rawTopic = new TopicInformation { OriginalName = SelectedTopic.Title, Type = SelectedTopic.Type }; ImageRootUrl = string.Empty; var normalizedLink = SelectedTopic.LinkPure.ToLowerInvariant(); if (normalizedLink.StartsWith("https://") || normalizedLink.StartsWith("http://")) { // This is an absolute link, so we can just try to load it rawTopic.OriginalContent = await WebClientEx.GetStringAsync(SelectedTopic.Link); ImageRootUrl = StringHelper.JustPath(SelectedTopic.Link) + "/"; } else if (!string.IsNullOrEmpty(normalizedLink)) { var repositoryType = RepositoryTypeHelper.GetTypeFromTypeName(GetSetting <string>(SettingsEnum.RepositoryType)); // Even if the overall repository type is something else, we will switch to different repository access for specific node types, // as they may point to other repositories or require different APIs even within the same repository if (TopicTypeHelper.IsVstsWorkItemType(rawTopic?.Type)) { repositoryType = RepositoryTypes.VstsWorkItemTracking; } switch (repositoryType) { case RepositoryTypes.GitHubRaw: var fullGitHubRawUrl = GitHubMasterUrlRaw + SelectedTopic.Link; if (string.IsNullOrEmpty(rawTopic.Type)) { rawTopic.Type = TopicTypeHelper.GetTopicTypeFromLink(fullGitHubRawUrl); } if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Markdown) || TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Html)) { rawTopic.OriginalContent = await WebClientEx.GetStringAsync(fullGitHubRawUrl); } else if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.ImageUrl)) { rawTopic.OriginalContent = fullGitHubRawUrl; } ImageRootUrl = StringHelper.JustPath(fullGitHubRawUrl); if (!string.IsNullOrEmpty(ImageRootUrl) && !ImageRootUrl.EndsWith("/")) { ImageRootUrl += "/"; } break; case RepositoryTypes.GitHubApi: if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Markdown) || TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Html)) { var gitHubClient = new GithubRepositoryParser(GitHubOwner, GitHubRepository, GitHubPat); var gitHubContent = await gitHubClient.GetItemContent(SelectedTopic.Link); rawTopic.OriginalContent = gitHubContent.Text; } // TODO: else if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.ImageUrl)) // rawTopic.OriginalContent = fullGitHubRawUrl; //ImageRootUrl = StringHelper.JustPath(fullGitHubRawUrl); //if (!string.IsNullOrEmpty(ImageRootUrl) && !ImageRootUrl.EndsWith("/")) ImageRootUrl += "/"; break; case RepositoryTypes.VstsGit: if (!string.IsNullOrEmpty(SelectedTopic.LinkPure)) { rawTopic.OriginalContent = await VstsHelper.GetFileContents(SelectedTopic.LinkPure, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsDocsFolder), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); } ImageRootUrl = "/___FileProxy___?mode=" + RepositoryTypeNames.VstsGit + "&path="; if (SelectedTopic.LinkPure.Contains("/")) { ImageRootUrl += StringHelper.JustPath(SelectedTopic.LinkPure) + "/"; } break; case RepositoryTypes.VstsWorkItemTracking: if ((TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQuery) || TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries)) && HttpContext.Request.Query.ContainsKey("workitemnumber")) { // The current node is a work item query, but we use it as a context to get the actual work item var itemNumber = int.Parse(HttpContext.Request.Query["workitemnumber"]); rawTopic.OriginalContent = await VstsHelper.GetWorkItemJson(itemNumber, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); rawTopic.Type = TopicBodyFormats.VstsWorkItem; } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries) && HttpContext.Request.Query.ContainsKey("queryid")) { // The current node is a list of work item queries, but we use it as a context to run the actual query var queryId = HttpContext.Request.Query["queryid"]; var queryInfoJson = await VstsHelper.GetWorkItemQueriesJson(queryId, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); dynamic queryInfo = JObject.Parse(queryInfoJson); if (queryInfo != null) { Title = "Query: " + queryInfo.name; } rawTopic.OriginalContent = await VstsHelper.RunWorkItemQueryJson(queryId, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); if (rawTopic.OriginalContent.StartsWith("{")) { rawTopic.Type = TopicBodyFormats.VstsWorkItemQuery; } else { rawTopic.Type = TopicBodyFormats.Markdown; // Something went wrong, but one way or another, we didn't end up with JSON } } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItem)) { // Plain work item node var itemNumber = int.Parse(SelectedTopic.Link); rawTopic.OriginalContent = await VstsHelper.GetWorkItemJson(itemNumber, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries)) { // Plain work item queries rawTopic.OriginalContent = await VstsHelper.GetWorkItemQueriesJson(SelectedTopic.Link, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); Title = SelectedTopic.Title; } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQuery)) { // Plain work item query rawTopic.OriginalContent = await VstsHelper.RunWorkItemQueryJson(SelectedTopic.Link, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); Title = SelectedTopic.Title; } Vsts.ImageLink = "/___FileProxy___?mode=" + RepositoryTypeNames.VstsWorkItemTracking + "&topic=" + CurrentSlug + "&path="; break; } } var renderer = TopicRendererFactory.GetTopicRenderer(rawTopic); var intermediateHtml = renderer.RenderToHtml(rawTopic, ImageRootUrl, this); if (!string.IsNullOrEmpty(intermediateHtml)) { intermediateHtml = await ProcessKavaTopic(intermediateHtml); intermediateHtml = AutoGenerateTitle(intermediateHtml); intermediateHtml = ProcessBrokenImageLinks(intermediateHtml, ImageRootUrl); } Html = intermediateHtml; Json = renderer.RenderToJson(rawTopic, ImageRootUrl, this); TemplateName = renderer.GetTemplateName(rawTopic, TemplateName, this); if (string.IsNullOrEmpty(Html) && SelectedTopic != null) { var sb = new StringBuilder(); sb.Append("<h1>" + SelectedTopic.Title + "</h1>"); if (SelectedTopic.Topics.Count > 0) { sb.Append("<ul>"); foreach (var topic in SelectedTopic.Topics) { sb.Append("<li class=\"kava-auto-link\">"); sb.Append("<a href=\"" + TopicHelper.GetNormalizedName(topic.Title) + "\">"); sb.Append(topic.Title); sb.Append("</a>"); sb.Append("</li>"); } sb.Append("</ul>"); } Html = sb.ToString(); } }
private async Task BuildToc() { string tocJson = null; var repositoryType = RepositoryTypeHelper.GetTypeFromTypeName(GetSetting <string>(SettingsEnum.RepositoryType)); var logoUrl = GetSetting <string>(SettingsEnum.LogoPath); var logoUrlLower = logoUrl.ToLowerInvariant(); var logoUrlIsAbsolute = true; if (!logoUrl.StartsWith("http://") && !logoUrl.StartsWith("https://")) { logoUrlIsAbsolute = false; } LogoUrl = logoUrl; if (UseSqlServer) // SQL server *may* provide a local tabe of contents that would override all others { tocJson = await SqlDataAccess.GetRepositoryLocalTableOfContents(CurrentPrefix); } if (string.IsNullOrEmpty(tocJson)) { switch (repositoryType) { case RepositoryTypes.GitHubRaw: tocJson = await TableOfContentsHelper.GetTocJsonFromGitHubRaw(GitHubMasterUrlRaw); if (!logoUrlIsAbsolute) { LogoUrl = GitHubMasterUrlRaw + logoUrl; } break; case RepositoryTypes.GitHubApi: tocJson = await TableOfContentsHelper.GetTocJsonFromGitHubApi(GitHubOwner, GitHubRepository, GitHubPat); // TODO: if (!logoUrlIsAbsolute) // LogoUrl = GitHubMasterUrlRaw + logoUrl; break; case RepositoryTypes.VstsGit: tocJson = await VstsHelper.GetTocJson(GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsDocsFolder), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); if (!logoUrlIsAbsolute) { LogoUrl = $"/___FileProxy___?mode=vstsgit&path={logoUrl}"; } break; } } if (string.IsNullOrEmpty(tocJson)) { return; } var dynamicToc = TableOfContentsHelper.GetDynamicTocFromJson(tocJson); if (dynamicToc.title != null) { RepositoryTitle = dynamicToc.title; } if (dynamicToc.owner != null) { Owner = dynamicToc.owner; } Topics = TableOfContentsHelper.BuildTocFromDynamicToc(dynamicToc, this, CurrentSlug, out List <TableOfContentsItem> flatTopicList); FlatTopics = flatTopicList; MainMenu = TableOfContentsHelper.BuildMainMenuStructureFromDynamicToc(dynamicToc); var matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.SlugMatchesTopic(CurrentSlug, t)); if (matchingTopic == null) { matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.SlugMatchesTopic(CurrentSlug, t, true)); } if (matchingTopic == null) { matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.LinkMatchesTopic(CurrentSlug, t)); } if (matchingTopic == null) { matchingTopic = Topics.FirstOrDefault(); } SelectedTopic = matchingTopic; TableOfContentsHelper.EnsureExpanded(SelectedTopic); TocSettings = dynamicToc.settings; CurrentTopicSettings = SelectedTopic?.SettingsDynamic; }