@memberjunction/actions-bizapps-social
Version:
Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer
227 lines (203 loc) • 9.66 kB
text/typescript
import { RegisterClass } from '@memberjunction/global';
import { LinkedInBaseAction } from '../linkedin-base.action';
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
import { LogStatus, LogError } from '@memberjunction/core';
import { BaseAction } from '@memberjunction/actions';
/**
* Action to get follower statistics for LinkedIn profiles and organizations
*/
(BaseAction, 'LinkedInGetFollowersAction')
export class LinkedInGetFollowersAction extends LinkedInBaseAction {
/**
* Get follower statistics for personal profile or organization
*/
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
const { Params, ContextUser } = params;
try {
// Initialize OAuth
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
if (!await this.initializeOAuth(companyIntegrationId)) {
throw new Error('Failed to initialize OAuth connection');
}
// Extract parameters
const entityType = this.getParamValue(Params, 'EntityType') || 'organization'; // 'personal' or 'organization'
const organizationId = this.getParamValue(Params, 'OrganizationID');
const includeGrowth = this.getParamValue(Params, 'IncludeGrowth') === true;
const timeRange = this.getParamValue(Params, 'TimeRange'); // Optional: {start: Date, end: Date}
let followerData: any = {};
if (entityType === 'organization') {
// Get organization follower statistics
let organizationUrn: string;
if (!organizationId) {
// Get first admin organization if not specified
const orgs = await this.getAdminOrganizations();
if (orgs.length === 0) {
throw new Error('No organizations found. Please specify OrganizationID.');
}
organizationUrn = orgs[0].urn;
LogStatus(`Using organization: ${orgs[0].name}`);
} else {
organizationUrn = `urn:li:organization:${organizationId}`;
}
followerData = await this.getOrganizationFollowers(organizationUrn, includeGrowth, timeRange);
} else {
// Get personal profile follower statistics
const userUrn = await this.getCurrentUserUrn();
followerData = await this.getPersonalFollowers(userUrn);
}
// Update output parameters
const outputParams = [...Params];
const followersParam = outputParams.find(p => p.Name === 'FollowerCount');
if (followersParam) followersParam.Value = followerData.followerCount || 0;
const statsParam = outputParams.find(p => p.Name === 'FollowerStatistics');
if (statsParam) statsParam.Value = followerData;
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Successfully retrieved follower statistics`,
Params: outputParams
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
Success: false,
ResultCode: 'ERROR',
Message: `Failed to get followers: ${errorMessage}`,
Params
};
}
}
/**
* Get organization follower statistics
*/
private async getOrganizationFollowers(organizationUrn: string, includeGrowth: boolean, timeRange?: any): Promise<any> {
try {
const params: any = {
q: 'organizationalEntity',
organizationalEntity: organizationUrn
};
// Add time range if specified for growth metrics
if (includeGrowth && timeRange) {
params.timeIntervals = `List((start:${new Date(timeRange.start).getTime()},end:${new Date(timeRange.end || Date.now()).getTime()}))`;
}
// Get follower statistics
const response = await this.axiosInstance.get('/organizationalEntityFollowerStatistics', { params });
const stats = response.data.elements?.[0] || {};
const result: any = {
followerCount: stats.followerCounts?.organicFollowerCount || 0,
paidFollowerCount: stats.followerCounts?.paidFollowerCount || 0,
totalFollowerCount: (stats.followerCounts?.organicFollowerCount || 0) + (stats.followerCounts?.paidFollowerCount || 0)
};
// Add growth metrics if requested
if (includeGrowth && stats.followerGains) {
result.followerGrowth = {
organicGains: stats.followerGains.organicFollowerGains || 0,
paidGains: stats.followerGains.paidFollowerGains || 0,
totalGains: (stats.followerGains.organicFollowerGains || 0) + (stats.followerGains.paidFollowerGains || 0),
timeRange: timeRange
};
}
// Get demographics if available
try {
const demographicsResponse = await this.axiosInstance.get('/organizationalEntityFollowerStatistics', {
params: {
q: 'organizationalEntity',
organizationalEntity: organizationUrn,
projection: '(followerCountsByAssociationType,followerCountsByFunction,followerCountsBySeniority,followerCountsByIndustry,followerCountsByRegion,followerCountsByCountry)'
}
});
if (demographicsResponse.data.elements?.[0]) {
const demographics = demographicsResponse.data.elements[0];
result.demographics = {
byFunction: demographics.followerCountsByFunction || [],
bySeniority: demographics.followerCountsBySeniority || [],
byIndustry: demographics.followerCountsByIndustry || [],
byRegion: demographics.followerCountsByRegion || [],
byCountry: demographics.followerCountsByCountry || []
};
}
} catch (error) {
LogError(`Failed to get follower demographics: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return result;
} catch (error) {
LogError(`Failed to get organization followers: ${error instanceof Error ? error.message : 'Unknown error'}`);
throw error;
}
}
/**
* Get personal profile follower statistics
* Note: LinkedIn provides limited follower data for personal profiles
*/
private async getPersonalFollowers(userUrn: string): Promise<any> {
try {
// Get basic profile information including follower count
const response = await this.axiosInstance.get('/me', {
params: {
projection: '(id,firstName,lastName,headline,publicProfileUrl,followerCount)'
}
});
return {
followerCount: response.data.followerCount || 0,
profileInfo: {
name: `${response.data.firstName?.localized?.en_US || ''} ${response.data.lastName?.localized?.en_US || ''}`.trim(),
headline: response.data.headline?.localized?.en_US || '',
profileUrl: response.data.publicProfileUrl || ''
},
note: 'LinkedIn API provides limited follower statistics for personal profiles'
};
} catch (error) {
LogError(`Failed to get personal followers: ${error instanceof Error ? error.message : 'Unknown error'}`);
// Fallback: return basic info
return {
followerCount: 0,
note: 'Unable to retrieve follower count for personal profile',
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
/**
* Define the parameters this action expects
*/
public get Params(): ActionParam[] {
return [
...this.commonSocialParams,
{
Name: 'EntityType',
Type: 'Input',
Value: 'organization' // 'personal' or 'organization'
},
{
Name: 'OrganizationID',
Type: 'Input',
Value: null
},
{
Name: 'IncludeGrowth',
Type: 'Input',
Value: false
},
{
Name: 'TimeRange',
Type: 'Input',
Value: null // Optional: {start: Date, end: Date}
},
{
Name: 'FollowerCount',
Type: 'Output',
Value: null
},
{
Name: 'FollowerStatistics',
Type: 'Output',
Value: null
}
];
}
/**
* Get action description
*/
public get Description(): string {
return 'Retrieves follower statistics for LinkedIn personal profiles or organization pages, including demographics and growth metrics where available';
}
}