diff --git a/poptimal.js b/poptimal.js index 7a0e334..ce920bf 100644 --- a/poptimal.js +++ b/poptimal.js @@ -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 media_url = `${cf.base_url}/api/v1/media`; const headers = { @@ -199,36 +245,45 @@ async function post_image(image, alt_text, cf) { const bodyjson = await resp.text(); const response = JSON.parse(bodyjson); 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['Content-Type'] = 'application/json'; const resp2 = await fetch(status_url, { method: 'POST', headers: headers, - body: JSON.stringify({ media_ids: [ media_id ] }) + body: JSON.stringify(status_body) }); 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()); + 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 paramsfile = cf['working_dir'] + '/' + jsfn; + console.log(`Generating ${imgfile}`); const params = await load_or_random_params(argv.p); const colourf = params.palette === 'grayscale' ? cf['grayscale'] : cf['colour']; @@ -238,19 +293,18 @@ async function main() { const svg = poptimal_svg(params); const opts = { - background: 'rgba(255, 255, 255, 1.0)', - fitTo: { - mode: 'width', - value: argv.s, - }, - }; + background: 'rgba(255, 255, 255, 1.0)', + fitTo: { + mode: 'width', + value: argv.s, + }, + }; const resvg = new Resvg(svg, opts); const pngData = resvg.render(); const pngBuffer = pngData.asPng(); await promises.writeFile(imgfile, pngBuffer); - // generate the alt_text last to check the image file histogram // so we don't include obscured colours const hist = await get_histogram(imgfile); @@ -258,12 +312,34 @@ async function main() { params.alt_text = alt_text; await save_params(paramsfile, params); console.log(alt_text); - console.log(imgfile); - if( cf['base_url'] ) { - await post_image(imgfile, alt_text, cf); + if( cf['base_url'] && !argv.n ) { + await post_image(imgfile, alt_text, cf, reply_to); } } +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();