mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-16 20:01:08 +00:00
fix(growth): x engagement approve now actually posts the reply (#3340)
The xeng_approve and xeng_edit_submit handlers marked the reply as approved in state.db but never called postToX(). Replies were silently stuck in "ready to post on X" limbo forever. Both handlers now call postToX(replyText, sourceTweetId) so the reply goes out as an actual threaded reply on X, and the Slack card shows the live tweet URL. Mirrors the tweet_approve flow. Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>
This commit is contained in:
parent
37d144dfd6
commit
c1cfd7ef2d
1 changed files with 68 additions and 27 deletions
|
|
@ -1657,7 +1657,7 @@ app.action("tweet_skip", async ({ ack, body, client }) => {
|
|||
}
|
||||
});
|
||||
|
||||
// --- xeng_approve: mark engagement reply as approved ---
|
||||
// --- xeng_approve: post engagement reply to X ---
|
||||
app.action("xeng_approve", async ({ ack, body, client }) => {
|
||||
await ack();
|
||||
const payload = toRecord("actions" in body && Array.isArray(body.actions) ? body.actions[0] : null);
|
||||
|
|
@ -1668,19 +1668,39 @@ app.action("xeng_approve", async ({ ack, body, client }) => {
|
|||
const tweet = findTweet(db, engageId);
|
||||
if (!tweet || tweet.status !== "pending") return;
|
||||
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "approved",
|
||||
actionedBy: userId,
|
||||
});
|
||||
logTweetDecision(tweet, "approved");
|
||||
const xResult = await postToX(tweet.tweetText, tweet.sourceTweetId ?? undefined);
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await replaceButtonsWithStatus(
|
||||
client,
|
||||
tweet.slackChannel,
|
||||
tweet.slackTs,
|
||||
`:white_check_mark: Reply approved by <@${userId}> — ready to post on X`,
|
||||
);
|
||||
if (xResult.ok) {
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "posted",
|
||||
actionedBy: userId,
|
||||
postedText: tweet.tweetText,
|
||||
});
|
||||
logTweetDecision(tweet, "approved");
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await replaceButtonsWithStatus(
|
||||
client,
|
||||
tweet.slackChannel,
|
||||
tweet.slackTs,
|
||||
`:white_check_mark: Reply posted by <@${userId}> <${xResult.tweetUrl}|view on X>`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "error",
|
||||
actionedBy: userId,
|
||||
});
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await client.chat
|
||||
.postMessage({
|
||||
channel: tweet.slackChannel,
|
||||
thread_ts: tweet.slackTs,
|
||||
text: `:x: Failed to post reply: ${xResult.error}`,
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1734,7 +1754,7 @@ app.action("xeng_edit", async ({ ack, body, client }) => {
|
|||
.catch(() => {});
|
||||
});
|
||||
|
||||
// --- xeng_edit_submit: modal submitted with edited reply ---
|
||||
// --- xeng_edit_submit: modal submitted with edited reply, post to X ---
|
||||
app.view("xeng_edit_submit", async ({ ack, view, body, client }) => {
|
||||
await ack();
|
||||
const engageId = view.private_metadata;
|
||||
|
|
@ -1754,20 +1774,41 @@ app.view("xeng_edit_submit", async ({ ack, view, body, client }) => {
|
|||
engageId,
|
||||
]);
|
||||
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "approved",
|
||||
actionedBy: userId,
|
||||
postedText: editedText,
|
||||
});
|
||||
logTweetDecision(tweet, "edited", editedText);
|
||||
const xResult = await postToX(editedText, tweet.sourceTweetId ?? undefined);
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await replaceButtonsWithStatus(
|
||||
client,
|
||||
tweet.slackChannel,
|
||||
tweet.slackTs,
|
||||
`:white_check_mark: Reply edited & approved by <@${userId}> — ready to post on X`,
|
||||
);
|
||||
if (xResult.ok) {
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "posted",
|
||||
actionedBy: userId,
|
||||
postedText: editedText,
|
||||
});
|
||||
logTweetDecision(tweet, "edited", editedText);
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await replaceButtonsWithStatus(
|
||||
client,
|
||||
tweet.slackChannel,
|
||||
tweet.slackTs,
|
||||
`:white_check_mark: Reply edited & posted by <@${userId}> <${xResult.tweetUrl}|view on X>`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
updateTweetStatus(db, engageId, {
|
||||
status: "error",
|
||||
actionedBy: userId,
|
||||
postedText: editedText,
|
||||
});
|
||||
logTweetDecision(tweet, "edited", editedText);
|
||||
|
||||
if (tweet.slackChannel && tweet.slackTs) {
|
||||
await client.chat
|
||||
.postMessage({
|
||||
channel: tweet.slackChannel,
|
||||
thread_ts: tweet.slackTs,
|
||||
text: `:x: Reply edited but failed to post: ${xResult.error}`,
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue