#!/usr/bin/env -S python3 -u # Copyright 2019 The Matrix.org Foundation CIC # # 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 # # http://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. import asyncio import socket import json from random import choice from aiohttp import web # The browsers ban some known ports, the dynamic port range doesn't contain any # banned ports, so we use that. port_range = range(49152, 65535) shutdown_task = None def to_weechat(message): print(json.dumps(message)) async def get_token(request): global shutdown_task async def shutdown(): await asyncio.sleep(1) raise KeyboardInterrupt token = request.query.get("loginToken") if not token: raise KeyboardInterrupt message = { "type": "token", "loginToken": token } # Send the token to weechat. print(json.dumps(message)) # Initiate a shutdown. shutdown_task = asyncio.ensure_future(shutdown()) # Respond to the browser. return web.Response(text="Continuing in Weechat.") def bind_socket(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) while True: port = choice(port_range) try: sock.bind(("localhost", port)) except OSError: continue return sock async def wait_for_shutdown_task(_): if not shutdown_task: return try: await shutdown_task except KeyboardInterrupt: pass def main(): app = web.Application() app.add_routes([web.get('/', get_token)]) sock = bind_socket() host, port = sock.getsockname() message = { "type": "redirectUrl", "host": host, "port": port } to_weechat(message) app.on_shutdown.append(wait_for_shutdown_task) web.run_app(app, sock=sock, handle_signals=True, print=None) if __name__ == "__main__": main()