Closed5

linebot作りを試す

not75743not75743

dockerfile

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/go-image.html

FROM golang:1.22 AS builder
WORKDIR /workspace

# Go Modules のキャッシュを利用
COPY go.mod go.sum ./
RUN go mod download

# ソースコードをコピーしてビルド
COPY lambda_function.go lambda_function.go
RUN go build -tags lambda.norpc -o main lambda_function.go

# Runtime stage: AWS Lambda 用の Go ランタイムイメージを利用
FROM public.ecr.aws/lambda/provided:al2023

# ビルド済みバイナリを配置
COPY --from=builder /workspace/main ./main

# Lambda のハンドラとして main バイナリを指定
ENTRYPOINT [ "./main" ]
not75743not75743

terraformのlambda部分

# lambda
resource "aws_lambda_function" "main" {
  function_name = "example-lambda"
  package_type  = "Image"
  image_uri     = "xxx:latest"
  timeout       = 30

  role = aws_iam_role.main.arn

  environment {
    variables = {
      LINE_CHANNEL_SECRET = "xxx"
      CHANNEL_ACCESS_TOKEN = "xxx"
    }
  }
}

# lambda function url
resource "aws_lambda_function_url" "main" {
  function_name      = aws_lambda_function.main.function_name
  authorization_type = "NONE"
}
not75743not75743

goコード

package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client

func init() {
	// LINE の Channel Secret は環境変数 "LINE_CHANNEL_SECRET" から取得
	secret := os.Getenv("LINE_CHANNEL_SECRET")
	// Channel Access Token は環境変数 "CHANNEL_ACCESS_TOKEN" から取得
	accessToken := os.Getenv("CHANNEL_ACCESS_TOKEN")

	var err error
	bot, err = linebot.New(secret, accessToken)
	if err != nil {
		log.Fatalf("Error initializing LINE bot: %v", err)
	}
}

func handler(ctx context.Context, req events.LambdaFunctionURLRequest) (events.LambdaFunctionURLResponse, error) {
	// Lambda Function URL のイベントから http.Request を生成
	r, err := http.NewRequest("POST", "/", strings.NewReader(req.Body))
	if err != nil {
		log.Printf("Error creating HTTP request: %v", err)
		return events.LambdaFunctionURLResponse{StatusCode: 500}, nil
	}
	// リクエストヘッダーを設定
	for key, value := range req.Headers {
		r.Header.Set(key, value)
	}

	// LINE の Webhook リクエストをパース
	eventsList, err := bot.ParseRequest(r)
	if err != nil {
		// 署名エラーの場合は 400 を返す
		if err == linebot.ErrInvalidSignature {
			return events.LambdaFunctionURLResponse{StatusCode: 400}, nil
		}
		log.Printf("Error parsing request: %v", err)
		return events.LambdaFunctionURLResponse{StatusCode: 500}, nil
	}

	// 各イベントに対してオウム返しの返信を実行
	for _, event := range eventsList {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				// 受信したテキストをそのまま返信
				if _, err := bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.Text)).Do(); err != nil {
					log.Printf("Error replying to message: %v", err)
				}
			}
		}
	}

	return events.LambdaFunctionURLResponse{
		StatusCode: 200,
		Body:       "OK",
		Headers: map[string]string{
			"Content-Type": "text/plain",
		},
	}, nil
}

func main() {
	lambda.Start(handler)
}
このスクラップは6ヶ月前にクローズされました