Basic version of replying to mentions with a freshly generated image

This commit is contained in:
Mike Lynch 2025-08-25 16:08:06 +10:00
parent c4e3c45a4d
commit c922ea49a1

View File

@ -179,7 +179,53 @@ function poptimal_svg(params) {
} }
async function post_image(image, alt_text, cf) { async function send_replies(argv, cf) {
const mentionsjson = await promises.readFile(cf.mentions);
const oldids = JSON.parse(mentionsjson).map((m) => m.id);
const params = new URLSearchParams();
params.append("types", ["mention"]) // this isn't working
// so filter it explicitly
const notifications_url = `${cf.base_url}/api/v1/notifications?${params}`;
const headers = {
'Authorization': `Bearer ${cf.access_token}`,
};
const resp = await fetch(notifications_url, {
method: 'GET',
headers: headers,
});
const bodyjson = await resp.text();
const response = JSON.parse(bodyjson);
const mentions = response.filter((s) => s.type === "mention").map((s) => {
const account = s.account;
const status = s.status;
return {
id: s.id,
created: s.created_at,
status_id: status.id,
account: account.acct,
url: status.url
};
});
const newmentions = mentions.filter((m) => !oldids.includes(m.id));
for (const mention of newmentions) {
console.log(`new mention ${mention.id}`);
const reply = {
id: mention.status_id,
account: `@${mention.account}`
};
post(argv, cf, reply);
}
if( !argv.n ) {
await promises.writeFile(cf.mentions, JSON.stringify(mentions, null, 4));
}
}
async function post_image(image, alt_text, cf, reply) {
const status_url = `${cf.base_url}/api/v1/statuses`; const status_url = `${cf.base_url}/api/v1/statuses`;
const media_url = `${cf.base_url}/api/v1/media`; const media_url = `${cf.base_url}/api/v1/media`;
const headers = { const headers = {
@ -199,36 +245,45 @@ async function post_image(image, alt_text, cf) {
const bodyjson = await resp.text(); const bodyjson = await resp.text();
const response = JSON.parse(bodyjson); const response = JSON.parse(bodyjson);
const media_id = response["id"]; const media_id = response["id"];
const status_body = { media_ids: [ media_id ] };
if( reply ) {
status_body["in_reply_to_id"] = reply.id;
status_body["status"] = reply.account;
}
headers['Accept'] = 'application/json'; headers['Accept'] = 'application/json';
headers['Content-Type'] = 'application/json'; headers['Content-Type'] = 'application/json';
const resp2 = await fetch(status_url, { const resp2 = await fetch(status_url, {
method: 'POST', method: 'POST',
headers: headers, headers: headers,
body: JSON.stringify({ media_ids: [ media_id ] }) body: JSON.stringify(status_body)
}); });
const bodyjson2 = await resp2.text(); const bodyjson2 = await resp2.text();
} }
async function main() {
const argv = yargs(hideBin(process.argv))
.usage("Usage: -s SIZE [-o output] -c config.json [-p params.json]")
.default('s', 1200)
.default('c', 'config.json').argv;
const cfjson = await promises.readFile(argv.c);
const cf = JSON.parse(cfjson); function make_unique_filename(reply_to) {
const ts = String(Date.now()); const ts = String(Date.now());
if( reply_to ) {
return `${ts}-${reply_to.id}`;
} else {
return ts;
}
}
const fn = (argv.o || ts) + '.png';
const jsfn = (argv.o || ts) + '.json'; async function post(argv, cf, reply_to) {
const filebase = make_unique_filename(reply_to);
const fn = (argv.o || filebase) + '.png';
const jsfn = (argv.o || filebase) + '.json';
const imgfile = cf['working_dir'] + '/' + fn; const imgfile = cf['working_dir'] + '/' + fn;
const paramsfile = cf['working_dir'] + '/' + jsfn; const paramsfile = cf['working_dir'] + '/' + jsfn;
console.log(`Generating ${imgfile}`);
const params = await load_or_random_params(argv.p); const params = await load_or_random_params(argv.p);
const colourf = params.palette === 'grayscale' ? cf['grayscale'] : cf['colour']; const colourf = params.palette === 'grayscale' ? cf['grayscale'] : cf['colour'];
@ -250,7 +305,6 @@ async function main() {
const pngBuffer = pngData.asPng(); const pngBuffer = pngData.asPng();
await promises.writeFile(imgfile, pngBuffer); await promises.writeFile(imgfile, pngBuffer);
// generate the alt_text last to check the image file histogram // generate the alt_text last to check the image file histogram
// so we don't include obscured colours // so we don't include obscured colours
const hist = await get_histogram(imgfile); const hist = await get_histogram(imgfile);
@ -258,12 +312,34 @@ async function main() {
params.alt_text = alt_text; params.alt_text = alt_text;
await save_params(paramsfile, params); await save_params(paramsfile, params);
console.log(alt_text); console.log(alt_text);
console.log(imgfile); if( cf['base_url'] && !argv.n ) {
if( cf['base_url'] ) { await post_image(imgfile, alt_text, cf, reply_to);
await post_image(imgfile, alt_text, cf);
} }
} }
async function main() {
const argv = yargs(hideBin(process.argv))
.usage("Usage: -s SIZE [-o output] [-r] [-n] -c config.json [-p params.json]")
.default('s', 1200)
.default('c', 'config.json').argv;
const cfjson = await promises.readFile(argv.c);
const cf = JSON.parse(cfjson);
if( argv.r ) {
if( !cf.base_url ) {
console.log("Can't check mentions without base_url");
} else {
send_replies(argv, cf);
}
} else {
post(argv, cf);
}
}
main(); main();