Rework social post manager to support multiple client types

This commit is contained in:
Matt Isenhower 2022-12-08 19:47:56 -08:00
parent 42d97c6bf0
commit 2cc68d13bd
7 changed files with 120 additions and 68 deletions

View File

@ -1,58 +1,54 @@
import fs from 'fs/promises';
import mkdirp from 'mkdirp';
import prefixedConsole from "../common/prefixedConsole.mjs";
import ScreenshotHelper from "../screenshots/ScreenshotHelper.mjs";
import StatusGenerator from "./generators/StatusGenerator.mjs";
import TwitterClient from "./TwitterClient.mjs";
export default class StatusGeneratorManager
{
/** @type {StatusGenerator[]} */
generators;
/** @type {TwitterClient} */
client;
/** @type {Client[]} */
clients;
/** @type {ScreenshotHelper} */
screenshotHelper;
constructor(generators = []) {
console(generator = null, client = null) {
let prefixes = ['Social', generator?.name, client?.name].filter(s => s);
return prefixedConsole(...prefixes);
}
constructor(generators = [], clients = []) {
this.generators = generators;
this.client = new TwitterClient;
this.clients = clients;
this.screenshotHelper = new ScreenshotHelper;
}
async sendStatuses() {
async shouldPost(generator) {
for (let client of this.clients) {
if (await generator.shouldPost(client)) {
return true;
}
}
return false;
}
async sendStatuses(force = false) {
for (let generator of this.generators) {
if (!(await generator.shouldPost())) {
if (!force && !(await this.shouldPost(generator))) {
this.console(generator).info('No status to post, skipping');
continue;
}
await generator.sendStatus(this.screenshotHelper, this.client);
}
await this.screenshotHelper.close();
}
async testStatuses() {
for (let generator of this.generators) {
let dir = 'temp';
await mkdirp(dir);
let status = await generator.getStatus(this.screenshotHelper);
let imgFilename = `temp/${generator.key}.png`;
await fs.writeFile(imgFilename, status.media[0].file);
let text = [
'Status:',
status.status,
'',
'Alt text:',
status.media[0].altText,
].join('\n');
let textFilename = `temp/${generator.key}.txt`;
await fs.writeFile(textFilename, text);
for (let client of this.clients) {
this.console(generator, client).info('Posting...');
await client.send(status, generator);
await generator.updatelastPostCache(client);
}
}
await this.screenshotHelper.close();

View File

@ -0,0 +1,16 @@
import Status from "../Status.mjs";
import StatusGenerator from "../generators/StatusGenerator.mjs";
export default class Client
{
key;
name;
/**
* @param {Status} status
* @param {StatusGenerator} generator
*/
async send(status, generator) {
//
}
}

View File

@ -0,0 +1,28 @@
import fs from 'fs/promises';
import mkdirp from 'mkdirp';
import Client from "./Client.mjs";
export default class FileWriter extends Client {
key = 'file';
name = 'FileWriter';
dir = 'temp';
async send(status, generator) {
await mkdirp(this.dir);
let imgFilename = `${this.dir}/${generator.key}.png`;
await fs.writeFile(imgFilename, status.media[0].file);
let text = [
'Status:',
status.status,
'',
'Alt text:',
status.media[0].altText,
].join('\n');
let textFilename = `${this.dir}/${generator.key}.txt`;
await fs.writeFile(textFilename, text);
}
}

View File

@ -1,12 +1,17 @@
import { TwitterApi } from "twitter-api-v2";
import Status from "./Status.mjs";
import Client from "./Client.mjs";
export default class TwitterClient
export default class TwitterClient extends Client
{
key = 'twitter';
name = 'Twitter';
/** @var {TwitterApi} */
#api;
constructor() {
super();
this.#api = new TwitterApi({
appKey: process.env.TWITTER_CONSUMER_KEY,
appSecret: process.env.TWITTER_CONSUMER_SECRET,
@ -15,10 +20,7 @@ export default class TwitterClient
});
}
/**
* @param {Status} status
*/
async send(status) {
async send(status, generator) {
// Upload images
let mediaIds = await Promise.all(
status.media.map(async m => {

View File

@ -19,10 +19,10 @@ export default class SalmonRunGearStatus extends StatusGenerator
return gear?.__splatoon3ink_id;
}
async shouldPost() {
async shouldPost(client) {
let gear = await this.getGear();
let cachedId = await this.lastPostCache.getData();
let cachedId = await this.lastPostCache(client).getData();
return gear?.__splatoon3ink_id && gear?.__splatoon3ink_id !== cachedId;
}

View File

@ -3,7 +3,7 @@ import { createPinia, setActivePinia } from 'pinia';
import { useCoopDataStore, useFestivalsDataStore, useGearDataStore, useSchedulesDataStore } from '../../../src/stores/data.mjs';
import prefixedConsole from '../../common/prefixedConsole.mjs';
import Status from '../Status.mjs';
import TwitterClient from '../TwitterClient.mjs';
import Client from '../clients/Client.mjs';
import ScreenshotHelper from '../../screenshots/ScreenshotHelper.mjs';
import { getTopOfCurrentHour } from '../../common/util.mjs';
import { useTimeStore } from '../../../src/stores/time.mjs';
@ -16,15 +16,13 @@ export default class StatusGenerator
/** @type {Console} */
get console() {
this._console ??= prefixedConsole('Twitter', this.name);
this._console ??= prefixedConsole('Social', this.name);
return this._console;
}
get lastPostCache() {
this._lastPostCache ??= new ValueCache(`twitter.${this.key}`);
return this._lastPostCache;
lastPostCache(client) {
return new ValueCache(`social.${client.key}.${this.key}`);
}
async preparePinia() {
@ -50,33 +48,23 @@ export default class StatusGenerator
return useTimeStore().now;
}
async shouldPost() {
async shouldPost(client) {
let currentTime = await this.getDataTime();
let cachedTime = await this.lastPostCache.getData();
let cachedTime = await this.lastPostCache(client).getData();
return currentTime && (!cachedTime || (currentTime > cachedTime));
}
async updatelastPostCache() {
async updatelastPostCache(client) {
let currentTime = await this.getDataTime();
await this.lastPostCache.setData(currentTime);
}
/**
* @param {ScreenshotHelper} screenshotHelper
* @param {TwitterClient} twitterClient
*/
async sendStatus(screenshotHelper, twitterClient) {
let status = await this.getStatus(screenshotHelper);
await twitterClient.send(status);
await this.updatelastPostCache();
await this.lastPostCache(client).setData(currentTime);
}
/** @param {ScreenshotHelper} screenshotHelper */
async getStatus(screenshotHelper) {
this.console.log('Generating status...');
const status = new Status;
status.status = await this._getStatus();

View File

@ -1,3 +1,5 @@
import FileWriter from "./clients/FileWriter.mjs";
import TwitterClient from "./clients/TwitterClient.mjs";
import DailyDropGearStatus from "./generators/DailyDropGearStatus.mjs";
import RegularGearStatus from "./generators/RegularGearStatus.mjs";
import SalmonRunGearStatus from "./generators/SalmonRunGearStatus.mjs";
@ -6,21 +8,41 @@ import SchedulesStatus from "./generators/SchedulesStatus.mjs";
import SplatfestResultsStatus from "./generators/SplatfestResultsStatus.mjs";
import StatusGeneratorManager from "./StatusGeneratorManager.mjs"
export function defaultTwitterManager() {
return new StatusGeneratorManager([
function defaultStatusGenerators() {
return [
new SchedulesStatus,
new DailyDropGearStatus,
new RegularGearStatus,
new SalmonRunStatus,
new SalmonRunGearStatus,
new SplatfestResultsStatus,
]);
];
}
function defaultClients() {
return [
new TwitterClient,
];
}
export function defaultStatusGeneratorManager() {
return new StatusGeneratorManager(
defaultStatusGenerators(),
defaultClients(),
);
}
export function testStatusGeneratorManager() {
return new StatusGeneratorManager(
defaultStatusGenerators(),
[new FileWriter],
);
}
export function sendStatuses() {
return defaultTwitterManager().sendStatuses();
return defaultStatusGeneratorManager().sendStatuses();
}
export function testStatuses() {
return defaultTwitterManager().testStatuses();
return testStatusGeneratorManager().sendStatuses(true);
}