Skip to content

Commit

Permalink
Merge pull request #1 from mmartinsky/main
Browse files Browse the repository at this point in the history
Refactor to modern lambda
  • Loading branch information
mmartinsky authored Oct 7, 2024
2 parents ee85cf5 + ae3f5cc commit d30738d
Show file tree
Hide file tree
Showing 26 changed files with 19,053 additions and 3,242 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TWITTER_API_KEY=
TWITTER_API_SECRET=
TWITTER_ACCESS_TOKEN=
TWITTER_ACCESS_SECRET=
25 changes: 0 additions & 25 deletions .eslintrc

This file was deleted.

25 changes: 25 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Unit Tests

on:
push:
branches: [ main ]
pull_request:
branches: [ master ]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '20'

- name: Install dependencies
run: npm ci

- name: Run tests
run: npm test
70 changes: 4 additions & 66 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,67 +1,5 @@
.vscode/launch.json
.eslintrc.json
deploy.env
.lambda
context.json
event.json
event_sources.json
rsg-development.zip

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
node_modules
.vscode/launch.json
dist
DS_Store
55 changes: 47 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,50 @@

![rsgMLB](https://i.imgur.com/ltkGprY.png)

## Essentials
* **lambda.js** - main handler function used in AWS Lambda
* **helper_scripts/getPlayerYears.js** - Web scraper for fangraphs to get missing player start and end year data.

## AWS Lambda
Use the following npm commands:
* **setup** - calls node-lambda setup
* **deploy** - deploys function to AWS Lambda
## Overview

This repository contains the code for the @rsgMLB Twitter Bot, an automated system that posts interesting baseball statistics and facts. The bot is designed to run as an AWS Lambda function, periodically fetching data from Baseball-Reference.com and posting updates to Twitter.

## Features

- Scrapes player data from Baseball-Reference.com
- Parses HTML to extract relevant statistics
- Supports both position players and pitchers
- Generates engaging tweets based on player statistics
- Runs serverless on AWS Lambda

## Tech Stack

- TypeScript
- Node.js
- AWS Lambda
- Twitter API (via twitter-api-v2 and twitter-api-sdk)
- Cheerio for HTML parsing
- Axios for HTTP requests
- Jest for testing

## Project Structure

- `src/`: Contains the source TypeScript files
- `handler.ts`: Main Lambda function handler
- `parsePlayer.ts`: Logic for parsing player data from HTML
- `parsePlayer.test.ts`: Unit tests for the parsing logic
- `local.ts`: Script for running the bot locally
- `dist/`: Compiled JavaScript files
- `sample_data/`: HTML samples for testing

## Setup and Deployment

1. Clone the repository
2. Install dependencies: `npm install`
3. Set up environment variables (Twitter API keys, AWS credentials)
4. Build the project: `npm run build`
5. Deploy to AWS Lambda (refer to AWS documentation for deployment steps)

## Local Development

- Run tests: `npm test`
- Watch tests: `npm run test:watch`
- Start locally: `npm start`


619 changes: 0 additions & 619 deletions RememberSomeGuys.csv

This file was deleted.

39 changes: 39 additions & 0 deletions deploy/cloudwatch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

FUNCTION_NAME="rsg-mlb-bot"
RULE_NAME="${FUNCTION_NAME}-daily-trigger"

# Check if the CloudWatch Events rule exists
aws events describe-rule --name $RULE_NAME > /dev/null 2>&1
if [ $? -ne 0 ]; then
# Rule doesn't exist, create it
echo "Creating CloudWatch Events rule..."
aws events put-rule \
--name $RULE_NAME \
--schedule-expression "cron(0 12 * * ? *)" \
--state ENABLED

RULE_ARN=$(aws events describe-rule --name $RULE_NAME --query 'Arn' --output text)
echo "Source ARN: $RULE_ARN"

# Add permission to CloudWatch Events to invoke the Lambda function
aws lambda add-permission \
--function-name $FUNCTION_NAME \
--statement-id "${RULE_NAME}-event" \
--action 'lambda:InvokeFunction' \
--principal events.amazonaws.com \
--source-arn $RULE_ARN

LAMBDA_ARN=$(aws lambda get-function --function-name $FUNCTION_NAME --query 'Configuration.FunctionArn' --output text)

# Set the Lambda function as the target for the CloudWatch Events rule
aws events put-targets \
--rule $RULE_NAME \
--targets "Id"="1","Arn"="$LAMBDA_ARN"

echo "Daily trigger setup completed."
else
echo "CloudWatch Events rule already exists. Skipping creation."
fi

echo "CloudWatch rule script completed."
84 changes: 84 additions & 0 deletions deploy/lambda.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash

FUNCTION_NAME="rsg-mlb-bot"
RUNTIME="nodejs20.x"
ROLE="arn:aws:iam::016670670970:role/LambdaTwitterBotRole"
HANDLER="dist/handler.handler"
TIMEOUT=45

source .env

ENV_VARS='{
"Variables": {
"TWITTER_API_KEY":"'$TWITTER_API_KEY'",
"TWITTER_API_SECRET":"'$TWITTER_API_SECRET'",
"TWITTER_ACCESS_TOKEN":"'$TWITTER_ACCESS_TOKEN'",
"TWITTER_ACCESS_SECRET":"'$TWITTER_ACCESS_SECRET'"
}
}'

# Build the project
echo "Building the project..."
npm run build

# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Build failed. Exiting."
exit 1
fi

# Create a deployment package
echo "Creating deployment package..."
cp -r src/sample_data dist/sample_data
zip -r deployment.zip dist node_modules

# Check if the Lambda function exists
aws lambda get-function --function-name $FUNCTION_NAME > /dev/null 2>&1
if [ $? -eq 0 ]; then
# Function exists, update it
echo "Updating existing Lambda function code..."
aws lambda update-function-code \
--function-name $FUNCTION_NAME \
--zip-file fileb://deployment.zip

echo "Updated function code".

echo "Sleeping for 5 seconds..."
sleep 5

echo "Updating function configuration..."

# Update the function configuration
aws lambda update-function-configuration \
--function-name $FUNCTION_NAME \
--runtime $RUNTIME \
--handler $HANDLER \
--role $ROLE \
--timeout $TIMEOUT \
--environment "$ENV_VARS"
else
# Function doesn't exist, create it
echo "Creating new Lambda function..."
aws lambda create-function \
--function-name $FUNCTION_NAME \
--runtime $RUNTIME \
--role $ROLE \
--handler $HANDLER \
--timeout $TIMEOUT \
--zip-file fileb://deployment.zip \
--environment "$ENV_VARS"
fi

# Check if the deployment was successful
if [ $? -eq 0 ]; then
echo "Deployment successful!"
else
echo "Deployment failed."
exit 1
fi

# Clean up
echo "Cleaning up..."
rm deployment.zip

echo "Script completed."
13 changes: 0 additions & 13 deletions event.json

This file was deleted.

44 changes: 0 additions & 44 deletions helper_scripts/getPlayerYears.js

This file was deleted.

Loading

0 comments on commit d30738d

Please sign in to comment.