UNPKG

@memberjunction/actions-bizapps-social

Version:

Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer

250 lines 9.74 kB
"use strict"; 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