mirror of
https://github.com/block/buzz.git
synced 2026-10-31 22:41:12 +00:00
Clarify Buzz's community and agent model, update public setup guidance, and replace internal screenshots with staged product assets.
195 lines
13 KiB
Bash
Executable File
195 lines
13 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Seed deterministic moderation reports and product feedback for local dashboard review.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
cd "${REPO_ROOT}"
|
|
|
|
if [[ -f ".env" ]]; then
|
|
set -o allexport
|
|
# shellcheck disable=SC1091
|
|
source .env
|
|
set +o allexport
|
|
fi
|
|
|
|
export PGHOST="${PGHOST:-localhost}"
|
|
export PGPORT="${PGPORT:-5432}"
|
|
export PGUSER="${PGUSER:-buzz}"
|
|
export PGPASSWORD="${PGPASSWORD:-buzz_dev}"
|
|
export PGDATABASE="${PGDATABASE:-buzz}"
|
|
|
|
if command -v psql >/dev/null 2>&1; then
|
|
run_psql() {
|
|
PGPASSWORD="${PGPASSWORD}" psql -h "${PGHOST}" -p "${PGPORT}" \
|
|
-U "${PGUSER}" -d "${PGDATABASE}" "$@"
|
|
}
|
|
elif docker exec buzz-postgres psql --version >/dev/null 2>&1; then
|
|
run_psql() {
|
|
docker exec -i -e PGPASSWORD="${PGPASSWORD}" buzz-postgres \
|
|
psql -U "${PGUSER}" -d "${PGDATABASE}" "$@"
|
|
}
|
|
else
|
|
echo "error: neither psql nor buzz-postgres docker psql is available" >&2
|
|
exit 1
|
|
fi
|
|
|
|
community_id="$(run_psql -At -v ON_ERROR_STOP=1 -c "
|
|
SELECT id
|
|
FROM communities
|
|
WHERE lower(host) IN ('localhost:3000', 'localhost', '127.0.0.1:3000', '127.0.0.1')
|
|
ORDER BY CASE lower(host)
|
|
WHEN 'localhost:3000' THEN 1
|
|
WHEN 'localhost' THEN 2
|
|
WHEN '127.0.0.1:3000' THEN 3
|
|
ELSE 4
|
|
END
|
|
LIMIT 1
|
|
")"
|
|
if [[ -z "${community_id}" ]]; then
|
|
echo "error: local community is missing; run just setup first" >&2
|
|
exit 1
|
|
fi
|
|
|
|
fixture_hash() {
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
sha256sum "$1" | awk '{print $1}'
|
|
else
|
|
shasum -a 256 "$1" | awk '{print $1}'
|
|
fi
|
|
}
|
|
|
|
fixture_size() {
|
|
wc -c < "$1" | awk '{print $1}'
|
|
}
|
|
|
|
upload_fixture() {
|
|
local path="$1" hash="$2" extension="$3" mime="$4" dimensions="$5"
|
|
local size sidecar
|
|
size="$(fixture_size "${path}")"
|
|
sidecar="$(printf '{"dim":"%s","blurhash":"","thumb_url":"","ext":"%s","mime_type":"%s","size":%s,"uploaded_at":0}' \
|
|
"${dimensions}" "${extension}" "${mime}" "${size}")"
|
|
docker exec -i buzz-minio mc pipe --quiet --attr "Content-Type=${mime}" \
|
|
"local/${BUZZ_S3_BUCKET:-buzz-media}/${hash}.${extension}" < "${path}"
|
|
printf '%s' "${sidecar}" | docker exec -i buzz-minio mc pipe --quiet \
|
|
--attr "Content-Type=application/json" \
|
|
"local/${BUZZ_S3_BUCKET:-buzz-media}/_meta/${community_id}/${hash}.json"
|
|
}
|
|
|
|
fixture_dir="$(mktemp -d "${TMPDIR:-/tmp}/buzz-admin-feedback.XXXXXX")"
|
|
search_image="${REPO_ROOT}/docs/assets/screenshots/media-comments.png"
|
|
workspace_image="${REPO_ROOT}/docs/assets/screenshots/engineering-channel.png"
|
|
quality_image="${REPO_ROOT}/docs/assets/screenshots/agent-swarm.png"
|
|
composer_diagnostics="${fixture_dir}/composer-diagnostics.txt"
|
|
workspace_diagnostics="${fixture_dir}/workspace-diagnostics.txt"
|
|
trap 'rm -f "${composer_diagnostics}" "${workspace_diagnostics}"; rmdir "${fixture_dir}"' EXIT
|
|
|
|
printf '%s\n' "buzz feedback diagnostics" "area: composer" \
|
|
"event: resumed_from_sleep" "result: composer_unresponsive" > "${composer_diagnostics}"
|
|
printf '%s\n' "buzz feedback diagnostics" "area: workspace-switching" \
|
|
"from: design" "to: engineering" \
|
|
"result: previous_sidebar_visible_for_one_frame" > "${workspace_diagnostics}"
|
|
|
|
search_image_hash="$(fixture_hash "${search_image}")"
|
|
workspace_image_hash="$(fixture_hash "${workspace_image}")"
|
|
quality_image_hash="$(fixture_hash "${quality_image}")"
|
|
composer_diagnostics_hash="$(fixture_hash "${composer_diagnostics}")"
|
|
workspace_diagnostics_hash="$(fixture_hash "${workspace_diagnostics}")"
|
|
|
|
if ! docker exec buzz-minio mc alias set local http://localhost:9000 \
|
|
"${BUZZ_S3_ACCESS_KEY:-buzz_dev}" "${BUZZ_S3_SECRET_KEY:-buzz_dev_secret}" >/dev/null; then
|
|
echo "error: local MinIO is unavailable; run just setup first" >&2
|
|
exit 1
|
|
fi
|
|
|
|
upload_fixture "${search_image}" "${search_image_hash}" png image/png 2000x1172
|
|
upload_fixture "${workspace_image}" "${workspace_image_hash}" png image/png 2000x1172
|
|
upload_fixture "${quality_image}" "${quality_image_hash}" png image/png 2000x1172
|
|
upload_fixture "${composer_diagnostics}" "${composer_diagnostics_hash}" txt text/plain ""
|
|
upload_fixture "${workspace_diagnostics}" "${workspace_diagnostics_hash}" txt text/plain ""
|
|
|
|
read -r -d '' sql <<'SQL' || true
|
|
DO $$
|
|
DECLARE
|
|
local_community_id UUID;
|
|
BEGIN
|
|
SELECT id INTO local_community_id
|
|
FROM communities
|
|
WHERE lower(host) IN ('localhost:3000', 'localhost', '127.0.0.1:3000', '127.0.0.1')
|
|
ORDER BY CASE lower(host)
|
|
WHEN 'localhost:3000' THEN 1
|
|
WHEN 'localhost' THEN 2
|
|
WHEN '127.0.0.1:3000' THEN 3
|
|
ELSE 4
|
|
END
|
|
LIMIT 1;
|
|
|
|
IF local_community_id IS NULL THEN
|
|
RAISE EXCEPTION 'local community is missing; run just setup first';
|
|
END IF;
|
|
|
|
INSERT INTO moderation_reports (
|
|
community_id, id, report_event_id, reporter_pubkey, target_kind,
|
|
target_event_id, target_pubkey, target_blob_sha256, report_type, note,
|
|
status, resolved_by, resolved_at, created_at
|
|
) VALUES
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000001', decode(repeat('01', 32), 'hex'), decode(repeat('11', 32), 'hex'), 'event', decode(repeat('21', 32), 'hex'), NULL, NULL, 'spam', 'Repeated unsolicited promotion across several channels.', 'open', NULL, NULL, now() - interval '8 minutes'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000002', decode(repeat('02', 32), 'hex'), decode(repeat('12', 32), 'hex'), 'pubkey', NULL, decode(repeat('22', 32), 'hex'), NULL, 'impersonation', 'Profile appears to impersonate a community organizer.', 'open', NULL, NULL, now() - interval '25 minutes'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000003', decode(repeat('03', 32), 'hex'), decode(repeat('13', 32), 'hex'), 'blob', NULL, NULL, decode(repeat('23', 32), 'hex'), 'malware', 'Attachment was flagged after download.', 'open', NULL, NULL, now() - interval '50 minutes'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000004', decode(repeat('04', 32), 'hex'), decode(repeat('14', 32), 'hex'), 'event', decode(repeat('24', 32), 'hex'), NULL, NULL, 'illegal', 'Contains material that may require legal review.', 'open', NULL, NULL, now() - interval '2 hours'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000005', decode(repeat('05', 32), 'hex'), decode(repeat('15', 32), 'hex'), 'blob', NULL, NULL, decode(repeat('25', 32), 'hex'), 'nudity', NULL, 'open', NULL, NULL, now() - interval '5 hours'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000006', decode(repeat('06', 32), 'hex'), decode(repeat('16', 32), 'hex'), 'pubkey', NULL, decode(repeat('26', 32), 'hex'), NULL, 'profanity', 'Repeated abusive replies from this account.', 'open', NULL, NULL, now() - interval '12 hours'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000007', decode(repeat('07', 32), 'hex'), decode(repeat('17', 32), 'hex'), 'event', decode(repeat('27', 32), 'hex'), NULL, NULL, 'other', 'Does not fit a standard report category.', 'open', NULL, NULL, now() - interval '1 day'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000008', decode(repeat('08', 32), 'hex'), decode(repeat('18', 32), 'hex'), 'pubkey', NULL, decode(repeat('28', 32), 'hex'), NULL, 'impersonation', 'Escalated while ownership is verified.', 'escalated', decode(repeat('38', 32), 'hex'), now() - interval '1 hour', now() - interval '2 days'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000009', decode(repeat('09', 32), 'hex'), decode(repeat('19', 32), 'hex'), 'blob', NULL, NULL, decode(repeat('29', 32), 'hex'), 'malware', 'Resolved after the attachment was removed.', 'resolved', decode(repeat('39', 32), 'hex'), now() - interval '1 day', now() - interval '3 days'),
|
|
(local_community_id, 'a11d0000-0000-4000-8000-000000000010', decode(repeat('0a', 32), 'hex'), decode(repeat('1a', 32), 'hex'), 'event', decode(repeat('2a', 32), 'hex'), NULL, NULL, 'other', 'Dismissed after reviewing the surrounding thread.', 'dismissed', decode(repeat('3a', 32), 'hex'), now() - interval '3 days', now() - interval '4 days')
|
|
ON CONFLICT (community_id, report_event_id) DO UPDATE SET
|
|
reporter_pubkey = EXCLUDED.reporter_pubkey,
|
|
target_kind = EXCLUDED.target_kind,
|
|
target_event_id = EXCLUDED.target_event_id,
|
|
target_pubkey = EXCLUDED.target_pubkey,
|
|
target_blob_sha256 = EXCLUDED.target_blob_sha256,
|
|
report_type = EXCLUDED.report_type,
|
|
note = EXCLUDED.note,
|
|
status = EXCLUDED.status,
|
|
resolved_by = EXCLUDED.resolved_by,
|
|
resolved_at = EXCLUDED.resolved_at,
|
|
created_at = EXCLUDED.created_at;
|
|
|
|
INSERT INTO product_feedback (
|
|
id, community_id, event_id, submitter_pubkey, category, body, tags,
|
|
event_created_at, received_at
|
|
) VALUES
|
|
('feed0000-0000-4000-8000-000000000001', local_community_id, decode(repeat('41', 32), 'hex'), decode(repeat('51', 32), 'hex'), 'bug', 'Unread counts return after reopening the desktop app.', '[["category", "bug"]]', now() - interval '20 minutes', now() - interval '19 minutes'),
|
|
('feed0000-0000-4000-8000-000000000002', local_community_id, decode(repeat('42', 32), 'hex'), decode(repeat('52', 32), 'hex'), 'needs-work', E'Search needs clearer empty-state guidance.\n', '[["category", "needs-work"], ["imeta", "url http://localhost:3000/media/__SEARCH_IMAGE_HASH__.png", "m image/png", "x __SEARCH_IMAGE_HASH__", "size __SEARCH_IMAGE_SIZE__", "dim 2000x1172", "filename search-empty-state.png"]]', now() - interval '5 hours', now() - interval '5 hours'),
|
|
('feed0000-0000-4000-8000-000000000003', local_community_id, decode(repeat('43', 32), 'hex'), decode(repeat('53', 32), 'hex'), 'praise', 'The new channel switcher feels immediate.', '[["category", "praise"]]', now() - interval '1 day', now() - interval '1 day'),
|
|
('feed0000-0000-4000-8000-000000000004', local_community_id, decode(repeat('44', 32), 'hex'), decode(repeat('54', 32), 'hex'), 'bug', E'The composer froze after waking my laptop. Diagnostics attached.\n[feedback-diagnostics.txt](http://localhost:3000/media/__COMPOSER_DIAGNOSTICS_HASH__.txt)', '[["category", "bug"], ["imeta", "url http://localhost:3000/media/__COMPOSER_DIAGNOSTICS_HASH__.txt", "m text/plain", "x __COMPOSER_DIAGNOSTICS_HASH__", "size __COMPOSER_DIAGNOSTICS_SIZE__", "filename feedback-diagnostics.txt"]]', now() - interval '2 days', now() - interval '2 days'),
|
|
('feed0000-0000-4000-8000-000000000005', local_community_id, decode(repeat('45', 32), 'hex'), decode(repeat('55', 32), 'hex'), NULL, 'General feedback without a selected category or any attachments.', '[]', now() - interval '3 days', now() - interval '3 days'),
|
|
('feed0000-0000-4000-8000-000000000006', local_community_id, decode(repeat('46', 32), 'hex'), decode(repeat('56', 32), 'hex'), 'needs-work', E'The sidebar briefly renders the previous workspace after switching. Screenshot and diagnostics attached.\n\n[feedback-diagnostics.txt](http://localhost:3000/media/__WORKSPACE_DIAGNOSTICS_HASH__.txt)', '[["category", "needs-work"], ["imeta", "url http://localhost:3000/media/__WORKSPACE_IMAGE_HASH__.png", "m image/png", "x __WORKSPACE_IMAGE_HASH__", "size __WORKSPACE_IMAGE_SIZE__", "dim 2000x1172", "filename workspace-flash.png"], ["imeta", "url http://localhost:3000/media/__WORKSPACE_DIAGNOSTICS_HASH__.txt", "m text/plain", "x __WORKSPACE_DIAGNOSTICS_HASH__", "size __WORKSPACE_DIAGNOSTICS_SIZE__", "filename feedback-diagnostics.txt"]]', now() - interval '5 days', now() - interval '5 days'),
|
|
('feed0000-0000-4000-8000-000000000007', local_community_id, decode(repeat('47', 32), 'hex'), decode(repeat('57', 32), 'hex'), 'praise', E'Calls have been much more reliable this week. Attaching the quality graph that made the improvement obvious.\n', '[["category", "praise"], ["imeta", "url http://localhost:3000/media/__QUALITY_IMAGE_HASH__.png", "m image/png", "x __QUALITY_IMAGE_HASH__", "size __QUALITY_IMAGE_SIZE__", "dim 2000x1172", "filename huddle-quality.png"]]', now() - interval '8 days', now() - interval '8 days')
|
|
ON CONFLICT (event_id) DO UPDATE SET
|
|
community_id = EXCLUDED.community_id,
|
|
submitter_pubkey = EXCLUDED.submitter_pubkey,
|
|
category = EXCLUDED.category,
|
|
body = EXCLUDED.body,
|
|
tags = EXCLUDED.tags,
|
|
event_created_at = EXCLUDED.event_created_at,
|
|
received_at = EXCLUDED.received_at;
|
|
END $$;
|
|
SQL
|
|
|
|
sql="${sql//__SEARCH_IMAGE_HASH__/${search_image_hash}}"
|
|
sql="${sql//__WORKSPACE_IMAGE_HASH__/${workspace_image_hash}}"
|
|
sql="${sql//__QUALITY_IMAGE_HASH__/${quality_image_hash}}"
|
|
sql="${sql//__COMPOSER_DIAGNOSTICS_HASH__/${composer_diagnostics_hash}}"
|
|
sql="${sql//__WORKSPACE_DIAGNOSTICS_HASH__/${workspace_diagnostics_hash}}"
|
|
sql="${sql//__SEARCH_IMAGE_SIZE__/$(fixture_size "${search_image}")}"
|
|
sql="${sql//__WORKSPACE_IMAGE_SIZE__/$(fixture_size "${workspace_image}")}"
|
|
sql="${sql//__QUALITY_IMAGE_SIZE__/$(fixture_size "${quality_image}")}"
|
|
sql="${sql//__COMPOSER_DIAGNOSTICS_SIZE__/$(fixture_size "${composer_diagnostics}")}"
|
|
sql="${sql//__WORKSPACE_DIAGNOSTICS_SIZE__/$(fixture_size "${workspace_diagnostics}")}"
|
|
|
|
run_psql -v ON_ERROR_STOP=1 -c "${sql}"
|
|
|
|
echo "Seeded 10 moderation reports, 7 feedback entries, and 5 attachments for the local admin dashboard."
|