使用GO,GPT-3和AWS构建Twitter机器人
#aws #twitter #go #gpt3

Twitter机器人帖子

我最近一直在学习,您可以阅读in my previous post。有什么比实际项目更好的学习编程语言的方法?

每个人都在谈论Twitter及其机器人。我想,这样做有多困难?甚至合法吗?

我制作的机器人就像是“明智的印度大师”,每2个小时都会发推文。使用GPT-3 API生成此建议。

我是如何做的?

  • 我们称为GPT-3 API并获取生成的响应主体。由此,我们对其进行解析并修剪以删除空白空间。该字符串将成为我们的bot的推文
  • 如果所有这些过程都成功,我们将向Twitter API提出邮政请求。

我们如何每2H触发它?

我们需要什么?

该项目的所有代码都是开源的,可在:https://github.com/el-pol/lovebot上找到。随意分叉并提交PRSð

获取Twitter凭据从机器人发推文

  1. 首先,您需要从主要帐户申请Twitter开发人员帐户:https://developer.twitter.com/en。然后,申请************ 提升访问 ************,以便您的应用程序可以阅读& 写。这是一个很好的分步:https://www.extly.com/docs/perfect_publisher/user_guide/tutorials/how-to-auto-post-from-joomla-to-twitter/apply-for-a-twitter-developer-account/#apply-for-a-developer-account
  2. 然后,为机器人创建一个新的常规Twitter帐户。我建议在另一个浏览器中执行此操作,因此您不会混淆您的********** 主要帐户 ************************************** ***使用您的****** bot帐户 ******。
  3. 在机器人帐户设置中,找到由 *******管理的******* 部分,然后将其引用到您的主帐户。这将为bot帐户添加自动化徽章,由 @yourhandle
  4. 一旦完成步骤1-2-3,请按照本指南:https://medium.com/geekculture/how-to-create-multiple-bots-with-a-single-twitter-developer-account-529eaba6a57611
    1. 我们在这里做的是授权我们的主要帐户控制我们的机器人帐户。这就是为什么我们需要另一个身份验证销。这使用了oauth1a。
    2. 最后一步是不同的。截至今天,您将需要执行帖子请求,而不是访问URL:curl --request POST --url '<https://twitter.com/oauth/access_token?oauth_token=><TOKEN>&oauth_verifier=<PIN>'
    3. 之后,您应该获得键和令牌的响应
    4. 有一种更好的方法可以使用OAuth2进行操作;它更加安全,但更复杂,因为每次制作新推文时,您都需要对此流进行重新认证。如果您有时间和精力,我建议您这样做。这是一个很好的例子:https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token
  5. 最后,您应该有4个不同的秘密键:
    1. 主要帐户消费者密钥
    2. 主帐户访问令牌秘密
    3. bot acess令牌(您刚刚生成的一个)
    4. 机器人访问令牌秘密(您也刚刚生成的秘密)
  6. 您将使用所有这些:前两个告诉Twitter,您有一个授权读/写的开发人员帐户,最后两个告诉Twitter您将从机器人帐户发推文。您确实通过两个不同的步骤进行身份验证。如果您只想从主帐户发推文,则只需要自己的消费者密钥和秘密。

获得OpenAI API凭据

OpenAI是付费API,因此您需要去https://beta.openai.com/overview并添加帐单详细信息。

然后,您将获得一个可以使用的API键。您可以在此处查看文档:https://beta.openai.com/docs/api-reference/making-requests

您可以看到,我们需要将钥匙传递给授权标题。

代码

相信与否 - 最困难的部分已经结束。如果您在编程方面有一定的经验,我们接下来要做的是两个顺序的帖子请求:首先到Openai获取文本,然后在Twitter下方从我们的机器人帐户发布。

这是我使用的文件结构:

File structure

  • 获取软件包包含我们的OpenAI请求的逻辑。然后,我们将将其导入main.go
  • main.go中,我们执行Twitter Post请求。可以将其重构为清洁码的另一个软件包。
  • 您的.env文件应该看起来像这样:

Env vars

AWS Lambda特定警告

通常,您将所有代码都放入func main()中,并且它将起作用。但是,当我们与AWS Lambda合作时,我们需要添加一个小的修改。我们必须将代码放入处理程序中,然后将其放入func main(),如下所述:https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html

因此,对于lambda,您通常会在main中放置的所有代码,必须进入另一个函数,然后像这样传递:

func main() {
    lambda.Start(HandleRequest)
}

HandleRequest是我们将执行主代码的功能。

这很重要,因为它告诉lambda何时开始。我犯了一个错误。然后,在lambda事件启动之前执行代码,因此它一直错误。

使用他的lambda处理程序,我们可以将信息传递到上下文中,因此我们可以从HTTP查询参数传递给我们的代码(将参数传递给代码),从而将信息传递到上下文。例如:https://aws.amazon.com/premiumsupport/knowledge-center/pass-api-gateway-rest-api-parameters/

代码审查

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "strings"
    "time"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/dghubble/oauth1"
    "github.com/el-pol/lovebot/fetch"
    "github.com/joho/godotenv"
)

