sample-code/python/main.py (51 lines of code) (raw):

# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This is a minimal starting app for receiving and sending Pub/Sub messages from # and to the Next 2024 Pinball game, and is used in the Pinball Python Codelab. # Receiving messages via push subscriptions does not require knowing where they # come from. Sending message back does requiring identifying the topic to use. PROJECT_ID = "backlogged-dev" TOPIC_ID = "pinball-reactions" import base64 # Used to decode Pub/Sub message data import json # Used to flatten dicts to strings import os # Used to determine the server port to listen on from flask import Flask, request # Python web framework from google.cloud import pubsub_v1 as pubsub # For publishing messages app = Flask(__name__) # Instantiate the web server @app.route('/', methods=["POST"]) # Receive Pub/Sub push messages (HTTP POST to "/") def receive_push_messages(): # Pub/Sub push subscriptions deliver messages through regular HTTP POST # requests, with a JSON body. request_body = request.get_json(silent=True) # Returns None if not JSON # This app is intended only to receive Pub/Sub push messages. Reject any # HTTP POST request that is not a properly formed Pub/Sub push message. if request_body is None: print("ERROR: Not JSON") # Log the issue return "Unsupported Media Type", 415 # Non-2XX notifies error to the sender if not isinstance(request_body, dict) or "message" not in request_body: print("ERROR: Not PubSub") # Log the issue return "Bad Request", 400 # Non-2XX notifies error to the sender # The request_body seems to a properly formed Pub/Sub message. The message # itself is a field called "message". message = request_body["message"] # The data portion of the message is base64-encoded. Decode it. data = message.get("data", "") # Empty string if missing body = base64.b64decode(data).decode("utf-8") # b64decode returns bytes # Log the decoded data to check if it was correctly received. print(f"DEBUG: decoded data = '{body}'") # The body can be any string. For the Pinball game, the body will always # be a JSON string, usually containing several data fields. # There are a number of other fields in the message that can convey # information, some of which are essential to understanding the Pinball # event. # See https://cloud.google.com/pubsub/docs for more information on # the structure and contents of Pub/Sub messages in general. # See the end of the codelab for specifications of the Pinball message format. # Determine whether you want the send a message back to the Pinball machine. # For most events you will not want to do this to avoid spamming the # machine. You will be given suggestions of events worth responding to, # such as a completed game with a new high score, or longest duration. if False: # replace with condition that should trigger a response result = send_response( reaction_type="DisplayMessage", machine_id="GBL:1", data={"MessageKey": "LUCKY"} ) print(f"Result of sending message is {result}.") # Acknowledge the message to prevent retries. return "OK", 200 # Your code can also send messages to the Pinball machine that affect what it is # displaying. This function is not triggered in response to an incoming event, # but is called when processing an incoming message that calls for a response. # For example, when a game with a new high score ends. def send_response(reaction_type="valid reaction", machine_id="valid ID", data=""): # return False # You will be replacing this function body with a working one print("Target Project ID: "+PROJECT_ID) print("Topic ID: "+TOPIC_ID) publisher = pubsub.PublisherClient() topic_path = f"projects/{PROJECT_ID}/topics/{TOPIC_ID}" message_data = json.dumps(data).encode("utf-8") message = { "data": message_data, "attributes": { "PinballReactionType": reaction_type, "MachineId": machine_id } } try: future = publisher.publish(topic_path, message['data'], **message['attributes']) message_id = future.result() print(f"Message {message_id} published successfully") except Exception as e: print(f"Error publishing message: {str(e)}") # Cloud Run and other platforms will often run this program as a module in a # preferred web server application. If this file is run as a stand-alone # application, it needs to start its own web server. if __name__ == '__main__': server_port = os.environ.get('PORT', '8080') app.run(debug=False, port=server_port, host='0.0.0.0')