juftin / camply

camply, the campsite finder ⛺️ - a tool to find campsites at sold out campgrounds through sites like recreation.gov
https://juftin.com/camply/
MIT License
464 stars 89 forks source link

πŸ› Specify utf-8 webhook encoding #299

Closed zdwolfe closed 11 months ago

zdwolfe commented 11 months ago

Description

Fixes https://github.com/juftin/camply/issues/302

Specify utf-8 body encoding on webhook requests. The emojis in campsites json body cannot be encoded with latin-1 encoding and camply crashes. The utf-8 encoding is the json spec character encoding, so it seems like an OK default stance for camply to take.

JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8

Before

 WEBHOOK_URL="http://localhost:8000" camply campsites --campground 233998 --start-date 2023-10-10 --end-date 2023-10-21  --notifications webhook

..would crash with

RuntimeError: camply encountered an error and exited 😟 [2023-09-14 22:13:53] - (UnicodeEncodeError) 'latin-1' codec
can't encode character '\U0001f3d5' in position 161: Body ('πŸ•') is not valid Latin-1. Use body.encode('utf-8') if you
want to send it encoded in UTF-8.

Has This Been Tested?

In background shell, start a simple webhook handler

from http.server import BaseHTTPRequestHandler, HTTPServer
import socketserver

class PostHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        print('request')
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        print(post_data.decode('utf-8'))

        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'OK')

if __name__ == "__main__":
    PORT = 8000
    with HTTPServer(("", PORT), PostHandler) as httpd:
        print("serving at port", PORT)
        httpd.serve_forever()
(camply) (base) zach@z-pc:~/src/camply$ git log --oneline | head -n 1
f3b51ae πŸ› Specify utf-8 webhook encoding

then run:

(camply) (base) zach@z-pc:~/src/camply$ hatch shell
(camply) (base) zach@z-pc:~/src/camply$ WEBHOOK_URL="http://localhost:8000" camply campsites --campground 233998 --start-date 2023-10-10 --end-date 2023-10-21  --notifications webhook

..and the webhook handler prints:

127.0.0.1 - - [14/Sep/2023 22:17:15] "POST / HTTP/1.1" 200 -
request
{"campsites": [{"campsite_id": 76540, "booking_date": "2023-10-12T00:00:00",
......

..also,

(camply) (base) zach@z-pc:~/src/camply$ hatch run all
...
-------------------------------------------------------------------------------------------------------
TOTAL                                                        3895    627    956    139    81%

...
108 passed in 30.67s 
...

Checklist:

(also, this is the first GitHub PR I've ever made, so apologies if something's not quite right).

juftin commented 11 months ago

Nice, so this works @zdwolfe but I was thinking of a different approach.

The actual message that broke the utf-8 encoding wasn't a standard webhook body, it was a text message sent by send_message. Something like this:

Found more than 5 matching campsites (16) on the first try. Try searching online instead. camply is only sending the first 5 notifications. Go Get your campsite! πŸ•
image

I'm wondering if we should be disabling send_message altogether with a no-op and only enabling send_campsites. This way the ony messages that get sent to the webhook are valid JSON campsites. We can also ensure utf-8 encoding while we're at it too.

Let me know what you think?

zdwolfe commented 11 months ago

Oh, I see! Disabling send_message sounds good to me, though I also agree utf-8 might be worth keeping around.

juftin commented 11 months ago

Resolved by #303