<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Creating Activity Stories</title><link>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories</link><description /><dc:language>en-US</dc:language><generator>14.0.0.586 14</generator><item><title>Creating Activity Stories</title><link>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories</link><pubDate>Wed, 05 Aug 2020 15:12:32 GMT</pubDate><guid isPermaLink="false">9002ccb8-cb89-4c27-b389-c7aae1e782af</guid><dc:creator>Former Member</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories#comments</comments><description>Current Revision posted to Developer Training by Former Member on 08/05/2020 15:12:32&lt;br /&gt;
&lt;p&gt;Activity stories are shown in the activity stream and provide an easy way for users to stay engaged with a community.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="Why_should_I_create_Activity_Stories" name="Why_should_I_create_Activity_Stories"&gt;&lt;/a&gt;Why should I create Activity Stories?&lt;/h2&gt;
&lt;p&gt;When performing actions upon a community providing a stream of events will allow the users to view relevant&amp;nbsp;activity at a glance. A good example is when a user adds an event to the calendar an activity story can provide users with information about the event without requiring navigating to the calendar.&amp;nbsp;Verint Community provides support for posting&amp;nbsp;stories&amp;nbsp;in the activity stream&amp;nbsp;via&amp;nbsp;the [[api-documentation:ILikeableContentType Plugin Type|IActivityStoryType Plugin Type]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Creating_an_Activity_Story_Type" name="Creating_an_Activity_Story_Type"&gt;&lt;/a&gt;Creating an Activity Story Type&lt;/h2&gt;
&lt;p&gt;To add support for creating stories, implement the [[api-documentation:IActivityStoryType Plugin Type|IActivityStoryType]] plugin (which requires a reference to Telligent.Evolution.Api.dll, Telligent.Evolution.Components.dll and Telligent.Evolution.Core.dll). The IActivityStoryType interface extends IPlugin to add support for activity stories.&lt;/p&gt;
&lt;p&gt;To begin you&amp;#39;ll need to generate a GUID&amp;nbsp;and return it as the&amp;nbsp;&lt;code&gt;StoryTypeId&lt;/code&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid StoryTypeId
{
    get { return new Guid(&amp;quot;247A9821-75F0-4E57-81E2-15B9D0578491&amp;quot;); }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;After setting up the Id the story type requires a &lt;code&gt;StoryTypeName&lt;/code&gt; and &lt;code&gt;StoryTypeDescription&lt;/code&gt;. This name and description is used to identify the story type in administration and stream configuration user interfaces.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string StoryTypeName
{
    get { return &amp;quot;My Activity Stories&amp;quot;; }
}

public string StoryTypeDescription
{
    get { return &amp;quot;Controls activity stories for My Activity Stories.&amp;quot;; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Activity stories can allow the user to delete an individual story. The &lt;code&gt;CanDeleteStory&lt;/code&gt; method accepts a &lt;code&gt;storyId&lt;/code&gt; and a &lt;code&gt;userId&lt;/code&gt;. These id&amp;#39;s can be used to find a particular story as well as a user. Then depending on your requirements return a boolean value that will identify if the&amp;nbsp;user can remove the provided story. In this sample we verify the user is logged in and not an anonymous user then we determine if the user is one of the actors of the story. An actor can be defined&amp;nbsp;as a user or users that took part in&amp;nbsp;a particular activity.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public bool CanDeleteStory(Guid storyId, int userId)
{
    Apis.Get&amp;lt;EventLog&amp;gt;().Write(&amp;quot;&amp;quot;, new EventLogEntryWriteOptions());
    // unregistered users cannot delete stories
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    var userIsRegistered = user != null &amp;amp;&amp;amp; !user.IsSystemAccount.GetValueOrDefault(false);
    if (!userIsRegistered)
    {
        return false;
    }

    // actors can delete
    var story = Apis.Get&amp;lt;ActivityStories&amp;gt;().Get(storyId);
    return story != null &amp;amp;&amp;amp; story.Actors != null &amp;amp;&amp;amp; story.Actors.ToList().Exists(actor =&amp;gt; actor.UserId == userId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ContentTypeIds&lt;/code&gt; property returns a list of content type IDs related to the content that the stories belong to (see [[Creating Custom Applications and Content||creating content]] for more details about content types). Typically it is related to one content type but can be set to multiple types.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid[] ContentTypeIds
{
    get { return new[] { Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId }; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In some cases the story must present a summary of the activity. Usually it is recommended to limit the summary to a single sentence. This is done in the &lt;code&gt;GetPreviewHtml&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetPreviewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The full view of the story will be processed through the &lt;code&gt;GetViewHtml&lt;/code&gt; method. This method receives two parameters [[api-documentation:IActivityStory In-Process API Supplementary Type|IActivityStory]]&lt;code&gt;&amp;nbsp;story&lt;/code&gt;&amp;nbsp;and [[api-documentation:Target Plugin Supplementary Type|Target]]&lt;code&gt;&amp;nbsp;target&lt;/code&gt;. The &lt;code&gt;IActivityStory&lt;/code&gt;&amp;nbsp;parameter can be used to retrieve the content associated with the story. This is&amp;nbsp;used to build the HTML response&amp;nbsp;and the target identifies where the rendered content will be included (such as&amp;nbsp;Web,&amp;nbsp;Email or&amp;nbsp;Other) to enable the story to render an appropriate version of the story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetViewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;lt;p&amp;gt;User was authenticated.&amp;lt;/p&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The community also needs to know who the primary user is for a given story. This process is left up to the story type&amp;nbsp;via the&amp;nbsp;&lt;code&gt;GetPrimaryUser&amp;nbsp;&lt;/code&gt;method. In this sample we simply return the last actor that is responsible for the given story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public int? GetPrimaryUser(IActivityStory story)
{
    if (story == null || story.Actors == null || story.Actors.Count == 0)
    {
        return null;
    }

    return story.Actors.Last().UserId;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The controller is the final member of the activity story type. The [[api-documentation:IActivityStoryController Plugin Supplementary Type|IActivityStoryController]]&amp;nbsp;provides the functionality to create, update or delete stories in Verint Community.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private IActivityStoryController _storyController;

public void SetController(IActivityStoryController controller)
{
    _storyController = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the complete source of our sample activity story type&amp;nbsp;plugin:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/0474_2E00_MyActivityStory_2E00_cs"&gt;community.telligent.com/.../0474_2E00_MyActivityStory_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_the_Activity_Story_Controller" name="Using_the_Activity_Story_Controller"&gt;&lt;/a&gt;Using the Activity Story Controller&lt;/h2&gt;
&lt;p&gt;In this sample we added a private method called &lt;code&gt;UserAuthenticatedStory&lt;/code&gt;. It is called when a user is authenticated, it demonstrates how to create a new story in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    Apis.Get&amp;lt;Users&amp;gt;().Events.AfterAuthenticate += Events_AfterAuthenticate;
}

private void Events_AfterAuthenticate(UserAfterAuthenticateEventArgs e)
{
    UserAuthenticatedStory(e.Id.GetValueOrDefault());
}

.
.
.

private void UserAuthenticatedStory(int userId)
{
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    
    _storyController.Create(new ActivityStoryCreateOptions
    {
        ContentId = user.ContentId,
        ContentTypeId = Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId,
        LastUpdate = DateTime.UtcNow,
        Actors = new List&amp;lt;ActivityStoryActor&amp;gt;
        {
            new ActivityStoryActor 
            { 
                UserId = user.Id.GetValueOrDefault(),
                Verb = &amp;quot;Add&amp;quot;,
                Date = DateTime.UtcNow
            }
        }
    });
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is a sample of what the story looks like in the activity stream.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png"&gt;&lt;img style="border:1px solid #dedede;" alt=" " src="/resized-image/__size/365x183/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: IActivityStoryType&lt;/div&gt;
</description></item><item><title>Creating Activity Stories</title><link>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories/revision/2</link><pubDate>Tue, 04 Aug 2020 21:32:14 GMT</pubDate><guid isPermaLink="false">9002ccb8-cb89-4c27-b389-c7aae1e782af</guid><dc:creator>Former Member</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories#comments</comments><description>Revision 2 posted to Developer Training by Former Member on 08/04/2020 21:32:14&lt;br /&gt;
&lt;p&gt;Activity stories are shown in the activity stream and provide an easy way for users to stay engaged with a community.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="Why_should_I_create_Activity_Stories" name="Why_should_I_create_Activity_Stories"&gt;&lt;/a&gt;Why should I create Activity Stories?&lt;/h2&gt;
&lt;p&gt;When performing actions upon a community providing a stream of events will allow the users to view relevant&amp;nbsp;activity at a glance. A good example is when a user adds an event to the calendar an activity story can provide users with information about the event without requiring navigating to the calendar.&amp;nbsp;Telligent Community provides support for posting&amp;nbsp;stories&amp;nbsp;in the activity stream&amp;nbsp;via&amp;nbsp;the [[api-documentation:ILikeableContentType Plugin Type|IActivityStoryType Plugin Type]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Creating_an_Activity_Story_Type" name="Creating_an_Activity_Story_Type"&gt;&lt;/a&gt;Creating an Activity Story Type&lt;/h2&gt;
&lt;p&gt;To add support for creating stories, implement the [[api-documentation:IActivityStoryType Plugin Type|IActivityStoryType]] plugin (which requires a reference to Telligent.Evolution.Api.dll, Telligent.Evolution.Components.dll and Telligent.Evolution.Core.dll). The IActivityStoryType interface extends IPlugin to add support for activity stories.&lt;/p&gt;
&lt;p&gt;To begin you&amp;#39;ll need to generate a GUID&amp;nbsp;and return it as the&amp;nbsp;&lt;code&gt;StoryTypeId&lt;/code&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid StoryTypeId
{
    get { return new Guid(&amp;quot;247A9821-75F0-4E57-81E2-15B9D0578491&amp;quot;); }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;After setting up the Id the story type requires a &lt;code&gt;StoryTypeName&lt;/code&gt; and &lt;code&gt;StoryTypeDescription&lt;/code&gt;. This name and description is used to identify the story type in administration and stream configuration user interfaces.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string StoryTypeName
{
    get { return &amp;quot;My Activity Stories&amp;quot;; }
}

public string StoryTypeDescription
{
    get { return &amp;quot;Controls activity stories for My Activity Stories.&amp;quot;; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Activity stories can allow the user to delete an individual story. The &lt;code&gt;CanDeleteStory&lt;/code&gt; method accepts a &lt;code&gt;storyId&lt;/code&gt; and a &lt;code&gt;userId&lt;/code&gt;. These id&amp;#39;s can be used to find a particular story as well as a user. Then depending on your requirements return a boolean value that will identify if the&amp;nbsp;user can remove the provided story. In this sample we verify the user is logged in and not an anonymous user then we determine if the user is one of the actors of the story. An actor can be defined&amp;nbsp;as a user or users that took part in&amp;nbsp;a particular activity.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public bool CanDeleteStory(Guid storyId, int userId)
{
    Apis.Get&amp;lt;EventLog&amp;gt;().Write(&amp;quot;&amp;quot;, new EventLogEntryWriteOptions());
    // unregistered users cannot delete stories
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    var userIsRegistered = user != null &amp;amp;&amp;amp; !user.IsSystemAccount.GetValueOrDefault(false);
    if (!userIsRegistered)
    {
        return false;
    }

    // actors can delete
    var story = Apis.Get&amp;lt;ActivityStories&amp;gt;().Get(storyId);
    return story != null &amp;amp;&amp;amp; story.Actors != null &amp;amp;&amp;amp; story.Actors.ToList().Exists(actor =&amp;gt; actor.UserId == userId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ContentTypeIds&lt;/code&gt; property returns a list of content type IDs related to the content that the stories belong to (see [[Creating Custom Applications and Content||creating content]] for more details about content types). Typically it is related to one content type but can be set to multiple types.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid[] ContentTypeIds
{
    get { return new[] { Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId }; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In some cases the story must present a summary of the activity. Usually it is recommended to limit the summary to a single sentence. This is done in the &lt;code&gt;GetPreviewHtml&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetPreviewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The full view of the story will be processed through the &lt;code&gt;GetViewHtml&lt;/code&gt; method. This method receives two parameters [[api-documentation:IActivityStory In-Process API Supplementary Type|IActivityStory]]&lt;code&gt;&amp;nbsp;story&lt;/code&gt;&amp;nbsp;and [[api-documentation:Target Plugin Supplementary Type|Target]]&lt;code&gt;&amp;nbsp;target&lt;/code&gt;. The &lt;code&gt;IActivityStory&lt;/code&gt;&amp;nbsp;parameter can be used to retrieve the content associated with the story. This is&amp;nbsp;used to build the HTML response&amp;nbsp;and the target identifies where the rendered content will be included (such as&amp;nbsp;Web,&amp;nbsp;Email or&amp;nbsp;Other) to enable the story to render an appropriate version of the story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetViewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;lt;p&amp;gt;User was authenticated.&amp;lt;/p&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The community also needs to know who the primary user is for a given story. This process is left up to the story type&amp;nbsp;via the&amp;nbsp;&lt;code&gt;GetPrimaryUser&amp;nbsp;&lt;/code&gt;method. In this sample we simply return the last actor that is responsible for the given story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public int? GetPrimaryUser(IActivityStory story)
{
    if (story == null || story.Actors == null || story.Actors.Count == 0)
    {
        return null;
    }

    return story.Actors.Last().UserId;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The controller is the final member of the activity story type. The [[api-documentation:IActivityStoryController Plugin Supplementary Type|IActivityStoryController]]&amp;nbsp;provides the functionality to create, update or delete stories in Telligent Community.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private IActivityStoryController _storyController;

public void SetController(IActivityStoryController controller)
{
    _storyController = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the complete source of our sample activity story type&amp;nbsp;plugin:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/0474_2E00_MyActivityStory_2E00_cs"&gt;community.telligent.com/.../0474_2E00_MyActivityStory_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_the_Activity_Story_Controller" name="Using_the_Activity_Story_Controller"&gt;&lt;/a&gt;Using the Activity Story Controller&lt;/h2&gt;
&lt;p&gt;In this sample we added a private method called &lt;code&gt;UserAuthenticatedStory&lt;/code&gt;. It is called when a user is authenticated, it demonstrates how to create a new story in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    Apis.Get&amp;lt;Users&amp;gt;().Events.AfterAuthenticate += Events_AfterAuthenticate;
}

private void Events_AfterAuthenticate(UserAfterAuthenticateEventArgs e)
{
    UserAuthenticatedStory(e.Id.GetValueOrDefault());
}

.
.
.

private void UserAuthenticatedStory(int userId)
{
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    
    _storyController.Create(new ActivityStoryCreateOptions
    {
        ContentId = user.ContentId,
        ContentTypeId = Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId,
        LastUpdate = DateTime.UtcNow,
        Actors = new List&amp;lt;ActivityStoryActor&amp;gt;
        {
            new ActivityStoryActor 
            { 
                UserId = user.Id.GetValueOrDefault(),
                Verb = &amp;quot;Add&amp;quot;,
                Date = DateTime.UtcNow
            }
        }
    });
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is a sample of what the story looks like in the activity stream.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png"&gt;&lt;img style="border:1px solid #dedede;" alt=" " src="/resized-image/__size/365x183/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: IActivityStoryType&lt;/div&gt;
</description></item><item><title>Creating Activity Stories</title><link>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories/revision/1</link><pubDate>Thu, 13 Jun 2019 19:28:26 GMT</pubDate><guid isPermaLink="false">9002ccb8-cb89-4c27-b389-c7aae1e782af</guid><dc:creator>Ben Tiedt</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65099/creating-activity-stories#comments</comments><description>Revision 1 posted to Developer Training by Ben Tiedt on 06/13/2019 19:28:26&lt;br /&gt;
&lt;p&gt;Activity stories are shown in the activity stream and provide an easy way for users to stay engaged with a community.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="Why_should_I_create_Activity_Stories" name="Why_should_I_create_Activity_Stories"&gt;&lt;/a&gt;Why should I create Activity Stories?&lt;/h2&gt;
&lt;p&gt;When performing actions upon a community providing a stream of events will allow the users to view relevant&amp;nbsp;activity at a glance. A good example is when a user adds an event to the calendar an activity story can provide users with information about the event without requiring navigating to the calendar.&amp;nbsp;Telligent Community provides support for posting&amp;nbsp;stories&amp;nbsp;in the activity stream&amp;nbsp;via&amp;nbsp;the [[api-documentation:ILikeableContentType Plugin Type|IActivityStoryType Plugin Type]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Creating_an_Activity_Story_Type" name="Creating_an_Activity_Story_Type"&gt;&lt;/a&gt;Creating an Activity Story Type&lt;/h2&gt;
&lt;p&gt;To add support for creating stories, implement the [[api-documentation:IActivityStoryType Plugin Type|IActivityStoryType]] plugin (which requires a reference to Telligent.Evolution.Api.dll, Telligent.Evolution.Components.dll and Telligent.Evolution.Core.dll). The IActivityStoryType interface extends IPlugin to add support for activity stories.&lt;/p&gt;
&lt;p&gt;To begin you&amp;#39;ll need to generate a GUID&amp;nbsp;and return it as the&amp;nbsp;&lt;code&gt;StoryTypeId&lt;/code&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid StoryTypeId
{
    get { return new Guid(&amp;quot;247A9821-75F0-4E57-81E2-15B9D0578491&amp;quot;); }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;After setting up the Id the story type requires a &lt;code&gt;StoryTypeName&lt;/code&gt; and &lt;code&gt;StoryTypeDescription&lt;/code&gt;. This name and description is used to identify the story type in administration and stream configuration user interfaces.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string StoryTypeName
{
    get { return &amp;quot;My Activity Stories&amp;quot;; }
}

public string StoryTypeDescription
{
    get { return &amp;quot;Controls activity stories for My Activity Stories.&amp;quot;; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Activity stories can allow the user to delete an individual story. The &lt;code&gt;CanDeleteStory&lt;/code&gt; method accepts a &lt;code&gt;storyId&lt;/code&gt; and a &lt;code&gt;userId&lt;/code&gt;. These id&amp;#39;s can be used to find a particular story as well as a user. Then depending on your requirements return a boolean value that will identify if the&amp;nbsp;user can remove the provided story. In this sample we verify the user is logged in and not an anonymous user then we determine if the user is one of the actors of the story. An actor can be defined&amp;nbsp;as a user or users that took part in&amp;nbsp;a particular activity.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public bool CanDeleteStory(Guid storyId, int userId)
{
    Apis.Get&amp;lt;EventLog&amp;gt;().Write(&amp;quot;&amp;quot;, new EventLogEntryWriteOptions());
    // unregistered users cannot delete stories
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    var userIsRegistered = user != null &amp;amp;&amp;amp; !user.IsSystemAccount.GetValueOrDefault(false);
    if (!userIsRegistered)
    {
        return false;
    }

    // actors can delete
    var story = Apis.Get&amp;lt;ActivityStories&amp;gt;().Get(storyId);
    return story != null &amp;amp;&amp;amp; story.Actors != null &amp;amp;&amp;amp; story.Actors.ToList().Exists(actor =&amp;gt; actor.UserId == userId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ContentTypeIds&lt;/code&gt; property returns a list of content type IDs related to the content that the stories belong to (see [[Creating Custom Applications and Content||creating content]] for more details about content types). Typically it is related to one content type but can be set to multiple types.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public Guid[] ContentTypeIds
{
    get { return new[] { Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId }; }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In some cases the story must present a summary of the activity. Usually it is recommended to limit the summary to a single sentence. This is done in the &lt;code&gt;GetPreviewHtml&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetPreviewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The full view of the story will be processed through the &lt;code&gt;GetViewHtml&lt;/code&gt; method. This method receives two parameters [[api-documentation:IActivityStory In-Process API Supplementary Type|IActivityStory]]&lt;code&gt;&amp;nbsp;story&lt;/code&gt;&amp;nbsp;and [[api-documentation:Target Plugin Supplementary Type|Target]]&lt;code&gt;&amp;nbsp;target&lt;/code&gt;. The &lt;code&gt;IActivityStory&lt;/code&gt;&amp;nbsp;parameter can be used to retrieve the content associated with the story. This is&amp;nbsp;used to build the HTML response&amp;nbsp;and the target identifies where the rendered content will be included (such as&amp;nbsp;Web,&amp;nbsp;Email or&amp;nbsp;Other) to enable the story to render an appropriate version of the story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetViewHtml(IActivityStory story, Target target)
{
    var content = Apis.Get&amp;lt;Contents&amp;gt;().Get(story.ContentId.GetValueOrDefault(), story.ContentTypeId.GetValueOrDefault());
    if (content == null) return null;

    return string.Format(&amp;quot;&amp;lt;h3&amp;gt;{0}&amp;lt;/h3&amp;gt;&amp;lt;p&amp;gt;User was authenticated.&amp;lt;/p&amp;gt;&amp;quot;, content.HtmlName(&amp;quot;Web&amp;quot;));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The community also needs to know who the primary user is for a given story. This process is left up to the story type&amp;nbsp;via the&amp;nbsp;&lt;code&gt;GetPrimaryUser&amp;nbsp;&lt;/code&gt;method. In this sample we simply return the last actor that is responsible for the given story.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public int? GetPrimaryUser(IActivityStory story)
{
    if (story == null || story.Actors == null || story.Actors.Count == 0)
    {
        return null;
    }

    return story.Actors.Last().UserId;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The controller is the final member of the activity story type. The [[api-documentation:IActivityStoryController Plugin Supplementary Type|IActivityStoryController]]&amp;nbsp;provides the functionality to create, update or delete stories in Telligent Community.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;private IActivityStoryController _storyController;

public void SetController(IActivityStoryController controller)
{
    _storyController = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the complete source of our sample activity story type&amp;nbsp;plugin:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/0474_2E00_MyActivityStory_2E00_cs"&gt;community.telligent.com/.../0474_2E00_MyActivityStory_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_the_Activity_Story_Controller" name="Using_the_Activity_Story_Controller"&gt;&lt;/a&gt;Using the Activity Story Controller&lt;/h2&gt;
&lt;p&gt;In this sample we added a private method called &lt;code&gt;UserAuthenticatedStory&lt;/code&gt;. It is called when a user is authenticated, it demonstrates how to create a new story in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    Apis.Get&amp;lt;Users&amp;gt;().Events.AfterAuthenticate += Events_AfterAuthenticate;
}

private void Events_AfterAuthenticate(UserAfterAuthenticateEventArgs e)
{
    UserAuthenticatedStory(e.Id.GetValueOrDefault());
}

.
.
.

private void UserAuthenticatedStory(int userId)
{
    var user = Apis.Get&amp;lt;Users&amp;gt;().Get(new UsersGetOptions { Id = userId });
    
    _storyController.Create(new ActivityStoryCreateOptions
    {
        ContentId = user.ContentId,
        ContentTypeId = Apis.Get&amp;lt;Users&amp;gt;().ContentTypeId,
        LastUpdate = DateTime.UtcNow,
        Actors = new List&amp;lt;ActivityStoryActor&amp;gt;
        {
            new ActivityStoryActor 
            { 
                UserId = user.Id.GetValueOrDefault(),
                Verb = &amp;quot;Add&amp;quot;,
                Date = DateTime.UtcNow
            }
        }
    });
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is a sample of what the story looks like in the activity stream.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png"&gt;&lt;img style="border:1px solid #dedede;" src="/resized-image/__size/365x183/__key/communityserver-wikis-components-files/00-00-00-12-83/1856.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>