{"id":1603,"date":"2021-09-11T12:44:09","date_gmt":"2021-09-11T10:44:09","guid":{"rendered":"https:\/\/hannes.enjoys.it\/blog\/?p=1603"},"modified":"2022-04-30T13:21:27","modified_gmt":"2022-04-30T11:21:27","slug":"how-to-build-your-own-aerial-image-twitter-bot","status":"publish","type":"post","link":"https:\/\/hannes.enjoys.it\/blog\/2021\/09\/how-to-build-your-own-aerial-image-twitter-bot\/","title":{"rendered":"How to build your own aerial image Twitter bot"},"content":{"rendered":"\n<p><a href=\"https:\/\/gitlab.com\/Hannes42\/twitter-image-bot\">https:\/\/gitlab.com\/Hannes42\/twitter-image-bot<\/a><\/p>\n\n\n\n<p>About a year ago I built a small <a href=\"https:\/\/twitter.com\/IrgendwoHH\">Twitter bot that posts an aerial image of Hamburg, Germany every day<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"543\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-31.png\" alt=\"\" class=\"wp-image-1611\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-31.png 623w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-31-300x261.png 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/figure>\n\n\n\n<p>As I will shut it down (no reason, just decluttering) here&#8217;s how it works so you can run your own:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Have aerial images with a permissive license<\/li><li>Register a Twitter account and set it up for posting via API access<\/li><li>Write code to pick an image and post it<\/li><\/ol>\n\n\n\n<p>Done!<\/p>\n\n\n\n<p>Okok, I am kidding.<\/p>\n\n\n\n<p>I used <a href=\"https:\/\/suche.transparenz.hamburg.de\/dataset\/digitale-orthophotos-belaubt-hamburg3\">https:\/\/suche.transparenz.hamburg.de\/dataset\/digitale-orthophotos-belaubt-hamburg3<\/a> as data source because they have a CC-BY like license, allowing such a project without any legal complications. As a side benefit these images are already provided in tiles: There is not one big image of the whole region but 1km\u00b2 image tiles. Perfect for random selection, quick resizing and posting.<\/p>\n\n\n\n<p>Registering a Twitter account and setting it up is a privacy nightmare and, being a good human being as you are, you ought hate any part of it. I followed the <a href=\"https:\/\/twython.readthedocs.io\/en\/latest\/usage\/starting_out.html#oauth-1-user-authentication\">Twython tutorial for OAuth1<\/a> in a live Python interpreter session which was fairly painless. If you do not want to link a phone number to your Twitter account (see above for how you should feel about that), <a href=\"https:\/\/twittercommunity.com\/t\/how-to-create-an-app-without-mobile\/21135\/18\">this approach<\/a> worked for me in the past but I bet they use regional profiling or worse so your luck might differ.<\/p>\n\n\n\n<p>Next you need some code to do the work for you automatically. Here is what I wrote with <code>Pillow==7.0.0<\/code> for the image processing and <code>twython==3.8.2<\/code> for posting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import glob\nimport random\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom twython import Twython\n\n## Initialise Twitter\n# use a Python interpreter to follow the stops on \n# https:\/\/twython.readthedocs.io\/en\/latest\/usage\/starting_out.html#oauth-1-user-authentication \n# don't rush, there are some intermediate keys iirc...\nAPP_KEY = '1234567890ABCDEFGHIJKLMNO'\nAPP_SECRET = '12345678901234567890123456F8U0CAKATAWAIATATAEARAAA'\nOAUTH_TOKEN = '1234567890123456789123456F8U0CAKATAWAIATATAEARAAAA'\nOAUTH_TOKEN_SECRET = '123456789012345678901234567890FFSFFSFFSFFSFFS'\ntwitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)\n\n## Prepare the image\n# via https:\/\/twython.readthedocs.io\/en\/latest\/usage\/advanced_usage.html#posting-a-status-with-an-editing-image\n\n# Pick the image\njpegs = glob.glob(\"DOP20_HH_sommerbefliegung_2019.zip\/*.jpg\")\ntodays_image = random.choice(jpegs)\nprint(f\"Today we will post {todays_image}\")\nphoto = Image.open(todays_image)\n\n# Resize the image\nbasewidth = 1000\nwpercent = (basewidth \/ float(photo.size&#91;0]))\nheight = int((float(photo.size&#91;1]) * float(wpercent)))\nresized_photo = photo.resize((basewidth, height), Image.ANTIALIAS)\n\n# \"Save\" the resulting image in temporary memory\nstream = BytesIO()\nresized_photo.save(stream, format='JPEG')\nstream.seek(0)\n\n## We've got what we need, let's tweet\nlicense = \"dl-de\/by-2-0 (Freie und Hansestadt Hamburg, Landesbetrieb Geoinformation und Vermessung)\"\ntweet = f\"Das ist #IrgendwoInHH, aber wo denn nur?\\n\\n#codeforhamburg\\n\\nBild: {license}\"\n\nresponse = twitter.upload_media(media=stream)\ntwitter.update_status(status=tweet, media_ids=&#91;response&#91;'media_id']])<\/code><\/pre>\n\n\n\n<p>First we initialize that Twython thingie, then we pick a random image from a directory of .jpg files, then we resize it to a maximum of 1000 pixels (you can simplify that if your images are square&#8230;) and finally we post it to Twitter.<\/p>\n\n\n\n<p>Set up a cronjob or systemd timer or alarm clock to run the script as often as you like and that&#8217;s it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"614\" height=\"513\" src=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-28.png\" alt=\"\" class=\"wp-image-1606\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-28.png 614w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/image-28-300x251.png 300w\" sizes=\"auto, (max-width: 614px) 100vw, 614px\" \/><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>https:\/\/gitlab.com\/Hannes42\/twitter-image-bot About a year ago I built a small Twitter bot that posts an aerial image of Hamburg, Germany every day. As I will shut it down (no reason, just decluttering) here&#8217;s how it works so you can run your own: Have aerial images with a permissive license Register a Twitter account and set it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,27,10,43],"tags":[],"class_list":["post-1603","post","type-post","status-publish","format-standard","hentry","category-guide","category-hamburg","category-open-data","category-python"],"_links":{"self":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1603","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/comments?post=1603"}],"version-history":[{"count":9,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1603\/revisions"}],"predecessor-version":[{"id":1742,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/1603\/revisions\/1742"}],"wp:attachment":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/media?parent=1603"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/categories?post=1603"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/tags?post=1603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}