Πώς να δημιουργήσετε ένα bot GitHub με πλαίσιο PhantomJS, React και χωρίς διακομιστή

Πώς να δημιουργήσετε ένα bot GitHub με πλαίσιο PhantomJS, React και χωρίς διακομιστή

Αυτό το σεμινάριο αφορά τη δημιουργία ενός απλού bot χωρίς διακομιστή που επιστρέφει ένα γράφημα με κορυφαίους συντελεστές αποθετηρίου GitHub για μια επιλεγμένη περίοδο. Είναι σχετικό με όσους έχουν κάποια εμπειρία με React, JavaScript, TypeScript, Node.js, Amazon Web Services (AWS) και το πλαίσιο χωρίς διακομιστή.

Μπορείτε να δείτε τον κωδικό στο Github.

Υπηρεσίες και εργαλεία που θα χρησιμοποιούμε

Πριν προχωρήσουμε στην κωδικοποίηση, ας κάνουμε μια γρήγορη επισκόπηση των υπηρεσιών και εργαλείων AWS που θα χρησιμοποιήσουμε.

Για την ανάκτηση κορυφαίων συντελεστών αποθετηρίου, θα χρησιμοποιήσουμε το GitHub stats API, το εκπληκτικό Nivo για την εμφάνιση δεδομένων, το Storybook για να ελέγξουμε πώς φαίνεται και αισθάνεται το γράφημα μας, PhantomJS για να μετατρέψει HTML σε εικόνα και πλαίσιο χωρίς διακομιστή για να αλληλεπιδράσει με το AWS.

Ας αρχίσουμε

Θα χρησιμοποιώ TypeScript. Εάν προτιμάτε το ES6, θα πρέπει να ρυθμίσετε το Babel.

Αρχικά, πρέπει να δημιουργήσετε tsconfig.jsonστη ρίζα του αποθετηρίου σας. Επιλογές για προσοχή που περιλαμβάνουν:

"module": "commonjs","target": "es5","lib": ["es6", "esnext.asynciterable"],"moduleResolution": "node","jsx": "react"

Στη συνέχεια, θα δημιουργήσουμε ένα απλό API για να ζητήσετε στατιστικά στοιχεία από το GitHub. Μπορείτε να ακολουθήσετε τη δομή αρχείων από το repo GitHub ή να χρησιμοποιήσετε τη δική σας. Για παράδειγμα:

Για να αποκτήσετε πρόσβαση στο GitHub API, θα πρέπει να δημιουργήσετε ένα προσωπικό διακριτικό πρόσβασης.

Αυτή η ενότητα απλώς στέλνει το αίτημα με το παρεχόμενο διακριτικό και ανακτά τα δεδομένα.

Εμφάνιση γραφημάτων

Για να εμφανίσουμε τα δεδομένα, θα χρησιμοποιήσουμε το Nivo και το Storybook. Ένα απλό συστατικό μπορεί να μοιάζει με αυτό:

Αρχικά, ρυθμίστε τα Storybooks εκτελώντας την ακόλουθη εντολή στον ριζικό φάκελο:

npm i -g @storybook/cligetstorybook

Αντιγράψτε το φάκελο .storybook στο ριζικό αποθετήριο και αντικαταστήστε όλα τα υπάρχοντα αρχεία. Περιέχει τη διαμόρφωση Webpack και Storybook. Δημιουργήστε ένα storiesφάκελο και τοποθετήστε ένα δείγμα ιστορίας για το στοιχείο σας:

Εκτελέστε npm run storybookκαι ανοίξτε το localhost στο πρόγραμμα περιήγησης. Θα πρέπει να δείτε το ακόλουθο αποτέλεσμα:

Προσπαθήστε να παίξετε με τις επιλογές και τα δεδομένα δοκιμής. Το Storybook θα αλλάξει την εμφάνιση αμέσως.

Μετατροπή HTML σε PNG

Συνήθως, τα συστήματα συνομιλίας όπως το Facebook Messenger και το Slack δεν επιτρέπουν στους χρήστες να εισάγουν κάρτες HTML στο διάλογο, οπότε το επόμενο βήμα θα είναι η δημιουργία ενός βοηθού που μετατρέπει το HTML σε εικόνα PNG.

