aws lambda
Have you ever wanted to create a Twitter Bot? It’s been on my list of things to do for quite some time, and I’ve never really had a good way to do it. Until today.
等皆你曾经想创建一个Twitter博特? 在我要做的事情上已经有一段时间了,而我从来没有真正有好的方法。 直到今天。
I’ve always thought about making some sort of bot, and I always appreciate getting new quotes to ponder, so it was time to just sit down and do it. I just felt the need to finish a project and get something working.
我一直在考虑制作某种机器人,并且我总是很高兴获得新的报价来思考,因此现在是时候坐下来做这件事了。 我只是觉得需要完成一个项目并使某些工作正常进行。
I’ve been using Twitter for quite some time now. I use it to get daily news updates. I get updates about what’s going on before the news. Really it’s a good resource. Not to continue to gloat, but I think it’s a useful product.
我已经使用Twitter很长时间了。 我用它来获取每日新闻更新。 在新闻发布之前,我会得到最新的消息。 真的,这是很好的资源。 不要继续幸灾乐祸,但我认为这是一个有用的产品。
I also have been using IFTTT for quite some time. It’s another useful platform that I don’t use as much as I can but thought of while working on this — it’s just a trigger. It’s great for little if-else scripting statements and can add a lot of functionality to business workflows and even managing your phone operations.
我也使用IFTTT已有相当一段时间了。 这是另一个有用的平台,我没有尽我所能使用,但在进行此工作时却想到了这–它只是一个触发器。 这对于很少使用if-else脚本语句非常有用,并且可以为业务工作流甚至是管理电话操作添加很多功能。
It’s just a cloud trigger.
这只是一个云触发器。
Now I know I need something that will just fire off a single function trigger. The first stack I think of is AWS Lambda. Low and behold, there is even some documentation on setting up a Serverless function and use that to deploy to AWS.
现在我知道我需要一些可以触发单个功能触发器的东西。 我想到的第一个堆栈是AWS Lambda。 低估了,甚至有一些文档介绍了如何设置无服务器功能并将其用于部署到AWS。
As I’ve got some experience in NodeJS (and I found a starter for NodeJS here), I think it could be useful to flex some pre-learned knowledge and bang the keys to get this going.
由于我对NodeJS有一定的经验(我在这里找到了NodeJS的入门者 ),所以我认为,充分利用一些预先学习的知识并敲击按键来使它继续进行可能会很有用。
Since this is going to be in AWS Lambda, a single-use, serverless structure, I thought I could keep this simple with Serverless. This framework helps setting up and managing not only Lambda functions but Google Cloud, Azure, and more! A safe bet to stick with AWS today.
由于这将在一次性使用的无服务器结构AWS Lambda中进行,因此我认为我可以使用Serverless使其保持简单。 该框架不仅有助于设置和管理Lambda功能,而且还可以帮助您设置和管理Google Cloud,Azure等! 今天可以放心使用AWS。
So with that I now have three platforms on my stack:
因此,现在我的堆栈上有了三个平台:
- AWS Lambda for the hosting 适用于托管的AWS Lambda
- NodeJS for the implementation NodeJS实现
- Serverless for the deploy and management with AWS 无服务器,用于通过AWS进行部署和管理
Next, I wanted a way to set up a timer to trigger the function. Luckily AWS has a great tool for that as well: AWS CloudWatch. CloudWatch will be configured with a timed event.
接下来,我想要一种设置计时器以触发功能的方法。 幸运的是,AWS也具有出色的工具:AWS CloudWatch。 CloudWatch将配置有定时事件。
Bringing the total to four on my stack.
将总数增加到4 。
Note: the time it runs depends on the region you’re in, so be weary of that.
注意:运行时间取决于您所在的地区,因此请对此感到疲倦。
With the stack setup, we can go into some finer details now.
通过堆栈设置,我们现在可以详细介绍一些细节。
触发器需要做什么 (What the Trigger Needs To Do)
- Authenticate and connect to Twitter 验证并连接到Twitter
Get the daily quote.rest
获取每日报价
- Create the Tweet from the quote JSON data 根据报价JSON数据创建推文
- Post the Tweet 发表推文
如何调用触发器 (How Will the Trigger Be Called)
CloudWatch Cron Expression as a trigger for the AWS Lambda. This will be covered when we deploy.
CloudWatch Cron Expression作为AWS Lambda的触发器。 部署时将涵盖此内容。
先决条件 (Pre-Requisites)
- Twitter account and Twitter Developer Account Twitter帐户和Twitter开发人员帐户
- AWS Account AWS账户
- NodeJS knowledge NodeJS知识
- If you know none of the above, check my links, and start learning! 如果您不知道上述任何一项,请检查我的链接,然后开始学习!
建立 (Set Up)
Let’s go ahead and crack open a new project. Git or not, I’ve covered a few posts of how to get started with git so we’re going to omit that here.
让我们继续前进,打开一个新项目。 不管是否使用Git,我已经介绍了几篇有关如何开始使用git的文章,因此在这里我们将省略它。
To set up this project, firstly you need the serverless
module installed globally:
要设置此项目,首先需要全局安装serverless
模块:
npm install serverless -g
Then to set up the current project dir with the AWS-NodeJS template:
然后使用AWS-NodeJS模板设置当前项目目录:
serverless create --template aws-nodejs
Which will create the following files
哪个将创建以下文件
handler.js
handler.js
serverless.yml
serverless.yml
Then we need to add the following packages:
然后,我们需要添加以下软件包:
npm install express body-parser oauth request twit serverless-secrets-plugin de-loggingsystem
- Express for the test server Express for测试服务器
- body-parser for the test server 测试服务器的主体解析器
- oauth for authenticating the Twitter API 用于验证Twitter API的oauth
- twit for the Twitter API Twitter API简介
serverless-secrets-plugin for encrypting/decrypting our
.env
fileserverless-secrets-plugin用于加密/解密我们的
.env
文件- de-loggingsystem is a custom logger package I made that helps my prints out de-loggingsystem是我制作的自定义记录程序包,可以帮助打印
I am going to give you some scripts that I kept in my package.json
file that really helped my workflow and suggest for you as well:
我将为您提供一些保存在package.json
文件中的脚本,这些脚本确实有助于我的工作流程并为您提供建议:
![Image for post](https://miro.medium.com/max/9999/1*FQ_C7b5ChNRYGaLD5KkbMg.png)
It’s a little messy, but essentially:
有点混乱,但本质上是:
precommit & commit
are used to encrypt the secrets.*
file and then for committing to my source control with some clean AngularJS commit messages.
precommit & commit
用于加密secrets.*
文件,然后使用一些干净的AngularJS commit消息提交到我的源代码管理。
develop
is to run the function locally one time.
develop
是一次本地运行功能。
predeploy & deploy
will decrypt the file before deploying the production data to the AWS Lambda project.
在将生产数据部署到AWS Lambda项目之前, predeploy & deploy
将解密文件。
test
is to run the testing functions.
test
是运行测试功能。
All
start:local
‘s should be in a separate terminal.所有
start:local
都应在单独的终端中。Dealing with
encrypt
ordecrypt
functions, before the npm command add:PASSWORD=[your password] npm run deploy
to pass the key.在npm命令添加以下内容之前,要处理
encrypt
或decrypt
功能:PASSWORD=[your password] npm run deploy
来传递密钥。
These functions really helped with my own workflow, and perhaps you can make it even better! If you do, let’s share that knowledge in responses.
这些功能确实对我自己的工作流程有所帮助,也许您可以使其变得更好! 如果您这样做,让我们在回应中分享这些知识。
Now that the project has been set up, we can begin to actually code the project and use those libraries.
现在已经建立了项目,我们可以开始实际编码项目并使用这些库了。
码 (Code)
Before we go further, let’s add secrets.*
to the .gitignore
and create secrets.dev
and secrets.prod
files with your Twitter app credentials:
在继续之前,让我们将secrets.*
添加到.gitignore
,并使用您的Twitter应用程序凭据创建secrets.dev
和secrets.prod
文件:
![Image for post](https://miro.medium.com/max/9999/1*LBhICI05QUlBq6Soi5KYfQ.png)
API_URL can vary from dev to prod as we will see in testing later.
API_URL在开发人员和产品之间可能会有所不同,我们稍后将在测试中看到。
Now we can start changing the handler.js
file to something more twitter-quote-botty.
现在我们可以开始将handler.js
文件更改为更多的twitter-quote-botty了。
我们将逐步进行。 (We’re going to take this step-by-step.)
Let’s add all the modules we need:
让我们添加所需的所有模块:
![Image for post](https://miro.medium.com/max/9999/1*sStjFpSHhaKiFaTsWOI8mA.png)
These are all the modules we installed earlier, except we don’t have express
and we do have https
. Express will be used later for our test API server, and the HTTPS module is a NodeJS default.
这些是我们之前安装的所有模块,除了我们没有express
和我们拥有https
。 Express稍后将用于我们的测试API服务器,并且HTTPS模块是NodeJS的默认设置。
Now we need to modify the hello
function. Go ahead and change it to async
:
现在我们需要修改hello
函数。 继续并将其更改为async
:
![Image for post](https://miro.medium.com/max/9999/1*6szbpKnUAx25rPj3g_KRTA.png)
Then we can set up our twit config object with our Twitter credentials loaded in from the environment and connect to Twitter.
然后,我们可以使用从环境中加载的Twitter凭证设置twit config对象,并连接到Twitter。
![Image for post](https://miro.medium.com/max/9999/1*cRzZg-gG2r9Z14qZ6bsTTg.png)
Therefore, connected to Twitter, we can call the quotes.rest API as a promise, that will be what our AWS Lambda function will return. This one is lengthy, so we will break it into parts:
因此,连接到Twitter后,我们可以将quotes.rest API称为promise,这将是我们的AWS Lambda函数将返回的内容。 这很长,因此我们将其分为几部分:
We create a response
(what we return) and tell the variable to await the promise
for the object. The promise
calls a request
function that uses a callback function to handle the request-response.
我们创建一个response
(返回的内容),并告诉变量等待对象的promise
。 promise
调用一个request
函数,该函数使用回调函数来处理请求-响应。
![Image for post](https://miro.medium.com/max/9999/1*HaZ7NI5MNU9CJHvbV6FVnw.png)
Then parse the data from the body of the request-response into a JSON object. I create and load a tag
variable with the tags of the quote. Then I use funky backticks (`) to parse the request-response JSON object into a quote-able string, and add all the tags.
然后将请求响应主体中的数据解析为JSON对象。 我用引号的标签创建并加载一个tag
变量。 然后,我使用时髦的反引号(`)将请求响应JSON对象解析为可引用的字符串,然后添加所有标签。
![Image for post](https://miro.medium.com/max/9999/1*BEfd7jqD00cyHJBS0c3_JA.png)
Finally, I try to post the Tweet and if there is a success or failure, the console logs the output:
最后,我尝试发布Tweet,如果成功或失败,控制台将记录输出:
![Image for post](https://miro.medium.com/max/9999/1*EbUFbJ85qBzPoWpAywzHwQ.png)
Here is the final file (with all the logging included I left out before):
这是最终文件(包括我之前遗漏的所有日志记录):
'use-strict';
const https = require('https');
const request = require('request');
const logger = require('de-loggingsystem');
const OAuth2 = require('oauth').OAuth2;
const twit = require('twit');
module.exports.hello = async event => {
let config = {
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token: process.env.ACCESS_TOKEN,
access_token_secret: process.env.ACCESS_TOKEN_SECRET
};
const Twitter = new twit(config);
const response = await new Promise((resolve, reject) => {
request(process.env.API_URL, function(err, res, body) {
logger.log(logger.LogLevel.debug, `Response: ${res}. Body: ${body}`);
let data = JSON.parse(body);
logger.log(logger.LogLevel.debug, `Parsed rfdc object: ${data.contents.quotes[0].quote}`);
var tags = "";
for (const [key, value] of Object.entries(data.contents.quotes[0].tags)) {
let tag = value;
tags += `#${tag} `;
};
var tweet = `"${data.contents.quotes[0].quote}" - ${data.contents.quotes[0].author}\n\n\n${tags}`;
logger.log(logger.LogLevel.debug, tweet);
Twitter.post('statuses/update', { status: tweet }, function(err, data, response) {
if (err) {
logger.log(logger.LogLevel.error, `Tweet was not posted. Errorcode: ${err}`, logger.ErrorCode.Error);
} else {
logger.log(logger.LogLevel.info, `Tweet posted`);
}
});
});
});
return response;
};
设置测试 (Set Up Tests)
For testing (well to code the tests) we need a simple JSON quote file to be sent back. We can do this with an Express instance. Create a server.js
file with the following:
为了进行测试(对测试进行编码),我们需要将一个简单的JSON报价文件发送回去。 我们可以使用Express实例来做到这一点。 使用以下命令创建server.js
文件:
![Image for post](https://miro.medium.com/max/9999/1*nzfUYWIZAZSy5mPaB9xg-g.png)
Now, I took this from my own example express server, but I took that from an example, and they used a routes/routes.js
files, so I do too:
现在,我从自己的示例快速服务器中获取了此信息,但从一个示例中获取了该信息,并且他们使用了routes/routes.js
文件,所以我也这样做了:
![Image for post](https://miro.medium.com/max/9999/1*4Q6xnM36HZk1AEB7BsMbMA.png)
Now when you run your tests (using the secrets.dev
) your function will call the local server with the API_URL: http://localhost:3000/qod
现在,当您运行测试(使用secrets.dev
)时,您的函数将使用API_URL调用本地服务器: http://localhost:3000/qod
实际测试 (Actual Testing)
To run the tests, first, you must run the test server. To run the test server, open another terminal to the folder path and run the server with:
要运行测试,首先,您必须运行测试服务器。 要运行测试服务器,请在文件夹路径中打开另一个终端,并使用以下命令运行服务器:
node server.js
I set up an npm test script with the following:
我使用以下命令设置了npm测试脚本:
"test": "sls invoke local -f hello --verbose --stage dev"
Which in turn runs the local function using the dev stage; which in turn uses the secrets.dev
file. You should see the quote by Ralph Waldo Emerson sent to Twitter.
依次使用dev阶段运行本地功能; 依次使用secrets.dev
文件。 您应该看到Ralph Waldo Emerson发送给Twitter的报价。
部署方式 (Deployment)
You will need to login with your AWS IAM account that you want to use with the project. You can do so with the instructions here.
您将需要使用要用于项目的AWS IAM帐户登录。 您可以按照此处的说明进行操作 。
Serverless handles the deployment.
无服务器处理部署。
We can use the PASSWORD=[your password] npm run deploy
script setup before to deploy to our AWS Lambda project setup now. Once it’s deployed, you’ll be able to check the status on the Dashboard.
我们可以先使用PASSWORD=[your password] npm run deploy
脚本设置,然后立即部署到我们的AWS Lambda项目设置。 部署完成后,您将可以在仪表板上检查状态。
Now that we’ve set up this project, we need to add a trigger from CloudWatch. To create a new trigger, AWS has some great documentation that will walk you through it. Be sure to check the correct action to run, and double-check your region, or calculate the timezone difference.
现在我们已经设置了这个项目,我们需要从CloudWatch添加触发器。 为了创建一个新的触发器, AWS提供了一些出色的文档 ,将逐步引导您。 确保检查要运行的正确操作,并仔细检查您的区域,或计算时区差异。
When you have your trigger ready, you can test the trigger with some blank data — which will pull from the API and post a tweet without the scheduled time.
准备好触发器后,您可以使用一些空白数据测试触发器-这些数据将从API中提取并发布一条没有计划时间的推文。
你做到了! (You did it!)
You made a Twitter quote bot too! I wanted to document this so that others could have fun making bots and other quirky APIs. Perhaps that’s next on the list, connecting this to an AWS API?
您也做了一个Twitter报价机器人! 我想对此进行记录,以使其他人可以玩机器人和其他古怪的API。 也许那是列表中的下一个,将其连接到AWS API?
Anywho, what did you like about making this project today? Are there any steps you improved? Let me know! It would be great to hear what others have to say, or tips they might have to speed up the process even more! I’m sure there’s a way to implement most of the deployment in GitHub Actions even (🤔).
任何人,您今天喜欢做这个项目有什么感觉? 您有什么改进的步骤吗? 让我知道! 听到别人怎么说,或者他们可能会进一步加快流程的提示,将是很棒的! 我敢肯定,有一种方法甚至可以在GitHub Actions中实现大多数部署。
资源资源 (Resources)
Like any good note-taker, I have some links to what I found useful while working on this little project. If you are a little more on the uneducated side of NodeJS, AWS and JavaScript that's okay too! It took me a while to get it all, but I have some tips: read the API and Google-learn everything you can:
像其他记笔记的人一样,我有一些指向我在从事这个小项目时发现有用的链接。 如果您对NodeJS,AWS和JavaScript的知识还不够多,那也可以! 我花了一些时间才了解所有内容,但我有一些提示:请阅读API并通过Google学习所有可以做到的事情:
Building Command-Line in NodeJS
Serverless AWS NodeJS Hello World
Encrypting Serverless Environment Variables
And most importantly: Quotes.rest
最重要的是: Quotes.rest
最后 (Finally)
You can find the source code for the bot I created — that is posting to Twitter as DailyQuoteBot2 — can be found on GitHub.
您可以在GitHub上找到我创建的机器人的源代码,该源代码以DailyQuoteBot2的形式发布到Twitter。
Drop the project a star if you like what I’ve done. Heck even make a pull request on my repo. Follow the bot even too!
如果您喜欢我的工作,请将该项目放下星星。 赫克甚至在我的仓库上提出拉请求。 也跟随机器人!
I made this project — and another — in a single day. I just had the stroke of “I need to do something cool today” and that’s where this bot came from. The other project was because my buddy denied my ability to do something awesome and memeingful (😏).
我一天之内就完成了这个项目以及另一个项目。 我刚提出“今天我需要做一些很棒的事情”,这就是该机器人的来源。 另一个项目是因为我的好友拒绝了我做某事的能力。
I hope you learned something new today. I hope this inspired you to make a cool little project or push yourself to make something you before thought was impossible but now the thing is probable.
希望您今天学到了新东西。 我希望这能激发您做一个很棒的小项目或推动自己做一些您以前认为不可能的事情,但现在事情可能发生。
Push Yourself Today.
今天推动自己。
Thanks for taking the time to read.
感谢您抽出宝贵的时间阅读。
All the best and stay safe — Spencer
一切顺利并保持安全— Spencer
aws lambda