├── .gitignore ├── event.json ├── localTest.js ├── test └── gatewaySpec.js ├── service ├── gateway.js ├── databaseManager.js ├── icalGen.js ├── parser.js ├── s3saver.js └── index.js ├── serverless.env.yml ├── package.json ├── handler.js └── serverless.yml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | .serverless/ 4 | ical.ics -------------------------------------------------------------------------------- /event.json: -------------------------------------------------------------------------------- 1 | { 2 | "key3": "value3", 3 | "key2": "value2", 4 | "key1": "value1" 5 | } 6 | -------------------------------------------------------------------------------- /localTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const meetupService = require('./service/index'); 4 | const AWS = require('aws-sdk'); 5 | AWS.config.update({region:'us-east-1'}); 6 | 7 | const calendarEventId = 'awsfin'; 8 | //meetupService.getIcalEvents(calendarEventId); 9 | 10 | meetupService.setGroupId(calendarEventId); 11 | -------------------------------------------------------------------------------- /test/gatewaySpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gateway = require('../gateway'); 4 | 5 | describe('getMeetupEvents', function() { 6 | it('should get events response for event', function() { 7 | gateway.getMeetupEvents('awsfin').then(function (response) { 8 | expect(response).to.be.null; 9 | expect(response).to.not.be.undefined; 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /service/gateway.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var rp = require('request-promise'); 4 | 5 | var getMeetupEvents = function(event) { 6 | var options = { 7 | uri: 'https://api.meetup.com/'+ event +'/events', 8 | json: true // Automatically parses the JSON string in the response 9 | }; 10 | return rp(options); 11 | }; 12 | 13 | module.exports = { 14 | getMeetupEvents : getMeetupEvents 15 | }; 16 | -------------------------------------------------------------------------------- /serverless.env.yml: -------------------------------------------------------------------------------- 1 | # This is the Serverless Environment File 2 | # 3 | # It contains listing of your stages and their regions 4 | # It also manages serverless variables at 3 levels: 5 | # - common variables: variables that apply to all stages/regions 6 | # - stage variables: variables that apply to a specific stage 7 | # - region variables: variables that apply to a specific region 8 | 9 | vars: 10 | stages: 11 | dev: 12 | vars: 13 | regions: 14 | us-east-1: 15 | vars: 16 | -------------------------------------------------------------------------------- /service/databaseManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const AWS = require('aws-sdk-promise'); 4 | const dynamodb = new AWS.DynamoDB.DocumentClient(); 5 | 6 | function saveGroupIdToDatabase(groupId) { 7 | console.log("GroupId: " + groupId); 8 | var params = { 9 | 'TableName': "groups-table-3", 10 | 'Item': { 11 | groupid: groupId 12 | } 13 | }; 14 | return dynamodb.put(params).promise(); 15 | } 16 | 17 | module.exports = { 18 | saveGroupIdToDatabase : saveGroupIdToDatabase 19 | }; 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "meetup-event-collector-serverless", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "aws-sdk": "^2.6.12", 9 | "aws-sdk-promise": "0.0.2", 10 | "chai": "^3.5.0", 11 | "ical-generator": "^0.2.8", 12 | "mocha": "^3.0.2", 13 | "request": "^2.75.0", 14 | "request-promise": "^4.1.1" 15 | }, 16 | "scripts": { 17 | "test": "mocha" 18 | }, 19 | "author": "marcia villalba", 20 | "license": "ISC" 21 | } 22 | -------------------------------------------------------------------------------- /service/icalGen.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ical = require('ical-generator'); 4 | 5 | var icalGenerator = function(events) { 6 | var cal = ical(); 7 | 8 | events.map(function(event) { 9 | cal.createEvent({ 10 | start: new Date(event.time), 11 | summary: event.name, 12 | location: event.venueAddress, 13 | description: event.name + ' -- ' + 14 | event.description + ' -- ' + 15 | 'Register at: ' + event.link + ' -- ' + 16 | 'Location: ' + event.venueName + ' ' + event.venueAddress + ' -- ' + 17 | 'Organized by: ' + event.groupName, 18 | url: event.link 19 | }); 20 | }); 21 | 22 | return cal; 23 | }; 24 | 25 | module.exports = { 26 | icalGenerator : icalGenerator 27 | }; 28 | -------------------------------------------------------------------------------- /handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const meetupService = require('./service/index'); 4 | 5 | module.exports.getMeetupEventsCalendar = function(event, context, callback) { 6 | const calendarEventId = event.pathParameters.id; 7 | meetupService.getIcalEvents(calendarEventId); 8 | const response = { 9 | statusCode: 200, 10 | body: JSON.stringify({ "message": 'Calendar Created for ' + calendarEventId + '!'}) 11 | }; 12 | callback(null, response); 13 | } 14 | 15 | module.exports.setGroupId = function(event, context, callback) { 16 | const groupId = event.pathParameters.groupId; 17 | meetupService.setGroupId(groupId); 18 | const response = { 19 | statusCode: 200, 20 | body: JSON.stringify({"message": "GroupId " + groupId + " saved Successfully!"}) 21 | }; 22 | callback(null, response); 23 | } 24 | -------------------------------------------------------------------------------- /service/parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var parseMeetupEvents = function(jsonEvents) { 4 | var resultEvents = []; 5 | jsonEvents.map(function(jsonEvent) { 6 | var event = {}; 7 | event.id = jsonEvent.id; 8 | event.status = jsonEvent.status; 9 | event.name = jsonEvent.name; 10 | event.time = jsonEvent.time; 11 | event.link = jsonEvent.link; 12 | event.description = jsonEvent.description; 13 | event.venueName = jsonEvent.venue.name; 14 | event.venueAddress = jsonEvent.venue.address_1 + ', ' + jsonEvent.venue.city + ', ' + jsonEvent.venue.localized_country_name; 15 | event.groupName = jsonEvent.group.name; 16 | 17 | resultEvents.push(event); 18 | }); 19 | 20 | return resultEvents; 21 | }; 22 | 23 | module.exports = { 24 | parseMeetupEvents : parseMeetupEvents 25 | }; 26 | -------------------------------------------------------------------------------- /service/s3saver.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var AWS = require('aws-sdk'); 4 | var s3 = new AWS.S3(); 5 | var fs = require('fs'); 6 | 7 | function saveCalendarToS3(localFileName) { 8 | var s3 = new AWS.S3(); 9 | console.log("Start uploading file to S3"); 10 | 11 | fs.readFile(localFileName, function (err, data) { 12 | if (err) throw err; 13 | var param = {Bucket: 'meetup-event-collector-bucket', Key: 'ical-generated.ical', Body: data}; 14 | 15 | s3.upload(param, function(err, data) { 16 | 17 | // Whether there is an error or not, delete the temp file 18 | fs.unlink(localFileName, function (err) { 19 | if (err) console.error(err); 20 | console.log('Temp File Delete'); 21 | }); 22 | 23 | if (err) console.log(err, err.stack); 24 | else console.log('Successfully uploaded data'); 25 | }); 26 | }); 27 | } 28 | 29 | module.exports = { 30 | saveCalendarToS3 : saveCalendarToS3 31 | }; 32 | -------------------------------------------------------------------------------- /service/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const gateway = require('./gateway'); 4 | const parser = require('./parser'); 5 | const icalGen = require('./icalGen'); 6 | const s3saver = require('./s3saver'); 7 | const databaseManager = require('./databaseManager.js'); 8 | 9 | function getIcalEvents(eventId) { 10 | gateway.getMeetupEvents(eventId).then(function (response) { 11 | var events = parser.parseMeetupEvents(response); 12 | var ical = icalGen.icalGenerator(events); 13 | console.log(ical.toString()); 14 | var localFileName = '/tmp/ical.ics'; 15 | ical.saveSync(localFileName); 16 | s3saver.saveCalendarToS3(localFileName); 17 | 18 | }) 19 | .catch(function (err) { 20 | console.log(err); 21 | }); 22 | } 23 | 24 | function setGroupId(groupId) { 25 | databaseManager.saveGroupIdToDatabase(groupId).then(function (data) { 26 | console.log('Saving successful index'); 27 | }).catch(function (err) { 28 | console.log('Error: ' + err); 29 | }); 30 | } 31 | 32 | module.exports = { 33 | getIcalEvents: getIcalEvents, 34 | setGroupId: setGroupId 35 | }; 36 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Serverless! 2 | # 3 | # This file is the main config file for your service. 4 | # It's very minimal at this point and uses default values. 5 | # You can always add more config options for more control. 6 | # We've included some commented out config examples here. 7 | # Just uncomment any of them to get that config option. 8 | # 9 | # For full config options, check the docs: 10 | # v1.docs.serverless.com 11 | # 12 | # Happy Coding! 13 | 14 | service: meetup-event-collector # NOTE: update this with your service name 15 | 16 | provider: 17 | name: aws 18 | runtime: nodejs4.3 19 | iamRoleStatements: 20 | - Effect: Allow 21 | Action: 22 | - dynamodb:PutItem 23 | Resource: 24 | - "Fn::Join": ["", ["arn:aws:dynamodb:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":table/groups-table-3*"]] 25 | 26 | # you can overwrite defaults here 27 | #defaults: 28 | # stage: dev 29 | # region: us-east-1 30 | 31 | # you can add packaging information here 32 | #package: 33 | # include: 34 | # - include-me.js 35 | # exclude: 36 | # - exclude-me.js 37 | # artifact: my-service-code.zip 38 | 39 | functions: 40 | getCalendar: 41 | handler: handler.getMeetupEventsCalendar 42 | events: 43 | - http: 44 | path: meetupevents/calendar/{id} 45 | method: get 46 | private: true 47 | setGroupId: 48 | handler: handler.setGroupId 49 | events: 50 | - http: 51 | path: meetupevents/groupId/{groupId} 52 | method: put 53 | private: true 54 | # - s3: ${bucket} 55 | # - schedule: rate(10 minutes) 56 | # - sns: greeter-topic 57 | 58 | # you can add CloudFormation resource templates here 59 | #resources: 60 | resources: 61 | Resources: 62 | GroupsIdTable: 63 | Type: "AWS::DynamoDB::Table" 64 | Properties: 65 | AttributeDefinitions: 66 | - AttributeName: "groupid" 67 | AttributeType: "S" 68 | KeySchema: 69 | - AttributeName: "groupid" 70 | KeyType: "HASH" 71 | ProvisionedThroughput: 72 | ReadCapacityUnits: 1 73 | WriteCapacityUnits: 1 74 | TableName: "groups-table-3" 75 | # Resources: 76 | # NewResource: 77 | # Type: AWS::S3::Bucket 78 | # Properties: 79 | # BucketName: my-new-bucket 80 | # Outputs: 81 | # NewOutput: 82 | # Description: "Description for the output" 83 | # Value: "Some output value" 84 | --------------------------------------------------------------------------------