{"id":80,"date":"2022-08-02T02:24:42","date_gmt":"2022-08-02T02:24:42","guid":{"rendered":"https:\/\/mudbrain.xyz\/?p=80"},"modified":"2022-10-03T22:51:30","modified_gmt":"2022-10-03T22:51:30","slug":"a-small-prank","status":"publish","type":"post","link":"https:\/\/mudbrain.xyz\/?p=80","title":{"rendered":"a small prank"},"content":{"rendered":"\n<p>I was having a conversation with a friend at a small house party one day about how wrong she was regarding the GameStock stock. She firmly believes that the stock will \u2018moon\u2019 too far beyond $1000. Maybe all the way to $10,000. Could it go further? As far as she is concerned, it totally could.<\/p>\n\n\n\n<p>Her belief in the stock (not even the company!) was ridiculous enough that I decided to make sure my ridicule was programmatically dished out everyday in the form of a message that tells her just how far away it was from her ludicrous ideas.<\/p>\n\n\n\n<p>The first thing I needed to do was figure out <em>how<\/em> exactly I was going to do this. I settled on coding it as much as I could in Python. The main reason was because it\u2019s an easy language. However, I learned so much doing this stupid little gag, that I realized the project was a teaching tool too.<\/p>\n\n\n\n<p>Learning, what a concept?<\/p>\n\n\n\n<p>To begin, I knew I needed to get the stock price of GameStop daily. Thankfully, that would be very easy as I was sure I could find an API that gave me free access to stock prices. I was right; not much tension there. Within a few moments of searching, I settled on FinnHub as my stock price provider. Since this was such a small project, their limitations were unproblematic and their Python package was simple to use.<\/p>\n\n\n\n<p>Now that I could easily call their API and get the stock price, I needed to get a method of sending a message. But what kind of message? I couldn\u2019t do a Discord message as that would be against their EULA and get me banned. I also couldn\u2019t do a Twitter bot as my friend isn\u2019t on Twitter. Instagram wouldn\u2019t make sense. She also didn\u2019t have Facebook Messenger. There was only one option left that made sense: good ol\u2019 SMS.<\/p>\n\n\n\n<p>I went back to DuckDuckGo (yes, I use it instead of Google) and found that Twilio was perfect. It was inexpensive to send a message\u2014about $0.0017 per SMS plus a $1 for a number\u2014and they provide some pretty solid documentation. Oh yeah, they have a solid Python library which means less coding from scratch.<\/p>\n\n\n\n<p>So now I\u2019m armed with two APIs that come with their own keys and tokens. It is now time to for me to employ them considering they don\u2019t do much without being given some direction.<\/p>\n\n\n\n<p>The first thing I learned was how to was set environment variables to protect the keys (and later phone numbers). Turns out they are pretty nifty at protecting secure pieces of information without embedding it into the source code.<\/p>\n\n\n\n<p>I created a virtual environment to keep my computer nice and clean from the random Finnhub and Twilio Python packages that would otherwise be floating around. I loaded those environment variables into the source and started looking at how to grab the price of $GME from the FinnHub API.<\/p>\n\n\n\n<p>Turns out the \u201cGetting Started\u201d documents from FinnHub for their Python package basically wrote the function for me. It was almost as easy a copy and paste. The only major difference was fitting it nicely into a function and making sure it pulls the price of the stock.<\/p>\n\n\n\n<p>It looks something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def getGMEprice():    finnhub_client = finnhub.Client(api_key=os.environ&#91;'FINNHUB_API_KEY'])    quote = finnhub_client.quote('GME')    return quote<\/code><\/pre>\n\n\n\n<p>The <code>return<\/code> statement was a bit of pride from my part because I learned how to send data I got back into a function that can then be used when the function is called.<\/p>\n\n\n\n<p>Next I needed to write a function that would actually fire off the text message using the Twilio API. I split it into two functions as I wanted two messages. I could probably turn it into one function but as of right now it works and I\u2019d rather not mess with it. Here is what it looks like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def send_up_message(price):\n    price = price\n    distanceFrom = 1000 - float(price&#91;\"c\"])\n    toSend = 'The price of GME went up by {}% (booo!) and is now: ${}. That is still ${} away from $1000 >:)'.format(price&#91;\"dp\"], price&#91;\"c\"], distanceFrom)\n\n    message = client.messages.create(  \n                                messaging_service_sid=messaging_service_sid, \n                                body=toSend,\n                                from_='+12513251057',      \n                                to=os.environ&#91;'RK_PHONE']\n                            <\/code><\/pre>\n\n\n\n<p>There are a couple of things here that I\u2019m quite proud of: the inclusion of an argument, the use of a Python f-string, and the fact that I successfully used the array location to grab just the data I needed.<\/p>\n\n\n\n<p>I have struggled with the idea of arguments required for functions for quite some time, but here, it seemed to click. The whole <code>price = price<\/code> actually made sense the moment I wrote it down. It takes the <code>price<\/code> object from the function argument and assigns it to another variable that I called <code>price<\/code>. Brilliant.<\/p>\n\n\n\n<p>The last bit of code that I loaded up in my Python script was a <code>main<\/code> function that simply calls <code>getGMEprice()<\/code> and loads it to a <code>price<\/code> variable that can then be placed into the argument for the message functions. All that is determined by a dinky <code>if<\/code> statement that checks if the price went up or down. Boom. It works.<\/p>\n\n\n\n<p>Kinda sort of, not exactly.<\/p>\n\n\n\n<p>Here is where a bulk of my time went: implementing my code. I knew I needed to load it into the cloud, since I don\u2019t have a small computer that can run 24\/7 (anymore), yet didn\u2019t know where. I was aiming toward doing this on a Digital Ocean Function but realized they didn\u2019t support scheduling apps. That became an instant no-go. I avoid AWS only because I don\u2019t like Amazon. Maybe to my detriment, but I digress.<\/p>\n\n\n\n<p>I settled on Google Cloud Apps as it was lightning quick to setup, required no major hassle loading the Python packages, and was super easy to setup my <em>environment variables<\/em>. After a few tests, it was time to see how to schedule it.<\/p>\n\n\n\n<p>Turns out, I needed to add another small function to my script called <code>hello_pubsub<\/code> that takes an <code>event<\/code> and a <code>context<\/code> to run. When it\u2019s triggered it runs <code>main<\/code> which runs the rest of the program. I had to translate a Monday through Friday at 1pm Pacific time trigger into cron (which wasn\u2019t fun) but now it runs!<\/p>\n\n\n\n<p>All this for a stupid little gag. I learned a ton and the best part was her reaction when she realized it was me. She originally thought there was a data leak somewhere but her other coworkers didn\u2019t receive a text message. Within moments she narrowed it down to me\u2014flattered, if disappointed it didn\u2019t take longer\u2014and sent me some all caps messages in incredulity.<\/p>\n\n\n\n<p>Anyways, this was a lot of fun coding and learning. The result has been a lot of fun and it reminds her how garbage $GME is.<\/p>\n\n\n\n<p>Cheers!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was having a conversation with a friend at a small house party one day about how wrong she was regarding the GameStock stock. She firmly believes that the stock will \u2018moon\u2019 too far beyond $1000. Maybe all the way to $10,000. Could it go further? As far as she is concerned, it totally could. &hellip; <\/p>\n","protected":false},"author":1,"featured_media":70,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[10,11],"tags":[],"class_list":["post-80","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-life","category-technology"],"_links":{"self":[{"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/posts\/80","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=80"}],"version-history":[{"count":2,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":115,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions\/115"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=\/wp\/v2\/posts\/70"}],"wp:attachment":[{"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mudbrain.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}