Χρησιμοποιώντας ένα απλό σενάριο με βιβλιοθήκη jsdom, μπορούμε να μιμηθούμε τη συμπεριφορά του προγράμματος περιήγησης και να σειριοποιήσουμε HTML, όπως αυτό:

createDomForChartεπιστρέφει μια νέα παρουσία του jsdom και η συνάρτηση γραφήματος καλεί απλώς dom.serialize()όταν γίνεται η απόδοση των στοιχείων.

Με το PhantomJS, μπορούμε να μετατρέψουμε τη σήμανση σε εικόνα χρησιμοποιώντας αυτό το απλό σενάριο:

Περνάμε screenshot.jsστην phantomjsεκτελέσιμη διαδρομή - μαζί με μια συμβολοσειρά HTML, πλάτος και ύψος - και επιστρέφουμε στην προσωρινή μνήμη με την εικόνα που αποδίδεται

Ίσως παρατηρήσετε ότι έχω χρησιμοποιήσει δύο δυαδικά αρχεία PhantomJS (για OS X και Linux). Χρειαζόμαστε την έκδοση Linux περαιτέρω σε περιβάλλον AWS. Μπορείτε να τα κατεβάσετε από το PhantomJS.org ή να χρησιμοποιήσετε αρχεία από το αποθετήριο.

Δένοντας τα πάντα

Τώρα, ας δημιουργήσουμε λάμδα για να χειριστούμε τα αιτήματα. Συνιστώ να βάλετε τη λογική απόδοσης PNG σε ξεχωριστή υπηρεσία. Επειδή το PhantomJS binary έχει μέγεθος περίπου 50 mb, επιβραδύνει την ανάπτυξη εάν αλλάξετε κάτι στο API. Επίσης, μπορείτε να επαναχρησιμοποιήσετε αυτό το λάμδα για άλλους σκοπούς.

Θα ξεκινήσουμε δημιουργώντας webpack.config.ts(για να ομαδοποιήσουμε τον πηγαίο κώδικα) και serverless.base.js(για να ορίσουμε τη διαμόρφωση χωρίς διακομιστή) στον ριζικό φάκελο.

Εάν θέλετε να μάθετε περισσότερα σχετικά με τις περιπτώσεις χρήσης διαμορφώσεων JavaScript χωρίς διακομιστή, μπορείτε να το διαβάσετε στο προηγούμενο άρθρο μου.

Θα πρέπει να αλλάξετε τα ονόματα ανάπτυξης και κάδου εικόνας, όπως αυτό:

