Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """Move the mouse based on Beam Interactive controls."""
- import asyncio
- from urllib.parse import urljoin
- from getpass import getpass
- from math import isnan
- from beam_interactive import start, proto
- from requests import Session
- URL = "https://beam.pro/api/v1/"
- URL_LOGIN = "https://beam.pro/api/v1/users/login"
- URL_INTERACIVE = "https://beam.pro/api/v1/interactive/{channel}/robot"
- USE_2FA = False
- AUTHENTICATION = {
- "username": "",
- "password": "",
- "code": "" # Unnecessary if two-factor authentication is disabled.
- }
- if AUTHENTICATION['username'] == '':
- AUTHENTICATION['username'] = input("Username : ")
- if AUTHENTICATION['password'] == '':
- AUTHENTICATION['password'] = getpass("Password : ")
- if USE_2FA:
- while not ((len(AUTHENTICATION['code']) == 6) or
- any(c.isalpha() for c in AUTHENTICATION['code'])):
- AUTHENTICATION['code'] = input("2FA code : ")
- if (len(AUTHENTICATION['code']) < 6) or (len(AUTHENTICATION['code']) > 6):
- print("ERROR: 2FA Code must be 6 characters long")
- if any(c.isalpha() for c in AUTHENTICATION['code']):
- print("ERROR: 2FA Code MUST NOT contain letters or special characters")
- SESSION = Session()
- def _build(endpoint, *, url=URL):
- """Build an address for an API endpoint."""
- return urljoin(url, endpoint.lstrip('/'))
- def login(username, password, code='', *, session=SESSION, url=URL_LOGIN):
- """Log into Beam via the API."""
- auth = dict(username=username, password=password, code=code)
- return session.post(url, data=auth).json()
- def join_interactive(channel, *, session=SESSION, url=URL_INTERACIVE):
- """Retrieve interactive connection information."""
- return session.get(url.format(channel=channel)).json()
- def on_error(error):
- """Handle error packets."""
- print("Oh no, there was an error!", error.message)
- def on_report(report):
- """Handle report packets."""
- # Tactile Mouse Click Control
- for tactile in report.tactile:
- if tactile.pressFrequency:
- print("Tactile report received!", tactile, sep='\n')
- # Joystick Mouse Movement Control
- for joystick in report.joystick:
- if not isnan(joystick.coordMean.x) and not isnan(joystick.coordMean.y):
- print("Joystick report received!", joystick, sep='\n')
- @asyncio.coroutine
- def run():
- """Run the interactive app."""
- # Authenticate with Beam and retrieve the channel id from the response.
- channel_id = login( # **AUTHENTICATION is a cleaner way of doing this.
- AUTHENTICATION["username"],
- AUTHENTICATION["password"],
- AUTHENTICATION["code"]
- )["channel"]["id"]
- # Get Interactive connection information.
- data = join_interactive(channel_id)
- # Initialize a connection with Interactive.
- connection = yield from start(data["address"], channel_id, data["key"])
- # Handlers, to be called when Interactive packets are received.
- handlers = {
- proto.id.error: on_error,
- proto.id.report: on_report
- }
- # wait_message is a coroutine that will return True when it receives
- # a complete packet from Interactive, or False if we got disconnected.
- while (yield from connection.wait_message()):
- # Decode the Interactive packet.
- decoded, _ = connection.get_packet()
- packet_id = proto.id.get_packet_id(decoded)
- # Handle the packet with the proper handler, if its type is known.
- if packet_id in handlers:
- handlers[packet_id](decoded)
- elif decoded is None:
- print("Unknown bytes were received. Uh oh!", packet_id)
- else:
- print("We got packet {} but didn't handle it!".format(packet_id))
- connection.close()
- if __name__ == "__main__":
- loop = asyncio.get_event_loop()
- try:
- loop.run_until_complete(run())
- finally:
- loop.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement