Address channels in Bot API form and add a founder-run send script
The provisioner records the MTProto channel id; the Bot API needs -100<id>. adapter-config now converts it, so the test channel resolves to -1004427430639. scripts/send-post.sh starts a short-lived adapter with the bot token injected from OpenBao (never printed) and sends one reviewed post. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5457@bnt-lap001 Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
This commit is contained in:
parent
679aad207e
commit
b09a5e21d4
3 changed files with 77 additions and 1 deletions
|
|
@ -52,11 +52,22 @@ func FromResolved(rs *state.Resolved, channel, tokenRef string) (Config, error)
|
|||
return Config{
|
||||
Campaign: rs.Campaign,
|
||||
Channel: channel,
|
||||
ChatID: ch.ChatID,
|
||||
ChatID: BotAPIChatID(ch.ChatID),
|
||||
TokenRef: tokenRef,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BotAPIChatID converts a channel id as the provisioner records it (the
|
||||
// MTProto channel id, positive) into the form the Bot API addresses it by
|
||||
// (-100 followed by the id). An id that is already negative is in Bot API
|
||||
// form and is returned unchanged.
|
||||
func BotAPIChatID(id int64) int64 {
|
||||
if id > 0 {
|
||||
return -1000000000000 - id
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// EnvFile is the non-secret configuration an adapter process is started with.
|
||||
// The token is named, not emitted: the runtime injects it from OpenBao.
|
||||
func (c Config) EnvFile() string {
|
||||
|
|
|
|||
|
|
@ -112,3 +112,18 @@ func TestLoadTokenReadsOnlyTheBotToken(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBotAPIChatIDPrefixesChannelIDs(t *testing.T) {
|
||||
if got := BotAPIChatID(4427430639); got != -1004427430639 {
|
||||
t.Fatalf("BotAPIChatID(4427430639) = %d", got)
|
||||
}
|
||||
if got := BotAPIChatID(-1001); got != -1001 {
|
||||
t.Fatalf("an id already in Bot API form changed: %d", got)
|
||||
}
|
||||
rs := provisioned()
|
||||
rs.Channels[spec.Test] = state.Channel{ChatID: 4427430639, AdminRights: []string{spec.PostMessages}}
|
||||
cfg, err := FromResolved(rs, spec.Test, "ref")
|
||||
if err != nil || cfg.ChatID != -1004427430639 {
|
||||
t.Fatalf("FromResolved chat id = %d, err %v", cfg.ChatID, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
50
scripts/send-post.sh
Executable file
50
scripts/send-post.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env bash
|
||||
# Send one prepared post (pr-hall-of-helix/posts/<file>.yaml) through a
|
||||
# short-lived local adapter, then stop it.
|
||||
#
|
||||
# Run it yourself, logged in to OpenBao (BAO_ADDR/BAO_TOKEN set). The bot token
|
||||
# goes from OpenBao straight into the adapter's environment and is never
|
||||
# printed. The adapter's store is in memory, so idempotency on post_id holds
|
||||
# only within one run: do not re-run for a post that already went out.
|
||||
#
|
||||
# scripts/send-post.sh ~/pr-hall-of-helix/posts/2026-10-08-test-outlet-parametrization.yaml test
|
||||
set -euo pipefail
|
||||
|
||||
post=$(realpath "$1")
|
||||
channel=${2:-test}
|
||||
spec=${SPEC:-$HOME/pr-hall-of-helix/presence/telegram.yaml}
|
||||
port=${PORT:-18089}
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
read -r want reviewed < <(python3 -c '
|
||||
import sys, yaml
|
||||
d = yaml.safe_load(open(sys.argv[1]))
|
||||
print(d["channel"], d["request"].get("reviewed_by") or "-")' "$post")
|
||||
[ "$want" = "$channel" ] || { echo "post is for channel '$want', not '$channel'" >&2; exit 2; }
|
||||
[ "$reviewed" != "-" ] || { echo "request.reviewed_by is empty; a person reviews before sending" >&2; exit 2; }
|
||||
|
||||
TELEGRAM_CHANNEL_ID=$(go run ./cmd/provision adapter-config --spec "$spec" --channel "$channel" \
|
||||
| sed -n 's/^TELEGRAM_CHANNEL_ID=//p')
|
||||
[ -n "$TELEGRAM_CHANNEL_ID" ] || { echo "no chat id for channel '$channel'" >&2; exit 2; }
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
go build -o "$tmp/adapter" ./cmd/adapter
|
||||
|
||||
token=$(bao kv get -mount=platform -field=token \
|
||||
workloads/infotech/fluid-telegram/hall-of-helix/bot-token) \
|
||||
|| { rm -rf "$tmp"; echo "could not read the bot token from OpenBao (logged in?)" >&2; exit 2; }
|
||||
|
||||
TELEGRAM_BOT_TOKEN=$token TELEGRAM_CHANNEL_ID=$TELEGRAM_CHANNEL_ID \
|
||||
ADAPTER_LISTEN_ADDR=127.0.0.1:$port "$tmp/adapter" &
|
||||
pid=$!
|
||||
unset token
|
||||
trap 'kill $pid 2>/dev/null; rm -rf "$tmp"' EXIT
|
||||
|
||||
for _ in $(seq 50); do
|
||||
curl -s -o /dev/null "http://127.0.0.1:$port/" && break
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
python3 -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(open(sys.argv[1]))["request"]))' "$post" \
|
||||
| curl -sS -w '\nHTTP %{http_code}\n' -X POST -H 'Content-Type: application/json' \
|
||||
--data-binary @- "http://127.0.0.1:$port/v1/channel-posts"
|
||||
Loading…
Add table
Add a link
Reference in a new issue