{"type_of":"article","id":88679,"title":"Inspired by @thevuedev, I created @TheReactDev","description":"\n\nThis weekend I stumbled upon this article:\n\n\n\n        \n          \n            \n...","readable_publish_date":"Mar 6 '19","slug":"inspired-by-thevuedev-i-created-thereactdev-55g2","path":"/frontendwizard/inspired-by-thevuedev-i-created-thereactdev-55g2","url":"https://dev.to/frontendwizard/inspired-by-thevuedev-i-created-thereactdev-55g2","comments_count":4,"public_reactions_count":43,"collection_id":null,"published_timestamp":"2019-03-06T01:14:36Z","language":null,"subforem_id":null,"positive_reactions_count":43,"cover_image":"https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwl60s4xomb46tlf874uv.png","social_image":"https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwl60s4xomb46tlf874uv.png","canonical_url":"https://dev.to/frontendwizard/inspired-by-thevuedev-i-created-thereactdev-55g2","created_at":"2019-03-06T01:14:36Z","edited_at":null,"crossposted_at":null,"published_at":"2019-03-06T01:14:36Z","last_comment_at":"2019-03-06T23:42:11Z","reading_time_minutes":2,"tag_list":"react, serverless","tags":["react","serverless"],"body_html":"\u003cp\u003eThis weekend I stumbled upon this article:\u003c/p\u003e\n\n\n\u003cdiv class=\"ltag__link\"\u003e\n  \u003ca href=\"/danielelkington\" class=\"ltag__link__link\"\u003e\n    \u003cdiv class=\"ltag__link__pic\"\u003e\n      \u003cimg src=\"https://res.cloudinary.com/practicaldev/image/fetch/s--iEq0is24--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--2pE2E74D--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/82772/83023ddf-9c80-40e3-a2ae-44f8c4a4d8dd.jpeg\" alt=\"danielelkington image\" loading=\"lazy\"\u003e\n    \u003c/div\u003e\n  \u003c/a\u003e\n  \u003ca href=\"/danielelkington/a-bot-that-tweets-new-dev-articles-about-vue-4p5a\" class=\"ltag__link__link\"\u003e\n    \u003cdiv class=\"ltag__link__content\"\u003e\n      \u003ch2\u003eA bot that tweets new DEV articles about Vue\u003c/h2\u003e\n      \u003ch3\u003eDaniel Elkington ・ Mar  3 '19 ・ 6 min read\u003c/h3\u003e\n      \u003cdiv class=\"ltag__link__taglist\"\u003e\n        \u003cspan class=\"ltag__link__tag\"\u003e#vue\u003c/span\u003e\n        \u003cspan class=\"ltag__link__tag\"\u003e#typescript\u003c/span\u003e\n        \u003cspan class=\"ltag__link__tag\"\u003e#serverless\u003c/span\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\n\u003cp\u003eAnd I immediately thought: \"Hey, this is an awesome idea. Let's make one about React as well, cause why not?\"\u003c/p\u003e\n\n\u003cp\u003eSo I did. I created a bot that checks dev.to/t/react/latest every minute and tweets any new article. Here it is: \u003ca href=\"https://twitter.com/thereactdev\"\u003e@TheReactDev\u003c/a\u003e\u003c/p\u003e\n\n\u003ch1\u003e\n  \u003ca name=\"typescript-nah\" href=\"#typescript-nah\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  TypeScript? Nah.\n\u003c/h1\u003e\n\n\u003cp\u003eI choose not to do TypeScript on this one. It is a super small function and I felt like JavaScript would get the job done faster.\u003c/p\u003e\n\n\u003ch1\u003e\n  \u003ca name=\"serverless\" href=\"#serverless\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  Serverless\n\u003c/h1\u003e\n\n\u003cp\u003eYou have many options when you do serverless. You can go AWS, Azure, GCloud, etc. The article explains in detail how to setup the Azure function and because I had never used Azure before, I followed along. The integration of Azure with VSCode is pretty cool, can't deny it, but I might switch up later on for the serverless framework to be sort of platform agnostic. Not that it matters for a project like this though. 😄\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eUPDATE\u003c/strong\u003e: I had some headaches with azure. Probably because I don't have much experience with. So after a couple of hours I switched to AWS with the serverless framework for the tooling.\u003c/p\u003e\n\n\u003ch1\u003e\n  \u003ca name=\"scraping\" href=\"#scraping\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  Scraping\n\u003c/h1\u003e\n\n\u003cp\u003eBecause dev.to does not have an api yet, I had to scrape away the data from the url. I had used puppeteer before, but I absolutely loved the \u003ccode\u003ex-ray\u003c/code\u003e lib. The API is so clean. I'll definitely use more of it.\u003c/p\u003e\n\n\u003ch1\u003e\n  \u003ca name=\"problems-i-had\" href=\"#problems-i-had\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  Problems I had\n\u003c/h1\u003e\n\n\u003cp\u003eAt first, when I fetched the recent tweets from the @TheReactDev, the twitter api didn't always returned the posted urls on the entities.\u003cbr\u003e\n\u003c/p\u003e\n\n\u003cdiv class=\"highlight\"\u003e\u003cpre class=\"highlight javascript\"\u003e\u003ccode\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\n  \u003cspan class=\"c1\"\u003e//...\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ehttps://t.co/AA3sKrLsDZ\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003eexpanded_url\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\n       \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ehttps://dev.to/peterj/run-a-react-app-in-a-docker-container-kjn\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003edisplay_url\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003edev.to/peterj/run-a-r…\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003eindices\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ehttps://t.co/hptME9oAgf\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003eexpanded_url\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ehttps://twitter.com/i/web/status/1102686466436681731\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003edisplay_url\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003etwitter.com/i/web/status/1…\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"na\"\u003eindices\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e],\u003c/span\u003e\n  \u003cspan class=\"c1\"\u003e// ..\u003c/span\u003e\n\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\n\u003cp\u003eBecause of this, I started checking for the article title and author on the tweet body. The problem is that the twitter API sometimes truncate the body. The solution to this was to use the \u003ccode\u003etweet_mode: \"extended\"\u003c/code\u003e on the request for the tweets.\u003c/p\u003e\n\n\u003cp\u003eBut, just as I was writing this post, I observed that this also solves the problem of the links. With this mode, the twitter API not only returns the \u003ccode\u003efull_text\u003c/code\u003e but also returns the full \u003ccode\u003eextended_url\u003c/code\u003e as well. 😅\u003c/p\u003e\n\n\u003cp\u003eChecking for the URL is way more reliable so I'm rewriting my function to use this as well.\u003c/p\u003e\n\u003ch1\u003e\n  \u003ca name=\"telegram\" href=\"#telegram\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  Telegram\n\u003c/h1\u003e\n\n\u003cp\u003eI also added a telegram bot that sends a message to a channel in case things go wrong. I choose telegram because it'll probably be the fastest way that the notification reaches me.\u003c/p\u003e\n\u003ch1\u003e\n  \u003ca name=\"the-repo\" href=\"#the-repo\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  The repo\n\u003c/h1\u003e\n\n\n\u003cdiv class=\"ltag-github-readme-tag\"\u003e\n  \u003cdiv class=\"readme-overview\"\u003e\n    \u003ch2\u003e\n      \u003cimg src=\"https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg\" alt=\"GitHub logo\" loading=\"lazy\"\u003e\n      \u003ca href=\"https://github.com/frontendwizard\"\u003e\n        frontendwizard\n      \u003c/a\u003e / \u003ca style=\"font-weight: 600;\" href=\"https://github.com/frontendwizard/TheReactDev\"\u003e\n        TheReactDev\n      \u003c/a\u003e\n    \u003c/h2\u003e\n    \u003ch3\u003e\n      The function that feeds @TheReactDev twitter.\n    \u003c/h3\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"ltag-github-body\"\u003e\n    \n\u003cdiv id=\"readme\" class=\"md\" data-path=\"README.md\"\u003e\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003ch1\u003e\nTheReactDev\u003c/h1\u003e\n\u003cp\u003eThe function that feeds @TheReactDev twitter.\u003c/p\u003e\n\u003cp\u003eThis project was inspired by\n\u003ca href=\"https://dev.to/danielelkington/a-bot-that-tweets-new-dev-articles-about-vue-4p5a\" rel=\"nofollow\"\u003ethis article\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThis function depends on a few environment variables:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003ccode\u003edev_tag\u003c/code\u003e: the dev.to tag to which the crawler will get the latest articles.\u003c/li\u003e\n\u003cli\u003e\n\u003ccode\u003etwitter_bot_screen_name\u003c/code\u003e: the name of the account that will tweet the\narticles.\u003c/li\u003e\n\u003cli\u003eTwitter keys\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003etwitter_consumer_key\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etwitter_consumer_secret\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etwitter_access_token\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etwitter_access_token_secret\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003ccode\u003etelegram_bot_token\u003c/code\u003e: the telegram bot who's going to log messages for\nmaintenance/debug purposes\u003c/li\u003e\n\u003cli\u003e\n\u003ccode\u003etelegram_chat_id\u003c/code\u003e: the channel where the bot will send messages\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eYou just need to create a \u003ccode\u003eenv.yml\u003c/code\u003e file and put those values in, like this:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003edev_tag\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ereact\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etwitter_bot_screen_name\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eNameOfTheTwitterAccount\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etwitter_consumer_key\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etwitter_consumer_secret\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etwitter_access_token\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etwitter_access_token_secret\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etelegram_bot_token\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003etelegram_chat_id\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e...\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp\u003eIt's worth noting that I used telegram here because it was simple and it\nprobably is the…\u003c/p\u003e\u003c/article\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"gh-btn-container\"\u003e\u003ca class=\"gh-btn\" href=\"https://github.com/frontendwizard/TheReactDev\"\u003eView on GitHub\u003c/a\u003e\u003c/div\u003e\n\u003c/div\u003e\n\n\n\n\u003ch1\u003e\n  \u003ca name=\"like-it\" href=\"#like-it\" class=\"anchor\"\u003e\n  \u003c/a\u003e\n  Like it?\n\u003c/h1\u003e\n\n\u003cp\u003eWell, it was super fun doing this. The feeling that you get when you see the function publishing new articles on twitter is amazing. 😄\u003c/p\u003e\n\n\u003cp\u003eIf you like it, be sure to follow the \u003ca href=\"https://twitter.com/thereactdev\"\u003e@TheReactDev\u003c/a\u003e on twitter!\u003c/p\u003e\n\n\u003cp\u003eThank you for your time and until the next one!\u003c/p\u003e\n\n","body_markdown":"This weekend I stumbled upon this article:\n\n{% link https://dev.to/danielelkington/a-bot-that-tweets-new-dev-articles-about-vue-4p5a %}\n\nAnd I immediately thought: \"Hey, this is an awesome idea. Let's make one about React as well, cause why not?\"\n\nSo I did. I created a bot that checks dev.to/t/react/latest every minute and tweets any new article. Here it is: [@TheReactDev](https://twitter.com/thereactdev)\n\n# TypeScript? Nah.\n\nI choose not to do TypeScript on this one. It is a super small function and I felt like JavaScript would get the job done faster.\n\n# Serverless\n\nYou have many options when you do serverless. You can go AWS, Azure, GCloud, etc. The article explains in detail how to setup the Azure function and because I had never used Azure before, I followed along. The integration of Azure with VSCode is pretty cool, can't deny it, but I might switch up later on for the serverless framework to be sort of platform agnostic. Not that it matters for a project like this though. :smile:\n\n**UPDATE**: I had some headaches with azure. Probably because I don't have much experience with. So after a couple of hours I switched to AWS with the serverless framework for the tooling.\n\n# Scraping\n\nBecause dev.to does not have an api yet, I had to scrape away the data from the url. I had used puppeteer before, but I absolutely loved the `x-ray` lib. The API is so clean. I'll definitely use more of it.\n\n# Problems I had\n\nAt first, when I fetched the recent tweets from the @TheReactDev, the twitter api didn't always returned the posted urls on the entities.\n\n\n```js\n[\n  //...\n  [ { url: 'https://t.co/AA3sKrLsDZ',\n      expanded_url:\n       'https://dev.to/peterj/run-a-react-app-in-a-docker-container-kjn',\n      display_url: 'dev.to/peterj/run-a-r…',\n      indices: [Array] } ],\n  [ { url: 'https://t.co/hptME9oAgf',\n      expanded_url: 'https://twitter.com/i/web/status/1102686466436681731',\n      display_url: 'twitter.com/i/web/status/1…',\n      indices: [Array] } ],\n  // ..\n]\n```\n\nBecause of this, I started checking for the article title and author on the tweet body. The problem is that the twitter API sometimes truncate the body. The solution to this was to use the `tweet_mode: \"extended\"` on the request for the tweets.\n\nBut, just as I was writing this post, I observed that this also solves the problem of the links. With this mode, the twitter API not only returns the `full_text` but also returns the full `extended_url` as well. :sweat_smile:\n\nChecking for the URL is way more reliable so I'm rewriting my function to use this as well.\n\n# Telegram\n\nI also added a telegram bot that sends a message to a channel in case things go wrong. I choose telegram because it'll probably be the fastest way that the notification reaches me.\n\n# The repo\n\n{% github thefrontendwizard/TheReactDev %}\n\n# Like it?\n\nWell, it was super fun doing this. The feeling that you get when you see the function publishing new articles on twitter is amazing. :smile:\n\nIf you like it, be sure to follow the [@TheReactDev](https://twitter.com/thereactdev) on twitter!\n\nThank you for your time and until the next one!","user":{"name":"Juliano Rafael","username":"frontendwizard","twitter_username":"frontendwizard","github_username":"frontendwizard","user_id":23686,"website_url":null,"profile_image":"https://media2.dev.to/dynamic/image/width=640,height=640,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23686%2F3573b002-cdbc-4979-bd12-d4a2a0a631b6.jpeg","profile_image_90":"https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23686%2F3573b002-cdbc-4979-bd12-d4a2a0a631b6.jpeg"}}