< Summary

Information
Class: LGDXRobotCloud.API.Services.Automation.TriggerService
Assembly: LGDXRobotCloud.API
File(s): /builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Automation/TriggerService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 201
Coverable lines: 201
Total lines: 268
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 65
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)0%4260%
GetTriggersAsync()0%620%
GetTriggerAsync()0%620%
CreateTriggerAsync()0%7280%
UpdateTriggerAsync()0%4260%
TestDeleteTriggerAsync()0%620%
DeleteTriggerAsync()100%210%
SearchTriggersAsync()0%620%
GetRobotName(...)0%2040%
GetRealmName(...)0%2040%
GeneratePresetValue(...)0%9090%
InitialiseTriggerAsync()0%272160%
RetryTriggerAsync()0%2040%

File(s)

/builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Automation/TriggerService.cs

#LineLine coverage
 1using System.Text.Json;
 2using LGDXRobotCloud.API.Exceptions;
 3using LGDXRobotCloud.API.Services.Administration;
 4using LGDXRobotCloud.Data.Contracts;
 5using LGDXRobotCloud.Data.DbContexts;
 6using LGDXRobotCloud.Data.Entities;
 7using LGDXRobotCloud.Data.Models.Business.Automation;
 8using LGDXRobotCloud.Utilities.Enums;
 9using LGDXRobotCloud.Utilities.Helpers;
 10using MassTransit;
 11using Microsoft.EntityFrameworkCore;
 12
 13namespace LGDXRobotCloud.API.Services.Automation;
 14
 15public interface ITriggerService
 16{
 17  Task<(IEnumerable<TriggerListBusinessModel>, PaginationHelper)> GetTriggersAsync(string? name, int pageNumber, int pag
 18  Task<TriggerBusinessModel> GetTriggerAsync(int triggerId);
 19  Task<TriggerBusinessModel> CreateTriggerAsync(TriggerCreateBusinessModel triggerCreateBusinessModel);
 20  Task<bool> UpdateTriggerAsync(int triggerId, TriggerUpdateBusinessModel triggerUpdateBusinessModel);
 21  Task<bool> TestDeleteTriggerAsync(int triggerId);
 22  Task<bool> DeleteTriggerAsync(int triggerId);
 23
 24  Task<IEnumerable<TriggerSearchBusinessModel>> SearchTriggersAsync(string? name);
 25
 26  Task InitialiseTriggerAsync(AutoTask autoTask, FlowDetail flowDetail);
 27  Task RetryTriggerAsync(AutoTask autoTask, Trigger trigger, string body);
 28}
 29
 030public sealed class TriggerService (
 031  IBus bus,
 032  LgdxContext context,
 033  IApiKeyService apiKeyService
 034) : ITriggerService
 35{
 036  private readonly IBus _bus = bus ?? throw new ArgumentNullException(nameof(bus));
 037  private readonly LgdxContext _context = context ?? throw new ArgumentNullException(nameof(context));
 038  private readonly IApiKeyService _apiKeyService = apiKeyService ?? throw new ArgumentNullException(nameof(apiKeyService
 39
 40  public async Task<(IEnumerable<TriggerListBusinessModel>, PaginationHelper)> GetTriggersAsync(string? name, int pageNu
 041  {
 042    var query = _context.Triggers as IQueryable<Trigger>;
 043    if(!string.IsNullOrWhiteSpace(name))
 044    {
 045      name = name.Trim();
 046      query = query.Where(t => t.Name.Contains(name));
 047    }
 048    var itemCount = await query.CountAsync();
 049    var PaginationHelper = new PaginationHelper(itemCount, pageNumber, pageSize);
 050    var triggers = await query.AsNoTracking()
 051      .OrderBy(t => t.Id)
 052      .Skip(pageSize * (pageNumber - 1))
 053      .Take(pageSize)
 054      .Select(t => new TriggerListBusinessModel {
 055        Id = t.Id,
 056        Name = t.Name,
 057        Url = t.Url,
 058        HttpMethodId = t.HttpMethodId,
 059      })
 060      .ToListAsync();
 061    return (triggers, PaginationHelper);
 062  }
 63
 64  public async Task<TriggerBusinessModel> GetTriggerAsync(int triggerId)
 065  {
 066    return await _context.Triggers.Where(t => t.Id == triggerId)
 067      .Include(t => t.ApiKey)
 068      .Select(t => new TriggerBusinessModel {
 069        Id = t.Id,
 070        Name = t.Name,
 071        Url = t.Url,
 072        HttpMethodId = t.HttpMethodId,
 073        Body = t.Body,
 074        SkipOnFailure = t.SkipOnFailure,
 075        ApiKeyInsertLocationId = t.ApiKeyInsertLocationId,
 076        ApiKeyFieldName = t.ApiKeyFieldName,
 077        ApiKeyId = t.ApiKey!.Id,
 078        ApiKeyName = t.ApiKey!.Name,
 079      })
 080      .FirstOrDefaultAsync()
 081        ?? throw new LgdxNotFound404Exception();
 082  }
 83
 84  public async Task<TriggerBusinessModel> CreateTriggerAsync(TriggerCreateBusinessModel triggerCreateBusinessModel)
 085  {
 086    if (triggerCreateBusinessModel.ApiKeyId != null)
 087    {
 088      var apiKey = await _apiKeyService.GetApiKeyAsync((int)triggerCreateBusinessModel.ApiKeyId);
 089      if (apiKey == null)
 090      {
 091        throw new LgdxValidation400Expection(nameof(TriggerBusinessModel.Id), $"The API Key Id {triggerCreateBusinessMod
 92      }
 093      else if (!apiKey.IsThirdParty)
 094      {
 095        throw new LgdxValidation400Expection(nameof(TriggerBusinessModel.Id), "Only third party API key is allowed.");
 96      }
 097    }
 98
 099    var trigger = new Trigger {
 0100      Name = triggerCreateBusinessModel.Name,
 0101      Url = triggerCreateBusinessModel.Url,
 0102      HttpMethodId = triggerCreateBusinessModel.HttpMethodId,
 0103      Body = triggerCreateBusinessModel.Body,
 0104      SkipOnFailure = triggerCreateBusinessModel.SkipOnFailure,
 0105      ApiKeyInsertLocationId = triggerCreateBusinessModel.ApiKeyInsertLocationId,
 0106      ApiKeyFieldName = triggerCreateBusinessModel.ApiKeyFieldName,
 0107      ApiKeyId = triggerCreateBusinessModel.ApiKeyId,
 0108    };
 0109    await _context.Triggers.AddAsync(trigger);
 0110    await _context.SaveChangesAsync();
 0111    return new TriggerBusinessModel {
 0112      Id = trigger.Id,
 0113      Name = trigger.Name,
 0114      Url = trigger.Url,
 0115      HttpMethodId = trigger.HttpMethodId,
 0116      Body = trigger.Body,
 0117      SkipOnFailure = trigger.SkipOnFailure,
 0118      ApiKeyInsertLocationId = trigger.ApiKeyInsertLocationId,
 0119      ApiKeyFieldName = trigger.ApiKeyFieldName,
 0120      ApiKeyId = trigger.ApiKeyId,
 0121      ApiKeyName = trigger.ApiKey?.Name,
 0122    };
 0123  }
 124
 125  public async Task<bool> UpdateTriggerAsync(int triggerId, TriggerUpdateBusinessModel triggerUpdateBusinessModel)
 0126  {
 0127    if (triggerUpdateBusinessModel.ApiKeyId != null)
 0128    {
 0129      var apiKey = await _apiKeyService.GetApiKeyAsync((int)triggerUpdateBusinessModel.ApiKeyId);
 0130      if (apiKey == null)
 0131      {
 0132        throw new LgdxValidation400Expection(nameof(triggerId), $"The API Key Id {triggerUpdateBusinessModel.ApiKeyId} i
 133      }
 0134      else if (!apiKey.IsThirdParty)
 0135      {
 0136        throw new LgdxValidation400Expection(nameof(triggerId), "Only third party API key is allowed.");
 137      }
 0138    }
 139
 0140    return await _context.Triggers
 0141      .Where(t => t.Id == triggerId)
 0142      .ExecuteUpdateAsync(setters => setters
 0143        .SetProperty(t => t.Name, triggerUpdateBusinessModel.Name)
 0144        .SetProperty(t => t.Url, triggerUpdateBusinessModel.Url)
 0145        .SetProperty(t => t.HttpMethodId, triggerUpdateBusinessModel.HttpMethodId)
 0146        .SetProperty(t => t.Body, triggerUpdateBusinessModel.Body)
 0147        .SetProperty(t => t.SkipOnFailure, triggerUpdateBusinessModel.SkipOnFailure)
 0148        .SetProperty(t => t.ApiKeyInsertLocationId, triggerUpdateBusinessModel.ApiKeyInsertLocationId)
 0149        .SetProperty(t => t.ApiKeyFieldName, triggerUpdateBusinessModel.ApiKeyFieldName)
 0150        .SetProperty(t => t.ApiKeyId, triggerUpdateBusinessModel.ApiKeyId)) == 1;
 0151  }
 152
 153  public async Task<bool> TestDeleteTriggerAsync(int triggerId)
 0154  {
 0155    var depeendencies = await _context.FlowDetails.Where(t => t.TriggerId == triggerId).CountAsync();
 0156    if (depeendencies > 0)
 0157    {
 0158      throw new LgdxValidation400Expection(nameof(triggerId), $"This trigger has been used by {depeendencies} details in
 159    }
 0160    return true;
 0161  }
 162
 163  public async Task<bool> DeleteTriggerAsync(int triggerId)
 0164  {
 0165    return await _context.Triggers.Where(t => t.Id == triggerId)
 0166      .ExecuteDeleteAsync() == 1;
 0167  }
 168
 169  public async Task<IEnumerable<TriggerSearchBusinessModel>> SearchTriggersAsync(string? name)
 0170  {
 0171    var n = name ?? string.Empty;
 0172    return await _context.Triggers.AsNoTracking()
 0173      .Where(w => w.Name.ToLower().Contains(n.ToLower()))
 0174      .Take(10)
 0175      .Select(t => new TriggerSearchBusinessModel {
 0176        Id = t.Id,
 0177        Name = t.Name,
 0178      })
 0179      .ToListAsync();
 0180  }
 181
 182  private string GetRobotName(Guid robotId)
 0183  {
 0184    return _context.Robots.AsNoTracking().Where(r => r.Id == robotId).FirstOrDefault()?.Name ?? string.Empty;
 0185  }
 186
 187  private string GetRealmName(int realmId)
 0188  {
 0189    return _context.Realms.AsNoTracking().Where(r => r.Id == realmId).FirstOrDefault()?.Name ?? string.Empty;
 0190  }
 191
 192  private string GeneratePresetValue(int i, AutoTask autoTask)
 0193  {
 0194    return i switch
 0195    {
 0196      (int)TriggerPresetValue.AutoTaskId => $"{autoTask.Id}",
 0197      (int)TriggerPresetValue.AutoTaskName => $"\"{autoTask.Name}\"",
 0198      (int)TriggerPresetValue.AutoTaskCurrentProgressId => $"{autoTask.CurrentProgressId}",
 0199      (int)TriggerPresetValue.AutoTaskCurrentProgressName => $"\"{autoTask.CurrentProgress.Name!}\"",
 0200      (int)TriggerPresetValue.RobotId => $"\"{autoTask.AssignedRobotId}\"",
 0201      (int)TriggerPresetValue.RobotName => $"\"{GetRobotName((Guid)autoTask.AssignedRobotId!)}\"",
 0202      (int)TriggerPresetValue.RealmId => $"\"{autoTask.RealmId}\"",
 0203      (int)TriggerPresetValue.RealmName => $"\"{GetRealmName(autoTask.RealmId)}\"",
 0204      _ => string.Empty,
 0205    };
 0206  }
 207
 208  public async Task InitialiseTriggerAsync(AutoTask autoTask, FlowDetail flowDetail)
 0209  {
 0210    var trigger = await _context.Triggers.AsNoTracking()
 0211      .Where(t => t.Id == flowDetail.TriggerId)
 0212      .FirstOrDefaultAsync();
 0213    if (trigger == null)
 0214    {
 0215      return;
 216    }
 217
 0218    var bodyDictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(trigger.Body ?? "{}");
 0219    if (bodyDictionary != null)
 0220    {
 221      // Replace Preset Value
 0222      foreach (var pair in bodyDictionary)
 0223      {
 0224        if (pair.Value.Length >= 5) // ((1)) has 5 characters
 0225        {
 0226          if (int.TryParse(pair.Value[2..^2], out int p))
 0227          {
 0228            bodyDictionary[pair.Key] = GeneratePresetValue(p, autoTask);
 0229          }
 0230        }
 0231      }
 232      // Add Next Token
 0233      if (flowDetail.AutoTaskNextControllerId != (int) AutoTaskNextController.Robot && autoTask.NextToken != null)
 0234      {
 0235        bodyDictionary.Add("NextToken", autoTask.NextToken);
 0236      }
 237
 0238      await _bus.Publish(new AutoTaskTriggerContract {
 0239        Trigger = trigger,
 0240        Body = bodyDictionary,
 0241        AutoTaskId = autoTask.Id,
 0242        AutoTaskName = autoTask.Name!,
 0243        RobotId = (Guid)autoTask.AssignedRobotId!,
 0244        RobotName = GetRobotName((Guid)autoTask.AssignedRobotId!),
 0245        RealmId = autoTask.RealmId,
 0246        RealmName = GetRealmName(autoTask.RealmId),
 0247      });
 0248    }
 0249  }
 250
 251  public async Task RetryTriggerAsync(AutoTask autoTask, Trigger trigger, string body)
 0252  {
 0253    var bodyDictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(body ?? "{}");
 0254    if (bodyDictionary != null)
 0255    {
 0256      await _bus.Publish(new AutoTaskTriggerContract {
 0257        Trigger = trigger,
 0258        Body = bodyDictionary,
 0259        AutoTaskId = autoTask.Id,
 0260        AutoTaskName = autoTask.Name!,
 0261        RobotId = (Guid)autoTask.AssignedRobotId!,
 0262        RobotName = GetRobotName((Guid)autoTask.AssignedRobotId!),
 0263        RealmId = autoTask.RealmId,
 0264        RealmName = GetRealmName(autoTask.RealmId),
 0265      });
 0266    }
 0267  }
 268}