deploymentBucket: { name: 'com.github-stats....deploys'},environment: { BUCKET: 'com.github-stats....images', GITHUB_TOKEN: '${env:GITHUB_TOKEN}', SLACK_TOKEN: '${env:SLACK_TOKEN}, STAGE: '${self:provider.stage}'},

Αυτό συμβαίνει επειδή το όνομα του κάδου πρέπει να είναι παγκοσμίως μοναδικό.

Μετατροπή HTML σε υπηρεσία PNG

Πρώτα απ 'όλα, θα δημιουργήσουμε ένα πρόγραμμα χειρισμού που θα επιστρέψει μια διεύθυνση URL της δημιουργημένης εικόνας. Ο διαχειριστής πρέπει να επικυρώσει και να επεξεργαστεί το σώμα αιτήματος:

… Και αν όλα είναι εντάξει, θα πρέπει να δημιουργήσει την εικόνα και να την τοποθετήσει σε κάδο S3.

Ας δημιουργήσουμε webpack.config.tsγια να ομαδοποιήσουμε αρχεία προέλευσης. Θα χρησιμοποιήσουμε τα copy-webpack-pluginκαι webpack-permissions-pluginγια να συμπεριλάβουμε τα δυαδικά αρχεία PhantomJS σε ένα πακέτο - και θα δώσουμε δικαιώματα για εκτέλεση. Αυτό θα απαιτήσει να εκτελέσουμε την εντολή ανάπτυξης με sudo, καθώς το Webpack δεν έχει δικαιώματα τροποποίησης των δικαιωμάτων συστήματος αρχείων από προεπιλογή.

Το τελευταίο βήμα είναι να χρησιμοποιήσετε το serverless.jsαρχείο για να συνδέσετε τον χειριστή μας με ένα συμβάν API Gateway.

Τώρα, πρέπει να εκτελέσουμε τα ίδια βήματα για τον χειρισμό στατιστικών, αλλά δεν χρειάζεται να κάνουμε καμία αλλαγή webpack.config.ts.

Η μόνη διαφορά είναι μια πρόσθετη άδεια για επίκληση του lambda:

iamRoleStatements: [ ...baseConfig.provider.iamRoleStatements,{ Effect: 'Allow', Action: ['lambda:InvokeFunction'], Resource: ['*']}]

Ρύθμιση του Slack bot

The last step will be to create a service that will handle message events for the bot. To keep it simple, we’ll handle only mention events. Let’s set up the basic event handler.

We have to handle a verification event from Slack and respond with 200 status and challenge parameters:

callback(null, { body: JSON.stringify({ challenge: (slackEvent as VerificationEvent).challenge }), statusCode: 200});

To properly handle a Slack event, the endpoint has to reply within 3000 milliseconds (3 seconds), so we’ll have to immediately respond and asynchronously send a follow-up message using postMessage API.

In the code above, we parsed the message text to extract a repository name and called out an image stats lambda to retrieve an image URL and send a message back to Slack. You can find the full code of the handler here.

Code for serverless.js and Webpack configurations would be similar to the stats service, so if you have problems with setting it up, take a look at the full source code.

Creating a Slack app

Now let’s create a new Slack app. Go to the Slack API, create a new account (if you have not already done so), create a new app, and add the bot scope in the scopes section.

Go to the “OAuth & Permissions” section in the sidebar.

Add the bot user scope.

Then, you’ll be able to install the app to your organization and get access to tokens.

Deploying the services

You’ll have to install a serverless framework version greater than 1.26 because earlier versions do not support JavaScript configuration files. And I recommend installing slx to simplify the deployment of multiple services.

npm install -g serverlessnpm install -g serviceless

Copy the GitHub and Slack bot tokens, and set them to GITHUB_TOKEN and SLACK_TOKEN environment variables accordingly. Run the following command in the terminal:

sudo GITHUB_TOKEN= SLACK_TOKEN= slx deploy all

As mentioned above, we need sudo to set execute permissions to PhantomJS binaries.

Be patient! Deployment may take a while. At the end you should see a similar output:

Deployment completed successfuly
[app/html-to-png] [completed]:Service Informationservice: html-to-pngstage: devregion: us-east-1stack: html-to-png-devapi keys: Noneendpoints: Nonefunctions: renderToPng: html-to-png-dev-renderToPngServerless: Removing old service versions...[app/slack] [completed]:Service Informationservice: git-stats-slackstage: devregion: us-east-1stack: git-stats-slack-devapi keys: Noneendpoints: POST - //xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/stats/slack/event-handlerfunctions: eventHandler: git-stats-slack-dev-eventHandlerServerless: Removing old service versions...[app/stats] [completed]:Service Informationservice: git-statsstage: devregion: us-east-1stack: git-stats-devapi keys: Noneendpoints: GET - //xxxxxx.execute-api.us-east-1.amazonaws.com/dev/stats/contributors/{owner}/{repo}functions: getContributorStatsImage: git-stats-dev-getContributorStatsImageServerless: Removing old service versions...

The last step will be to subscribe our endpoint to bot mention events.

Select the “Event Subscription” section in the Slack API navigation.

Then paste the event handler URL that you can find in the deploy command output.

Time to play around a bit! Here are some examples of rendered images:

serverless/serverless

facebook/react

plouc/nivo

That’s it!

I hope you found this article helpful. I’d love to see in the comments other types of stats you would like to see in the service.

Παρακαλώ χειροκρότημα αν σας άρεσε το άρθρο! Και αν θέλετε να συνομιλήσετε ή να συνδεθείτε, μπορείτε να με βρείτε στο Twitter, το GitHub και το Linkedin.