CREATE EXTENSION plpython3u;

CREATE TABLE blockbot_config (
	hostname TEXT,
	token TEXT
);

CREATE TABLE blockbot_opt_out (
	account_id BIGINT
);

CREATE FUNCTION blockbot_notify(
	blocker TEXT,
	blocked TEXT,
	unblock BOOLEAN,
	hostname TEXT,
	token TEXT
) RETURNS boolean AS $$
import requests

# non-local user, ignore
if '@' in blocked:
	return False

direction = 'unblocked' if unblock else 'blocked'

r = requests.post(
	f'https://{hostname}/api/v1/statuses',
	headers={'Authorization': f'Bearer {token}'},
	data={
		'status': f'@{blocked} You have been {direction} by {blocker}.',
		'visibility': 'direct',
	}
)
return r.status_code == 200
$$ LANGUAGE plpython3u;

CREATE FUNCTION blockbot_trigger_inner(
	blocker BIGINT,
	blocked BIGINT,
	unblock BOOLEAN
) RETURNS boolean AS $$
WITH handles AS (
	SELECT id, username || (CASE WHEN domain IS NULL THEN '' ELSE '@' || domain END) AS handle
	FROM accounts
	WHERE id IN ($1, $2)
)
SELECT blockbot_notify(
	(SELECT handle FROM handles WHERE id = $1),
	(SELECT handle FROM handles WHERE id = $2),
	unblock,
	(SELECT hostname FROM blockbot_config),
	(SELECT token FROM blockbot_config)
)
WHERE blocker NOT IN (
	SELECT blocker
	FROM blockbot_opt_out
	WHERE account_id = $1
);
$$ LANGUAGE SQL;

CREATE FUNCTION blockbot_block() RETURNS TRIGGER AS $$ BEGIN
	PERFORM * FROM blockbot_trigger_inner(NEW.account_id, NEW.target_account_id, false);
	RETURN NEW;
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER blockbot_block_trigger
AFTER INSERT ON blocks
FOR EACH ROW
EXECUTE FUNCTION blockbot_block();

CREATE FUNCTION blockbot_unblock() RETURNS TRIGGER AS $$ BEGIN
	PERFORM * FROM blockbot_trigger_inner(OLD.account_id, OLD.target_account_id, true);
	RETURN NULL;
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER blockbot_unblock_trigger
AFTER DELETE ON blocks
FOR EACH ROW
EXECUTE FUNCTION blockbot_unblock();
