//called when the timeout has expired which was waiting for pending changes. private static void PostChangesToSlack(IssueDtoEventArgs args, GlobalConfigurationWidgetData <SlackConfigData> data, string channel, DateTime createDate) { var issueManager = GeminiApp.GetManager <IssueManager>(args.User); var userManager = GeminiApp.GetManager <UserManager>(args.User); var userDto = userManager.Convert(args.User); var issue = issueManager.Get(args.Issue.Id); //get the changelog of all changes since the create date (minus a second to avoid missing the initial change) var changelog = issueManager.GetChangeLog(issue, userDto, userDto, createDate.AddSeconds(-1)); changelog.RemoveAll(c => c.Entity.AttributeChanged == ItemAttributeVisibility.AssociatedComments); // No need to show comments in updates as we already do that in the AfterComment event. if (changelog.Count == 0) { return; // No changes made! } var fields = changelog .Select(a => new { title = a.Field, value = StripHTML(a.FullChange), _short = a.Entity.AttributeChanged != ItemAttributeVisibility.Description && a.Entity.AttributeChanged != ItemAttributeVisibility.AssociatedComments }); QuickSlack.Send(data.Value.SlackAPIEndpoint, channel, string.Format("{0} updated issue <{1}|{2} - {3}>" , args.User.Fullname, args.BuildIssueUrl(args.Issue), args.Issue.IssueKey, args.Issue.Title), "details attached", "good", //todo colors here based on something fields.ToArray()); }
public IssueDto updateCustomField(IssueDtoEventArgs args) { var CustomFieldName = "Original Estimate"; var customFieldData = args.Issue.CustomFields[CustomFieldName]; if (customFieldData != null && customFieldData.Entity.Data == string.Empty && (args.Issue.EstimatedHours > 0 || args.Issue.EstimatedMinutes > 0)) { customFieldData.Entity.Data = string.Format("{0}h {1}m", args.Issue.EstimatedHours, args.Issue.EstimatedMinutes); } return(args.Issue); }
public override IssueDto BeforeUpdateFull(IssueDtoEventArgs args) { try { IssueDto issue = AddDomain(args, true); AddSuperuser(args.Context, issue, args.User, true); return(issue); } catch (Exception exception) { GeminiApp.LogException(exception, false, exception.Message); return(args.Issue); } }
private bool Send(IssueDtoEventArgs args) { var token = args.Context.GlobalConfigurationWidgetStore.Get <string>(AppConstants.AppId); if (token == null || token.Value.IsEmpty()) { return(false); } var client = new RestClient("https://api.flowdock.com/v1/messages"); var request = new RestRequest("team_inbox/{token}", Method.POST); request.AddUrlSegment("token", token.Value); request.AddHeader("Accept", "application/json"); request.JsonSerializer = new JsonSerializer(); request.Method = Method.POST; request.RequestFormat = DataFormat.Json; request.AddHeader("Content-Type", "application/json"); var data = new { source = "Gemini", project = args.Issue.ProjectCode, from_name = args.User.Fullname, from_address = args.User.Email, subject = args.Issue.Title, content = args.Issue.Description, tags = args.Issue.Type, link = args.BuildIssueUrl(args.Issue) }; //reply_to request.AddBody(data); var response = client.Execute(request); var content = response.Content; return(true); }
/*** * the functionality here hinges on the "changelog" that is provided from the gemini api * We don't have to keep track of changes. * This method looks for a recent change for this user/issue and extends the timeout if there is * a match, otherwise it creates an executor to post to slack after 60 seconds * */ public override void AfterUpdateFull(IssueDtoEventArgs args) { var data = GetConfig(args.Context); if (data == null || data.Value == null) { return; } string channel = GetProjectChannel(args.Issue.Entity.ProjectId, data.Value.ProjectChannels); if (channel == null || channel.Trim().Length == 0) { return; } lock (_executorDictionary) { var key = Tuple.Create(args.User.Username, args.Issue.Id); //look for an existing username/issue# combination indicating that a change was recently //made in which case we just extend the timeout IdleTimeoutExecutor ex = null; if (!_executorDictionary.TryGetValue(key, out ex)) { DateTime createDate = DateTime.Now.AddSeconds(-1); _executorDictionary[key] = new IdleTimeoutExecutor(DateTime.Now.AddSeconds(data.Value.SecondsToQueueChanges), //this executes x seconds after the last update, initially set above ^^ then adjusted on subsequent //updates further below (in the else) based on the key being found () => { PostChangesToSlack(args, data, channel, createDate); }, () => { _executorDictionary.Remove(key); new SessionManager().CloseSession(); // Need to close the DB connection as we span a new thread. }, _executorDictionary); } else { //we found a pending executor, just update the timeout to be later ex.Timeout = DateTime.Now.AddSeconds(data.Value.SecondsToQueueChanges); } } base.AfterUpdateFull(args); }
/// <summary> /// Check if the "Fremd-ID"-field is "" /// Then it checks if the ID is in the description /// if there is no ID, then it checks in the comment section /// </summary> /// <param name="args">Properties of the task</param> /// <returns>args.Issue</returns> public IssueDto BeforeUpdateFull(IssueDtoEventArgs args) { try { List <IssueCommentDto> comments = args.Issue.Comments; string description = args.Issue.Description; string fieldName = GetAppConfigValue("customFieldName"); CustomFieldDataDto fremdIDField = args.Issue.CustomFields.Find(field => field.Name.Equals(fieldName)); if (fremdIDField.Entity.Data == "") { if (FindID(description) != "") { string beforeValue = fremdIDField.Entity.Data; string valueIdDescription = FindID(description); string fieldValue = fremdIDField.Entity.Data = valueIdDescription; CreateAuditlog(args.Context, args.Issue.Entity.Id, args.Issue.Entity.ProjectId, fremdIDField, beforeValue, fieldValue); } else { foreach (IssueCommentDto comment in comments) { string valueIdComment = FindID(comment.Entity.Comment); if (valueIdComment != "") { string fieldValue = fremdIDField.Entity.Data = valueIdComment; IssueManager issueManager = new IssueManager(GeminiApp.Cache(), GeminiApp.UserContext(), args.Context); issueManager.Update(args.Issue); CreateAuditlog(args.Context, args.Issue.Entity.Id, args.Issue.Entity.ProjectId, fremdIDField, "", fieldValue); break; } } } } } catch (Exception e) { int issueID = args.Issue.Id; string message = string.Format("IssueID: {0}", issueID); GeminiApp.LogException(e, false, message); } return(args.Issue); }
public IssueDto BeforeUpdateFull(IssueDtoEventArgs args) { return(args.Issue); }
public override void AfterUpdateFull(IssueDtoEventArgs args) { // Do something with args.Issue }
public override void AfterUpdateFull(IssueDtoEventArgs args) { CallWebhook(GetData(args.Context, false, true), args.Issue, args.Previous); }
public override void AfterCreateFull(IssueDtoEventArgs args) { CallWebhook(GetData(args.Context, true, false), args.Issue, null); }
public override void AfterUpdateFull(IssueDtoEventArgs args) { Send(args); }
public override IssueDto BeforeUpdateFull(IssueDtoEventArgs args) { return(updateCustomField(args)); }
/// <summary> /// Add the domain to the custom field, and create an auditlog if it hasn't just been created. /// </summary> /// <param name="args"></param> /// <param name="createAudit"></param> /// <returns></returns> private IssueDto AddDomain(IssueDtoEventArgs args, bool createAudit) { try { IssueDto issue = args.Issue; Helper helper = new Helper(); if ((issue.CustomFields.Count > 0) && (!issue.CustomFields.Find(field => field.Name.Equals(helper.GetAppConfigValue("customFieldNameDomain"))).ToString().Equals(null))) { CustomFieldDataDto erstellerOEField = issue.CustomFields.Find(field => field.Name.Equals(helper.GetAppConfigValue("customFieldNameDomain"))); // If there is no domain in the OE-Field yet // Depending on whether you want users to manually change the OE-Field or not, .FormattedData or .Entity.Data could be chosen. if (string.IsNullOrEmpty(erstellerOEField.Entity.Data)) { string maildomain = helper.FindDomain(issue.OriginatorData); // If no email address in OriginatorData present, take email address from creator user if (string.IsNullOrEmpty(maildomain)) { UserManager userManager = new UserManager(GeminiApp.Cache(), GeminiApp.UserContext(), args.Context); int userId; // If created via another user if (issue.Entity.ReportedBy > 0) { userId = issue.Entity.ReportedBy; } // If not else { userId = args.User.Id; } UserDto creatorUser = userManager.Get(userId); maildomain = helper.FindDomain(creatorUser.Entity.Email); } // OriginatorData has email address, no more actions required string beforeValue = erstellerOEField.FormattedData; erstellerOEField.Entity.Data = maildomain; erstellerOEField.FormattedData = maildomain; // Keep in mind that args.Issue / issue / erstellerOEField are reference types, not value types // Create auditlog if being called from BeforeUpdateFull with the auditlog flag if (createAudit) { // beforeValue -> previous value (args.Issue FormattedData -> previous value) // issue FormattedData -> new value (alternatively erstellerOEField.FormattedData) if (!beforeValue.Equals(helper.GetFormattedDataErstellerOE(issue))) { IssueManager issueManager = new IssueManager(GeminiApp.Cache(), GeminiApp.UserContext(), args.Context); helper.CreateAuditlog(args.Context, args.Issue.Entity.Id, args.Issue.Entity.ProjectId, erstellerOEField, beforeValue, erstellerOEField.FormattedData, args.User.Id, args.User.Fullname); } } } return(issue); } return(args.Issue); } catch (Exception exception) { GeminiApp.LogException(exception, false, exception.Message); return(args.Issue); } }
public IssueDto BeforeIssueCopy(IssueDtoEventArgs args) { return(args.Issue); }
public IssueDto CopyIssueComplete(IssueDtoEventArgs args) { return(args.Issue); }
public override void AfterCreateFull(IssueDtoEventArgs args) { if (!GeminiApp.Config.EmailAlertsEnabled) { return; } var data = args.Context.GlobalConfigurationWidgetStore.Get <List <CreateItemNotifierData> >(AppConstants.AppId); if (data == null || data.Value == null || data.Value.Count == 0) { return; } var projectData = data.Value.Find(d => d.ProjectId.GetValueOrDefault() == args.Issue.Entity.ProjectId); if (projectData == null) { projectData = data.Value.Find(d => d.ProjectId.GetValueOrDefault() == 0); } if (projectData == null) { return; } var alertService = GeminiApp.Container.Resolve <IAlertTemplates>(); var alerts = alertService.GetAll(); var template = alerts.Find(t => t.Id == projectData.TemplateId); if (template == null) { return; } AlertsTemplateHelper helper = new AlertsTemplateHelper(alerts, args.GeminiUrls[0].Key); using (var cache = GeminiApp.Container.Resolve <ICacheContainer>()) { var userManager = GeminiApp.GetManager <UserManager>(cache.Users.Find(u => u.Active && u.ProjectGroups.Where(p => p.ProjectGroupId == Constants.GlobalGroupAdministrators && p.UserId == u.Id).Any())); var metaManager = new MetaManager(userManager); var types = metaManager.TypeGetAll(); var OrganizationManager = new OrganizationManager(userManager); var organizations = OrganizationManager.GetAll(); var permissions = new PermissionSetManager(userManager); var permissionSets = permissions.GetAll(); PermissionsManager permissionManager = null; foreach (var user in projectData.UserIds) { var userDto = userManager.Get(user); if (userDto != null && userDto.Entity.Active) { if (permissionManager == null) { permissionManager = new PermissionsManager(userDto, types, permissionSets, organizations, userManager.UserContext.Config.HelpDeskModeGroup, false); } else { permissionManager = permissionManager.Copy(userDto); } if (!permissionManager.CanSeeItem(args.Issue.Project, args.Issue) || !userDto.Entity.EmailMe) { continue; } var body = helper.Build(template, args.Issue, userDto); string emailLog; EmailHelper.Send(GeminiApp.Config, body.Key.HasValue() ? body.Key : string.Format("[{0}] {1}", args.Issue.IssueKey, args.Issue.Title), body.Value, userDto.Entity.Email, userDto.Entity.Fullname, true, out emailLog); } } } }