@memberjunction/actions-bizapps-social
Version:
Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer
250 lines • 9.74 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BufferSearchPostsAction = void 0;
const global_1 = require("@memberjunction/global");
const buffer_base_action_1 = require("../buffer-base.action");
const actions_1 = require("@memberjunction/actions");
/**
* Action to search historical posts in Buffer across profiles and date ranges
*/
let BufferSearchPostsAction = class BufferSearchPostsAction extends buffer_base_action_1.BufferBaseAction {
/**
* Search for posts in Buffer
*/
async InternalRunAction(params) {
const { Params, ContextUser } = params;
try {
// Get parameters
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
const query = this.getParamValue(Params, 'Query');
const profileIds = this.getParamValue(Params, 'ProfileIDs');
const hashtags = this.getParamValue(Params, 'Hashtags');
const startDate = this.getParamValue(Params, 'StartDate');
const endDate = this.getParamValue(Params, 'EndDate');
const limit = this.getParamValue(Params, 'Limit') || 100;
const offset = this.getParamValue(Params, 'Offset') || 0;
const includeAnalytics = this.getParamValue(Params, 'IncludeAnalytics') !== false;
// Validate required parameters
if (!companyIntegrationId) {
throw new Error('CompanyIntegrationID is required');
}
// Initialize OAuth
if (!await this.initializeOAuth(companyIntegrationId)) {
return {
Success: false,
ResultCode: 'INVALID_TOKEN',
Message: 'Failed to initialize Buffer OAuth connection',
Params
};
}
// Search posts
const searchParams = {
query,
hashtags,
startDate: startDate ? new Date(startDate) : undefined,
endDate: endDate ? new Date(endDate) : undefined,
limit,
offset,
profileIds
};
const posts = await this.searchPosts(searchParams);
// Optionally fetch analytics for each post
if (includeAnalytics) {
for (const post of posts) {
try {
const analytics = await this.getAnalytics(post.id);
post.analytics = this.normalizeAnalytics(analytics);
}
catch (error) {
// Log but don't fail if analytics fetch fails
console.warn(`Failed to fetch analytics for post ${post.id}:`, error);
}
}
}
// Create search statistics
const statistics = this.generateSearchStatistics(posts, searchParams);
// Create summary
const summary = {
totalResults: posts.length,
searchCriteria: {
query: query || null,
hashtags: hashtags || [],
dateRange: {
start: startDate || null,
end: endDate || null
},
profileIds: profileIds || [],
limit,
offset
},
statistics,
topPerformingPost: this.findTopPerformingPost(posts),
dateRange: {
earliest: posts.length > 0 ? posts[posts.length - 1].publishedAt : null,
latest: posts.length > 0 ? posts[0].publishedAt : null
}
};
// Update output parameters
const outputParams = [...Params];
const postsParam = outputParams.find(p => p.Name === 'Posts');
if (postsParam)
postsParam.Value = posts;
const summaryParam = outputParams.find(p => p.Name === 'Summary');
if (summaryParam)
summaryParam.Value = summary;
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Found ${posts.length} posts matching search criteria`,
Params: outputParams
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
const resultCode = this.mapBufferError(error);
return {
Success: false,
ResultCode: resultCode,
Message: `Failed to search posts: ${errorMessage}`,
Params
};
}
}
/**
* Generate statistics from search results
*/
generateSearchStatistics(posts, searchParams) {
const stats = {
postsByProfile: {},
postsByMonth: {},
postsByDayOfWeek: {},
postsByHour: {},
averageEngagements: 0,
totalEngagements: 0,
postsWithMedia: 0,
hashtagFrequency: {}
};
let totalEngagements = 0;
let postsWithEngagementData = 0;
for (const post of posts) {
// Count by profile
stats.postsByProfile[post.profileId] = (stats.postsByProfile[post.profileId] || 0) + 1;
// Count by month
const month = post.publishedAt.toISOString().substring(0, 7); // YYYY-MM
stats.postsByMonth[month] = (stats.postsByMonth[month] || 0) + 1;
// Count by day of week
const dayOfWeek = post.publishedAt.toLocaleDateString('en-US', { weekday: 'long' });
stats.postsByDayOfWeek[dayOfWeek] = (stats.postsByDayOfWeek[dayOfWeek] || 0) + 1;
// Count by hour
const hour = post.publishedAt.getHours();
stats.postsByHour[hour] = (stats.postsByHour[hour] || 0) + 1;
// Count posts with media
if (post.mediaUrls && post.mediaUrls.length > 0) {
stats.postsWithMedia++;
}
// Calculate engagements
if (post.analytics) {
totalEngagements += post.analytics.engagements;
postsWithEngagementData++;
}
// Extract and count hashtags
const hashtags = this.extractHashtags(post.content);
for (const hashtag of hashtags) {
stats.hashtagFrequency[hashtag] = (stats.hashtagFrequency[hashtag] || 0) + 1;
}
}
// Calculate averages
stats.totalEngagements = totalEngagements;
stats.averageEngagements = postsWithEngagementData > 0 ?
totalEngagements / postsWithEngagementData : 0;
return stats;
}
/**
* Find the top performing post by engagements
*/
findTopPerformingPost(posts) {
if (posts.length === 0)
return null;
return posts.reduce((top, post) => {
if (!top || (post.analytics?.engagements || 0) > (top.analytics?.engagements || 0)) {
return post;
}
return top;
}, posts[0]);
}
/**
* Define the parameters this action expects
*/
get Params() {
return [
...this.commonSocialParams,
{
Name: 'Query',
Type: 'Input',
Value: null
},
{
Name: 'ProfileIDs',
Type: 'Input',
Value: null
},
{
Name: 'Hashtags',
Type: 'Input',
Value: null
},
{
Name: 'StartDate',
Type: 'Input',
Value: null
},
{
Name: 'EndDate',
Type: 'Input',
Value: null
},
{
Name: 'Limit',
Type: 'Input',
Value: 100
},
{
Name: 'Offset',
Type: 'Input',
Value: 0
},
{
Name: 'IncludeAnalytics',
Type: 'Input',
Value: true
},
{
Name: 'Posts',
Type: 'Output',
Value: null
},
{
Name: 'Summary',
Type: 'Output',
Value: null
}
];
}
/**
* Metadata about this action
*/
get Description() {
return 'Searches historical posts in Buffer across profiles with support for date ranges, hashtags, and content queries';
}
};
exports.BufferSearchPostsAction = BufferSearchPostsAction;
exports.BufferSearchPostsAction = BufferSearchPostsAction = __decorate([
(0, global_1.RegisterClass)(actions_1.BaseAction, 'BufferSearchPostsAction')
], BufferSearchPostsAction);
//# sourceMappingURL=search-posts.action.js.map