func HandleRequest(ctx context.Context) (string, error) {
    godotenv.Load()

    consumerKey := os.Getenv("CONSUMER_KEY")
    consumerSecret := os.Getenv("CONSUMER_SECRET")
    accessToken := os.Getenv("ACCESS_TOKEN")
    accessSecret := os.Getenv("TOKEN_SECRET")
    prompt := os.Getenv("PROMPT")

    if consumerKey == "" || consumerSecret == "" || accessToken == "" || accessSecret == "" {
        panic("Missing required environment variable")
    }

    // Will return a trimmed string
    fetched := fetch.GetGenerated(prompt)

    // From here on, Twitter POST API
    config := oauth1.NewConfig(consumerKey, consumerSecret)
    token := oauth1.NewToken(accessToken, accessSecret)

    httpClient := config.Client(oauth1.NoContext, token)

    // Necessary - you don't want to be charged for long Lambdas timing out.
    httpClient.Timeout = time.Second * 10

    path := "https://api.twitter.com/2/tweets"

    body := fmt.Sprintf(`{"text": "%s"}`, fetched)

    bodyReader := strings.NewReader(body)

    response, err := httpClient.Post(path, "application/json", bodyReader)

    if err != nil {
        log.Fatalf("Error when posting to twitter: %v", err)
    }

    defer response.Body.Close()
    log.Printf("Response was OK: %v", response)
    return "finished", nil
}

代码非常基本 - 因为这只是我学习的一个有趣的项目。顺便说一句,如果您看到任何错误或改进,请告诉我。

然后在fetch.go中我们有:

package fetch

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os"
    "strings"
    "time"

    "github.com/joho/godotenv"
)

func GetGenerated(prompt string) string {
    godotenv.Load()

    apiKey := os.Getenv("OPENAI_API_KEY")

    if apiKey == "" {
        panic("Missing required environment variable")
    }

    // Create the request body
    jsonBody := fmt.Sprintf(`{"prompt": "%s", "max_tokens": 256, "model": "text-davinci-003"}`, prompt)

    // Create the request
    req, err := http.NewRequest("POST", "https://api.openai.com/v1/completions", bytes.NewBuffer([]byte(jsonBody)))

    if err != nil {
        log.Fatalf("Error when creating request: %v", err)
    }

    // Add the headers
    req.Header.Add("Authorization", fmt.Sprintf("Bearer %s",
        apiKey))
    req.Header.Add("Content-Type", "application/json")

    client := &http.Client{
        Timeout: time.Second * 10,
    }

    resp, err := client.Do(req)

    if err != nil {
        log.Fatalf("Error when sending request: %v", err)
    }

    defer resp.Body.Close()

    // Check the response
    if resp.StatusCode != 200 {
        log.Fatalf("Response was not OK: %v", resp)
    }

    // Parse the response
    var respBody struct {
        Choices []struct {
            Text string `json:"text"`
        } `json:"choices"`
    }

    err = json.NewDecoder(resp.Body).Decode(&respBody)

    if err != nil {
        log.Fatalf("Error when decoding response: %v", err)
    }

    trimmed := strings.TrimSpace(respBody.Choices[0].Text)

    if trimmed == "" {
        log.Fatalln("Result is empty")
    }

    if len(trimmed) >= 280 {
        log.Fatalln("Result is too long")
    }

    return trimmed
}

使用的软件包

包装代码并将其上传到AWS lambda

对于这一部分,我遵循了Toul撰写的这一惊人的指南:https://dev.to/toul_codes/infrahamburglar-a-cybersecurity-news-bot-built-with-aws-lambda-golang-and-twitter-api-v2-198e

首先,我们需要构建我们的应用程序然后将其拉链。这个zipperiped文件是我们上传到aws lambda。

要在Go中构建,在您的终端写入:

GOOS=linux  GOARCH=amd64 go build -o your-twitter-bot main.go

完成此操作后,要做:

zip your-twitter-bot.zip your-twitter-bot 

此zip文件是您将作为lambda的代码上传的内容。您进行的每项进一步修改都会迫使您重复这两个步骤并再次上传。

添加扳机

每次此Lambda运行时,您都会发布一条新推文。安排它的方法是使用AWS CloudWatch事件或EventBridge使用CRON表达式。 EventBridge的参考在这里:https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html

确保参考文档,aws cron表达式与标准有所不同:https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html

在添加触发器之前,您应该测试您的lambda是否有效。如果您进入***** test ***** lambda部分,则可以触发它。我们不在乎事件的内容 - 因为我们的lambda不取决于任何参数或参数。因此,我们可以触发任何事件,它应该开火和工作。

如果有效,您应该在机器人帐户中看到一个新推文。

如果一切正常,您可以添加触发器,以便bot用cron表达式发推文每x发推文。

完成的!

如果您达到了尽头,则应该有一个工作机器人。

这是我做的,请给他一个关注:https://twitter.com/LoveAdviceWiseG

View of the bot timeline