// Package connector is the backend's gRPC client for the Telegram platform // connector side-service. The admin console uses it to send operator broadcasts: // a direct message to one user, or a post to the connector's configured game // channel. The connector lives on the trusted internal network, so the // connection uses insecure (plaintext) transport credentials // (docs/ARCHITECTURE.md ยง12). It mirrors gateway/internal/connector, narrowed to // the two broadcast methods the admin surface needs. package connector import ( "context" "fmt" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" telegramv1 "scrabble/pkg/proto/telegram/v1" ) // Client wraps the connector's Telegram gRPC service. type Client struct { conn *grpc.ClientConn c telegramv1.TelegramClient } // New dials the connector gRPC endpoint at addr. func New(addr string) (*Client, error) { conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, fmt.Errorf("connector: dial %s: %w", addr, err) } return &Client{conn: conn, c: telegramv1.NewTelegramClient(conn)}, nil } // Close releases the gRPC connection. func (c *Client) Close() error { return c.conn.Close() } // SendToUser sends an operator text message to one user, addressed by their // platform external_id. delivered reports whether the connector actually sent it // (false when the user has not started the bot). func (c *Client) SendToUser(ctx context.Context, externalID, text string) (bool, error) { resp, err := c.c.SendToUser(ctx, &telegramv1.SendToUserRequest{ExternalId: externalID, Text: text}) if err != nil { return false, err } return resp.GetDelivered(), nil } // SendToGameChannel posts an operator text message to the connector's configured // game channel. delivered reports whether the connector sent it (false when no // channel is configured). func (c *Client) SendToGameChannel(ctx context.Context, text string) (bool, error) { resp, err := c.c.SendToGameChannel(ctx, &telegramv1.SendToGameChannelRequest{Text: text}) if err != nil { return false, err } return resp.GetDelivered(), nil }